Fix grapheme_position when ligatures are present

This commit is contained in:
Héctor Ramón Jiménez 2024-01-11 08:29:44 +01:00
parent 68c0484b5c
commit 9c50a7ed7e
No known key found for this signature in database
GPG key ID: 7CC46565708259A7

View file

@ -187,38 +187,43 @@ impl core::text::Paragraph for Paragraph {
}
fn grapheme_position(&self, line: usize, index: usize) -> Option<Point> {
use unicode_segmentation::UnicodeSegmentation;
let run = self.internal().buffer.layout_runs().nth(line)?;
// index represents a grapheme, not a glyph
// Let's find the first glyph for the given grapheme cluster
let mut last_start = None;
let mut last_grapheme_count = 0;
let mut graphemes_seen = 0;
let glyph = run
.glyphs
.iter()
.find(|glyph| {
if graphemes_seen == index {
return true;
}
if Some(glyph.start) != last_start {
last_grapheme_count = run.text[glyph.start..glyph.end]
.graphemes(false)
.count();
last_start = Some(glyph.start);
graphemes_seen += 1;
graphemes_seen += last_grapheme_count;
}
false
graphemes_seen >= index
})
.or_else(|| run.glyphs.last())?;
let advance_last = if index == run.glyphs.len() {
glyph.w
} else {
let advance = if index == 0 {
0.0
} else {
glyph.w
* (1.0
- graphemes_seen.saturating_sub(index) as f32
/ last_grapheme_count as f32)
};
Some(Point::new(
glyph.x + glyph.x_offset * glyph.font_size + advance_last,
glyph.x + glyph.x_offset * glyph.font_size + advance,
glyph.y - glyph.y_offset * glyph.font_size,
))
}