diff --git a/parley/src/layout/cursor.rs b/parley/src/layout/cursor.rs index a60784c2..a405ca8b 100644 --- a/parley/src/layout/cursor.rs +++ b/parley/src/layout/cursor.rs @@ -799,10 +799,7 @@ impl Selection { /// This avoids allocation if the intent is to render the rectangles /// immediately. pub fn geometry_with(&self, layout: &Layout, mut f: impl FnMut(Rect)) { - // Ensure we add some visual indicator for selected empty - // lines. - // Make this configurable? - const MIN_RECT_WIDTH: f64 = 8.0; + const NEWLINE_WHITESPACE_WIDTH_RATIO: f64 = 0.25; if self.is_collapsed() { return; } @@ -824,6 +821,17 @@ impl Selection { let metrics = line.metrics(); let line_min = metrics.min_coord as f64; let line_max = metrics.max_coord as f64; + // Trailing whitespace to indicate that the newline character at the + // end of this line is selected. It's based on the ascent and + // descent so it doesn't change with the line height. + // + // TODO: the width of this whitespace should be the width of a space + // (U+0020) character. + let newline_whitespace = if line.break_reason() == BreakReason::Explicit { + (metrics.ascent as f64 + metrics.descent as f64) * NEWLINE_WHITESPACE_WIDTH_RATIO + } else { + 0.0 + }; if line_ix == line_start_ix || line_ix == line_end_ix { // We only need to run the expensive logic on the first and // last lines @@ -838,22 +846,29 @@ impl Selection { cur_x += advance; } else { if cur_x != start_x { - let width = (cur_x - start_x).max(MIN_RECT_WIDTH); - f(Rect::new(start_x, line_min, start_x + width, line_max)); + f(Rect::new(start_x, line_min, cur_x, line_max)); } cur_x += advance; start_x = cur_x; } } } - if cur_x != start_x || (cluster_count != 0 && line.metrics().advance == 0.0) { - let width = (cur_x - start_x).max(MIN_RECT_WIDTH); - f(Rect::new(start_x, line_min, start_x + width, line_max)); + let mut end_x = cur_x; + if line_ix != line_end_ix || (cluster_count != 0 && metrics.advance == 0.0) { + end_x += newline_whitespace; + } + if end_x != start_x { + f(Rect::new(start_x, line_min, end_x, line_max)); } } else { let x = metrics.offset as f64; - let width = (metrics.advance as f64).max(MIN_RECT_WIDTH); - f(Rect::new(x, line_min, x + width, line_max)); + let width = metrics.advance as f64; + f(Rect::new( + x, + line_min, + x + width + newline_whitespace, + line_max, + )); } } } diff --git a/parley/tests/snapshots/editor_select_all-0.png b/parley/tests/snapshots/editor_select_all-0.png index af59cc7d..16bdc74a 100644 --- a/parley/tests/snapshots/editor_select_all-0.png +++ b/parley/tests/snapshots/editor_select_all-0.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:efa4d5e92e23176c9449a626781b958a04b60bfec28bc9078fa24dc4ef6375ab -size 3088 +oid sha256:d2450c54c1e8be7d03098e3afef6223624a44261c1b37e9a904a466a03d2b30e +size 3147