diff options
| author | Laurenz <laurmaedje@gmail.com> | 2024-10-12 14:01:34 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-12 12:01:34 +0000 |
| commit | 8b6f7298e3b09faf2f23112368d440fb0889da42 (patch) | |
| tree | 14db9003be3a859fc27c7d124c3e39e6744d2fda /crates | |
| parent | 61d461f0800c22afd2c279786d326733f679a36d (diff) | |
Fix outline with CJK text (#5187)
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/typst/src/model/outline.rs | 31 | ||||
| -rw-r--r-- | crates/typst/src/text/mod.rs | 10 |
2 files changed, 24 insertions, 17 deletions
diff --git a/crates/typst/src/model/outline.rs b/crates/typst/src/model/outline.rs index b90c4e3b..5bf2407b 100644 --- a/crates/typst/src/model/outline.rs +++ b/crates/typst/src/model/outline.rs @@ -10,7 +10,9 @@ use crate::foundations::{ NativeElement, Packed, Show, ShowSet, Smart, StyleChain, Styles, }; use crate::introspection::{Counter, CounterKey, Locatable}; -use crate::layout::{BoxElem, Em, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing}; +use crate::layout::{ + BoxElem, Dir, Em, Fr, HElem, HideElem, Length, Rel, RepeatElem, Spacing, +}; use crate::model::{ Destination, HeadingElem, NumberingPattern, ParElem, ParbreakElem, Refable, }; @@ -499,12 +501,27 @@ impl Show for Packed<OutlineEntry> { } }; - // The body text remains overridable. - crate::text::isolate( - self.body().clone().linked(Destination::Location(location)), - styles, - &mut seq, - ); + // Isolate the entry body in RTL because the page number is typically + // LTR. I'm not sure whether LTR should conceptually also be isolated, + // but in any case we don't do it for now because the text shaping + // pipeline does tend to choke a bit on default ignorables (in + // particular the CJK-Latin spacing). + // + // See also: + // - https://github.com/typst/typst/issues/4476 + // - https://github.com/typst/typst/issues/5176 + let rtl = TextElem::dir_in(styles) == Dir::RTL; + if rtl { + // "Right-to-Left Embedding" + seq.push(TextElem::packed("\u{202B}")); + } + + seq.push(self.body().clone().linked(Destination::Location(location))); + + if rtl { + // "Pop Directional Formatting" + seq.push(TextElem::packed("\u{202C}")); + } // Add filler symbols between the section name and page number. if let Some(filler) = self.fill() { diff --git a/crates/typst/src/text/mod.rs b/crates/typst/src/text/mod.rs index 53163e18..5b35d60c 100644 --- a/crates/typst/src/text/mod.rs +++ b/crates/typst/src/text/mod.rs @@ -1284,16 +1284,6 @@ pub(crate) fn is_default_ignorable(c: char) -> bool { DEFAULT_IGNORABLE_DATA.as_borrowed().contains(c) } -/// Pushes `text` wrapped in LRE/RLE + PDF to `out`. -pub(crate) fn isolate(text: Content, styles: StyleChain, out: &mut Vec<Content>) { - out.push(TextElem::packed(match TextElem::dir_in(styles) { - Dir::RTL => "\u{202B}", - _ => "\u{202A}", - })); - out.push(text); - out.push(TextElem::packed("\u{202C}")); -} - /// Checks for font families that are not available. fn check_font_list(engine: &mut Engine, list: &Spanned<FontList>) { let book = engine.world.book(); |
