From d867d7b58af8e7f121684f81a0f834ed31da69b5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 30 Jul 2021 15:55:08 +0200 Subject: [PATCH] Fix rendering of text selection with combining characters with the GL backend When the text selection end follows right after a grapheme that uses less glyphs than characters, then there may not be a matching glyph with the byte index, therefore we wouldn't set the selection_end_x and draw incorrectly. Take the visual tail of the last glyph then. --- sixtyfps_runtime/rendering_backends/gl/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sixtyfps_runtime/rendering_backends/gl/lib.rs b/sixtyfps_runtime/rendering_backends/gl/lib.rs index e14ed113b..8b93cacf0 100644 --- a/sixtyfps_runtime/rendering_backends/gl/lib.rs +++ b/sixtyfps_runtime/rendering_backends/gl/lib.rs @@ -743,13 +743,19 @@ impl ItemRenderer for GLItemRenderer { let (anchor_pos, cursor_pos) = text_input.selection_anchor_and_cursor(); let mut selection_start_x = 0.; let mut selection_end_x = 0.; + // Determine the first and last (inclusive) glyph of the selection. The anchor + // will always be at the start of a grapheme boundary, so there's at ShapedGlyph + // that has a matching byte index. For the selection end we have to look for the + // visual end of glyph before the cursor, because due to for example ligatures + // (or generally glyph substitution) there may not be a dedicated glyph. for glyph in &metrics.glyphs { if glyph.byte_index == anchor_pos { selection_start_x = glyph.x; } - if glyph.byte_index == (cursor_pos as i32 - 1).max(0) as usize { - selection_end_x = glyph.x + glyph.advance_x; + if glyph.byte_index == cursor_pos { + break; } + selection_end_x = glyph.x + glyph.advance_x; } let selection_rect = Rect::new(