From 10eff1d6d5aa9835150d2f3bd9dda9359d453b16 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Thu, 3 Oct 2024 18:16:44 +0200 Subject: [PATCH] Tweak default ignorable fix (#5105) --- crates/typst-pdf/src/content.rs | 4 ++-- crates/typst/src/layout/place.rs | 4 ++-- crates/typst/src/text/item.rs | 32 +++++++++++++------------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/crates/typst-pdf/src/content.rs b/crates/typst-pdf/src/content.rs index 4f2baafb9..79323b6a0 100644 --- a/crates/typst-pdf/src/content.rs +++ b/crates/typst-pdf/src/content.rs @@ -493,7 +493,7 @@ fn write_normal_text( let glyph_set = ctx.resources.glyph_sets.entry(text.item.font.clone()).or_default(); for g in text.glyphs() { - glyph_set.entry(g.id).or_insert_with(|| text.glyph_text(&g)); + glyph_set.entry(g.id).or_insert_with(|| text.glyph_text(g)); } let fill_transform = ctx.state.transforms(Size::zero(), pos); @@ -638,7 +638,7 @@ fn write_color_glyphs( ctx.content.show(Str(&[index])); - glyph_set.entry(glyph.id).or_insert_with(|| text.glyph_text(&glyph)); + glyph_set.entry(glyph.id).or_insert_with(|| text.glyph_text(glyph)); } ctx.content.end_text(); diff --git a/crates/typst/src/layout/place.rs b/crates/typst/src/layout/place.rs index ce13a0c96..67b50926d 100644 --- a/crates/typst/src/layout/place.rs +++ b/crates/typst/src/layout/place.rs @@ -46,7 +46,7 @@ use crate::layout::{Alignment, Em, Length, Rel}; /// you can wrap the `place` call in a [`box`] when the call is made /// in the middle of a paragraph. The alignment and offsets will then be /// relative to this zero-size box. To make sure it doesn't interfere with -/// spacing, the box should be attached to a word using a zero-width joiner. +/// spacing, the box should be attached to a word using a word joiner. /// /// For example, the following defines a function for attaching an annotation /// to the following word: @@ -55,7 +55,7 @@ use crate::layout::{Alignment, Em, Length, Rel}; /// >>> #set page(height: 70pt) /// #let annotate(..args) = { /// box(place(..args)) -/// sym.zwj +/// sym.wj /// h(0pt, weak: true) /// } /// diff --git a/crates/typst/src/text/item.rs b/crates/typst/src/text/item.rs index f6044b2f3..b2f9e272c 100644 --- a/crates/typst/src/text/item.rs +++ b/crates/typst/src/text/item.rs @@ -89,33 +89,27 @@ impl<'a> TextItemView<'a> { /// Returns an iterator over the glyphs of the slice. /// - /// The range of text that each glyph represents is remapped to be relative - /// to the start of the slice. - pub fn glyphs(&self) -> impl Iterator + '_ { - let first = self.item.glyphs[self.glyph_range.start].range(); - let last = self.item.glyphs[self.glyph_range.end - 1].range(); - let base = first.start.min(last.start) as u16; - (0..self.glyph_range.len()).map(move |index| { - let g = &self.item.glyphs[self.glyph_range.start + index]; - Glyph { - range: g.range.start - base..g.range.end - base, - ..*g - } - }) + /// Note that the ranges are not remapped. They still point into the + /// original text. + pub fn glyphs(&self) -> &[Glyph] { + &self.item.glyphs[self.glyph_range.clone()] } - /// The plain text for the given glyph. This is an approximation since - /// glyphs do not correspond 1-1 with codepoints. + /// The plain text for the given glyph from `glyphs()`. This is an + /// approximation since glyphs do not correspond 1-1 with codepoints. pub fn glyph_text(&self, glyph: &Glyph) -> EcoString { + // Trim default ignorables which might have ended up in the glyph's + // cluster. Keep interior ones so that joined emojis work. All of this + // is a hack and needs to be reworked. See + // https://github.com/typst/typst/pull/5099 self.item.text[glyph.range()] - .chars() - .filter(|&c| !is_default_ignorable(c)) - .collect() + .trim_matches(is_default_ignorable) + .into() } /// The total width of this text slice pub fn width(&self) -> Abs { - self.item.glyphs[self.glyph_range.clone()] + self.glyphs() .iter() .map(|g| g.x_advance) .sum::()