From 28d41d436313152ace3cfb68b4679affb307ef8f Mon Sep 17 00:00:00 2001 From: alex-ds13 <145657253+alex-ds13@users.noreply.github.com> Date: Tue, 25 Nov 2025 18:43:51 +0000 Subject: fix: select graphemes with multi codepoints properly - We continue to use the graphemes index for the selection ends, however when calculating the selection rectangles we now check if the visual line had any glyph with `start` and `end` index bigger than 1 before or within the range and update the range accordingly. This way all the code that checks for word boundaries when selecting by words still functions properly. --- src/text/rich.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'src/text/rich.rs') diff --git a/src/text/rich.rs b/src/text/rich.rs index 060ab26..22be56d 100644 --- a/src/text/rich.rs +++ b/src/text/rich.rs @@ -977,7 +977,7 @@ fn highlight_line( .map(|glyph| glyph.end) .unwrap_or(0); - let range = start.max(from)..end.min(to); + let mut range = start.max(from)..end.min(to); let x_offset = visual_line .glyphs @@ -990,21 +990,31 @@ fn highlight_line( } else if range.start == start && range.end == end { (x_offset, visual_line.w) } else { - let first_glyph = visual_line - .glyphs - .iter() - .position(|glyph| range.start <= glyph.start) - .unwrap_or(0); - - let mut glyphs = visual_line.glyphs.iter(); + let mut x = 0.0; + let mut width = 0.0; + for glyph in &visual_line.glyphs { + let glyph_count = glyph.start.abs_diff(glyph.end); + + // Check for multi codepoint glyphs before or within the range + if glyph_count > 1 { + if range.start > glyph.start { + range.start += glyph_count - 1; + range.end += glyph_count - 1; + } else if range.end > glyph.start { + range.end += glyph_count - 1; + } + } - let x: f32 = - glyphs.by_ref().take(first_glyph).map(|glyph| glyph.w).sum(); + if range.start > glyph.start { + x += glyph.w; + } - let width: f32 = glyphs - .take_while(|glyph| range.end > glyph.start) - .map(|glyph| glyph.w) - .sum(); + if range.start <= glyph.start && range.end > glyph.start { + width += glyph.w; + } else if range.end <= glyph.start { + break; + } + } (x_offset + x, width) } -- cgit v1.2.3