summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-10-12 14:01:34 +0200
committerLaurenz <laurmaedje@gmail.com>2024-10-15 15:06:36 +0200
commite7d88b3ac74852c2df15188156e10dad4fddcdd2 (patch)
treea6e50f9f043d106b60c19a7731cfda3e2e3b4421
parent2a956bb88f073db8d7a462dadb51a213e5ceabf3 (diff)
Fix outline with CJK text (#5187)
-rw-r--r--crates/typst/src/model/outline.rs31
-rw-r--r--crates/typst/src/text/mod.rs10
-rw-r--r--tests/ref/issue-5176-cjk-title.pngbin0 -> 1246 bytes
-rw-r--r--tests/suite/model/outline.typ9
4 files changed, 33 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();
diff --git a/tests/ref/issue-5176-cjk-title.png b/tests/ref/issue-5176-cjk-title.png
new file mode 100644
index 00000000..e904fbd7
--- /dev/null
+++ b/tests/ref/issue-5176-cjk-title.png
Binary files differ
diff --git a/tests/suite/model/outline.typ b/tests/suite/model/outline.typ
index 3c134760..18c61df8 100644
--- a/tests/suite/model/outline.typ
+++ b/tests/suite/model/outline.typ
@@ -171,3 +171,12 @@ A
= הוקוס Pocus
= זוהי כותרת שתורגמה על ידי מחשב
+
+--- issue-5176-cjk-title ---
+#set text(font: "Noto Serif CJK SC")
+#show heading: none
+
+#outline(title: none)
+
+= 测
+= 很