diff options
| author | Peng Guanwen <pg999w@outlook.com> | 2023-11-07 04:43:15 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-11-06 21:43:15 +0100 |
| commit | 4a7d3585d9baff43a74a802f58ab8dc4d16ff222 (patch) | |
| tree | 4420ff4594dedcbe3843df5bd5b656fcf77278d5 /crates/typst-library/src/text | |
| parent | e550f0a8f726bf2696390e5f91df4c638888a990 (diff) | |
Improve reshape condition (#2547)
Diffstat (limited to 'crates/typst-library/src/text')
| -rw-r--r-- | crates/typst-library/src/text/shaping.rs | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/crates/typst-library/src/text/shaping.rs b/crates/typst-library/src/text/shaping.rs index f7cf90bd..05ed4633 100644 --- a/crates/typst-library/src/text/shaping.rs +++ b/crates/typst-library/src/text/shaping.rs @@ -488,17 +488,35 @@ impl<'a> ShapedText<'a> { } // Find any glyph with the text index. - let mut idx = self - .glyphs - .binary_search_by(|g| { - let ordering = g.range.start.cmp(&text_index); - if ltr { - ordering - } else { - ordering.reverse() - } - }) - .ok()?; + let found = self.glyphs.binary_search_by(|g: &ShapedGlyph| { + let ordering = g.range.start.cmp(&text_index); + if ltr { + ordering + } else { + ordering.reverse() + } + }); + let mut idx = match found { + Ok(idx) => idx, + Err(idx) => { + // Handle the special case where we break before a '\n' + // + // For example: (assume `a` is a CJK character with three bytes) + // text: " a \n b " + // index: 0 1 2 3 4 5 + // text_index: ^ + // glyphs: 0 . 1 + // + // We will get found = Err(1), because '\n' does not have a glyph. + // But it's safe to break here. Thus the following condition: + // - glyphs[0].end == text_index == 3 + // - text[3] == '\n' + return (idx > 0 + && self.glyphs[idx - 1].range.end == text_index + && self.text[text_index - self.base..].starts_with('\n')) + .then_some(idx); + } + }; let next = match towards { Side::Left => usize::checked_sub, |
