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