aboutsummaryrefslogtreecommitdiff
path: root/src/text.rs
diff options
context:
space:
mode:
authoralex-ds13 <145657253+alex-ds13@users.noreply.github.com>2025-11-25 18:43:51 +0000
committerPolesznyák Márk <contact@pml68.dev>2026-02-05 14:36:32 +0100
commit28d41d436313152ace3cfb68b4679affb307ef8f (patch)
treee9209dc4d52d266e65a4ee9817960af278069cf2 /src/text.rs
parentfix: outbounds selecting when inside a scrollable (diff)
downloadiced_selection-28d41d436313152ace3cfb68b4679affb307ef8f.tar.gz
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.
Diffstat (limited to '')
-rw-r--r--src/text.rs38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/text.rs b/src/text.rs
index ffd5ea2..9c132ad 100644
--- a/src/text.rs
+++ b/src/text.rs
@@ -830,7 +830,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
@@ -843,21 +843,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)
}