From 8b6f7298e3b09faf2f23112368d440fb0889da42 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 12 Oct 2024 14:01:34 +0200 Subject: [PATCH] Fix outline with CJK text (#5187) --- crates/typst/src/model/outline.rs | 31 ++++++++++++++++++++++------- crates/typst/src/text/mod.rs | 10 ---------- tests/ref/issue-5176-cjk-title.png | Bin 0 -> 1246 bytes tests/suite/model/outline.typ | 9 +++++++++ 4 files changed, 33 insertions(+), 17 deletions(-) create mode 100644 tests/ref/issue-5176-cjk-title.png diff --git a/crates/typst/src/model/outline.rs b/crates/typst/src/model/outline.rs index b90c4e3b6..5bf2407bf 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 { } }; - // 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 53163e186..5b35d60cd 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) { - 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) { let book = engine.world.book(); diff --git a/tests/ref/issue-5176-cjk-title.png b/tests/ref/issue-5176-cjk-title.png new file mode 100644 index 0000000000000000000000000000000000000000..e904fbd77fda62699875a57c168ea58d2b1c2db1 GIT binary patch literal 1246 zcmV<41R?v0P);3)x=H}+Pxw-iG_~_{9z{1MY)6=rDvMTo0^)M zIyyQnEiGAFV?jYd;NalS&dzprcAlP|-QC}Ugp8q~p@oN!tE;PheSQ1;`>n05uCA`G zuCP#0Qha`fe}RdCfq^M0DZRbDb8~aFw6r!hHsa#qx3{-BIXUU+=~-D>jg5`!>g+#1 zLBhhqSXfw-lat%q+rq@m;o;%U&CL!D4&2<_$;r#h%gwH^xNU81d3kxv&em;jcdxOz zQdC@ohK|(K)UdL;WM*#8(Acf7x3#yws;snTXmGy3$Y*JBXlim^U}%nzn3~cpp;}yIqNJ>Se}_m&O2ELvu&}a`lbgA_!+3gvUS437mY&GU(#*`v z8X6iQBP+49yVlm$K0ZEygNtctY4P##xVX5%!NFHoSG>N)DJwIeprE3nqH1btnw+Fg zP*_S#RGy%yOG`_%w!X^B%+S!%I66X5Qd*CZnYg;b!^O?m+Tz;W!2ng-%?J_bl>gwwJ{QTwRHAC3-YwThxuP(g8md+)vXmWq4ty>Kh;y%&fI zZ2`fe;#N?ER~{|*rrSu3n- zvzj7&DBHSj_0sT%?FWUkz$tpG7XBC_EDngXIp^jHB^=!bPi+ma-_R!sSFNAB)%5Ja zhxZasE7-D`_^xpM8bhbDeJ93IqZyI$mz11@p-!4oFX1b_cR$WTFyvFG&&VZn=S-Ri z7}~;ji4KuOwa54a?$pq&JKlFtUCGvMc%tEU1o6|@u?t4(m^q`NG+7^zsCsTPnR*c% zNxMY4=-F~76tY~dvQ^i!_(WDMY*_f;-n+YVWEWck0_tBbQg@XW;1>Qb&}^FsdI8b!sjf!a^WIDF{H*kiiHOc0k;c&fnJABuT10I z_`g9E#7ZPoLZotTd5~h2*NHI=C0D%!9=%@g)h=lb4UI@~07*qo IM6N<$f|j