summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorPeng Guanwen <pg999w@outlook.com>2023-11-07 04:43:15 +0800
committerGitHub <noreply@github.com>2023-11-06 21:43:15 +0100
commit4a7d3585d9baff43a74a802f58ab8dc4d16ff222 (patch)
tree4420ff4594dedcbe3843df5bd5b656fcf77278d5 /crates
parente550f0a8f726bf2696390e5f91df4c638888a990 (diff)
Improve reshape condition (#2547)
Diffstat (limited to 'crates')
-rw-r--r--crates/typst-library/src/text/shaping.rs40
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,