Include length in run to not use tuples

Nathan Sobo created

Change summary

crates/gpui3/src/elements/text.rs            |  2 
crates/gpui3/src/style.rs                    |  9 ++++---
crates/gpui3/src/text_system.rs              | 25 +++++++++++----------
crates/gpui3/src/text_system/line_wrapper.rs | 26 +++++++++++++++------
4 files changed, 37 insertions(+), 25 deletions(-)

Detailed changes

crates/gpui3/src/elements/text.rs 🔗

@@ -80,7 +80,7 @@ impl<S: 'static + Send + Sync> Element for Text<S> {
                     .layout_text(
                         text.as_ref(),
                         font_size,
-                        &[(text.len(), text_style.to_run())],
+                        &[text_style.to_run(text.len())],
                         known_dimensions.width, // Wrap if we know the width.
                     )
                     .log_err()

crates/gpui3/src/style.rs 🔗

@@ -1,8 +1,8 @@
 use crate::{
     phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners,
     CornersRefinement, DefiniteLength, Edges, EdgesRefinement, Font, FontFeatures, FontStyle,
-    FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, RunStyle, SharedString,
-    Size, SizeRefinement, ViewContext, WindowContext,
+    FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rems, Result, SharedString, Size,
+    SizeRefinement, TextRun, ViewContext, WindowContext,
 };
 use refineable::{Cascade, Refineable};
 use smallvec::SmallVec;
@@ -161,8 +161,9 @@ impl TextStyle {
         Ok(self)
     }
 
-    pub fn to_run(&self) -> RunStyle {
-        RunStyle {
+    pub fn to_run(&self, len: usize) -> TextRun {
+        TextRun {
+            len,
             font: Font {
                 family: self.font_family.clone(),
                 features: Default::default(),

crates/gpui3/src/text_system.rs 🔗

@@ -149,7 +149,7 @@ impl TextSystem {
         &self,
         text: &str,
         font_size: Pixels,
-        runs: &[(usize, RunStyle)],
+        runs: &[TextRun],
         wrap_width: Option<Pixels>,
     ) -> Result<SmallVec<[Arc<Line>; 1]>> {
         let mut runs = runs.iter().cloned().peekable();
@@ -165,39 +165,39 @@ impl TextSystem {
             let mut decoration_runs = SmallVec::<[DecorationRun; 32]>::new();
             let mut run_start = line_start;
             while run_start < line_end {
-                let Some((run_len, run_style)) = runs.peek_mut() else {
+                let Some(run) = runs.peek_mut() else {
                     break;
                 };
 
-                let run_len_within_line = cmp::min(line_end, run_start + *run_len) - run_start;
+                let run_len_within_line = cmp::min(line_end, run_start + run.len) - run_start;
 
-                if last_font == Some(run_style.font.clone()) {
+                if last_font == Some(run.font.clone()) {
                     font_runs.last_mut().unwrap().0 += run_len_within_line;
                 } else {
-                    last_font = Some(run_style.font.clone());
+                    last_font = Some(run.font.clone());
                     font_runs.push((
                         run_len_within_line,
-                        self.platform_text_system.font_id(&run_style.font)?,
+                        self.platform_text_system.font_id(&run.font)?,
                     ));
                 }
 
                 if decoration_runs.last().map_or(false, |last_run| {
-                    last_run.color == run_style.color && last_run.underline == run_style.underline
+                    last_run.color == run.color && last_run.underline == run.underline
                 }) {
                     decoration_runs.last_mut().unwrap().len += run_len_within_line as u32;
                 } else {
                     decoration_runs.push(DecorationRun {
                         len: run_len_within_line as u32,
-                        color: run_style.color,
-                        underline: run_style.underline.clone(),
+                        color: run.color,
+                        underline: run.underline.clone(),
                     });
                 }
 
-                if run_len_within_line == *run_len {
+                if run_len_within_line == run.len {
                     runs.next();
                 } else {
                     // Preserve the remainder of the run for the next line
-                    *run_len -= run_len_within_line;
+                    run.len -= run_len_within_line;
                 }
                 run_start += run_len_within_line;
             }
@@ -360,7 +360,8 @@ impl Display for FontStyle {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub struct RunStyle {
+pub struct TextRun {
+    pub len: usize,
     pub font: Font,
     pub color: Hsla,
     pub underline: Option<UnderlineStyle>,

crates/gpui3/src/text_system/line_wrapper.rs 🔗

@@ -203,7 +203,7 @@ impl Boundary {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::{font, App, RunStyle};
+    use crate::{font, App, TextRun};
 
     #[test]
     fn test_wrap_line() {
@@ -274,28 +274,38 @@ mod tests {
         App::test().run(|cx| {
             let text_system = cx.text_system().clone();
 
-            let normal = RunStyle {
+            let normal = TextRun {
+                len: 0,
                 font: font("Helvetica"),
                 color: Default::default(),
                 underline: Default::default(),
             };
-            let bold = RunStyle {
+            let bold = TextRun {
+                len: 0,
                 font: font("Helvetica").bold(),
                 color: Default::default(),
                 underline: Default::default(),
             };
 
+            impl TextRun {
+                fn with_len(&self, len: usize) -> Self {
+                    let mut this = self.clone();
+                    this.len = len;
+                    this
+                }
+            }
+
             let text = "aa bbb cccc ddddd eeee";
             let lines = text_system
                 .layout_text(
                     text,
                     px(16.),
                     &[
-                        (4, normal.clone()),
-                        (5, bold.clone()),
-                        (6, normal.clone()),
-                        (1, bold.clone()),
-                        (7, normal.clone()),
+                        normal.with_len(4),
+                        bold.with_len(5),
+                        normal.with_len(6),
+                        bold.with_len(1),
+                        normal.with_len(7),
                     ],
                     None,
                 )