diff --git a/parley/src/layout/cluster.rs b/parley/src/layout/cluster.rs index 9504dd6c..cad4fcdb 100644 --- a/parley/src/layout/cluster.rs +++ b/parley/src/layout/cluster.rs @@ -21,8 +21,8 @@ impl<'a, B: Brush> Cluster<'a, B> { let mut path = ClusterPath::default(); if let Some((line_index, line)) = layout.line_for_byte_index(byte_index) { path.line_index = line_index as u32; - for (run_index, run) in line.runs().enumerate() { - path.run_index = run_index as u32; + for run in line.runs() { + path.run_index = run.index; if !run.text_range().contains(&byte_index) { continue; } @@ -44,13 +44,17 @@ impl<'a, B: Brush> Cluster<'a, B> { path.line_index = line_index as u32; let mut offset = line.metrics().offset; let last_run_index = line.len().saturating_sub(1); - for (run_index, run) in line.runs().enumerate() { + for run_index in 0..line.len() { + let advance = line.item(run_index).unwrap().advance; + let Some(run) = line.run(run_index) else { + offset += advance; + continue; + }; let is_last_run = run_index == last_run_index; - let run_advance = run.advance(); path.run_index = run_index as u32; path.logical_index = 0; - if x > offset + run_advance && !is_last_run { - offset += run_advance; + if x > offset + advance && !is_last_run { + offset += advance; continue; } let last_cluster_index = run.cluster_range().len().saturating_sub(1); @@ -354,16 +358,15 @@ impl<'a, B: Brush> Cluster<'a, B> { pub fn visual_offset(&self) -> Option { let line = self.path.line(self.run.layout)?; let mut offset = line.metrics().offset; - for run_index in 0..=self.path.run_index() { - let run = line.run(run_index)?; - if run_index != self.path.run_index() { - offset += run.advance(); - } else { - let visual_index = run.logical_to_visual(self.path.logical_index())?; - for cluster in run.visual_clusters().take(visual_index) { - offset += cluster.advance(); - } - } + for run_index in 0..self.path.run_index() { + let item = line.item(run_index)?; + offset += item.advance; + } + + let run = line.run(self.path.run_index())?; + let visual_index = run.logical_to_visual(self.path.logical_index())?; + for cluster in run.visual_clusters().take(visual_index) { + offset += cluster.advance(); } Some(offset) } diff --git a/parley/src/layout/cursor.rs b/parley/src/layout/cursor.rs index d25c1d6f..d685e335 100644 --- a/parley/src/layout/cursor.rs +++ b/parley/src/layout/cursor.rs @@ -5,7 +5,9 @@ #[cfg(feature = "accesskit")] use super::LayoutAccessibility; -use super::{Affinity, BreakReason, Brush, Cluster, ClusterSide, Layout, Line}; +use super::{ + Affinity, BreakReason, Brush, Cluster, ClusterSide, Layout, Line, PositionedLayoutItem, +}; #[cfg(feature = "accesskit")] use accesskit::TextPosition; use alloc::vec::Vec; @@ -826,10 +828,18 @@ impl Selection { let mut start_x = metrics.offset as f64; let mut cur_x = start_x; let mut cluster_count = 0; - for run in line.runs() { - for cluster in run.visual_clusters() { + for item in line.items() { + let PositionedLayoutItem::GlyphRun(run) = item else { + continue; + }; + let offset = run.offset() + metrics.offset; + let run = run.run(); + for (ix, cluster) in run.visual_clusters().enumerate() { let advance = cluster.advance() as f64; if text_range.contains(&cluster.text_range().start) { + if ix == 0 { + cur_x = offset as f64; + } cluster_count += 1; cur_x += advance; } else { @@ -837,6 +847,9 @@ impl Selection { let width = (cur_x - start_x).max(MIN_RECT_WIDTH); f(Rect::new(start_x as _, line_min, start_x + width, line_max)); } + if ix == 0 { + cur_x = offset as f64; + } cur_x += advance; start_x = cur_x; }