From 92ff7f4e5eb45d8679dd5aacbd6fd13e86920622 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 21 May 2021 14:10:38 -0600 Subject: [PATCH 1/4] Accept colors in styling runs passed to layout_str Also move from the runs being expressed as ranges to the runs being expressed as a sequence of contiguous scalar lengths. --- gpui/examples/text.rs | 17 ++--- gpui/src/elements/label.rs | 123 +++++++++++++------------------ gpui/src/platform/mac/fonts.rs | 59 ++++++++++----- gpui/src/platform/mod.rs | 11 ++- gpui/src/text_layout.rs | 92 +++++++++++++---------- zed/src/editor/buffer_element.rs | 23 +++--- zed/src/editor/buffer_view.rs | 25 ++++--- 7 files changed, 182 insertions(+), 168 deletions(-) diff --git a/gpui/examples/text.rs b/gpui/examples/text.rs index df1f367cdbd9bcef0128be2941bb4a4724f8d7bd..7c59336672f0db03fbd26b284be4fa4ea00329df 100644 --- a/gpui/examples/text.rs +++ b/gpui/examples/text.rs @@ -82,11 +82,11 @@ impl gpui::Element for TextElement { text, font_size, &[ - (0..1, normal), - (1..2, bold), - (2..3, normal), - (3..4, bold), - (4..text.len(), normal), + (1, normal, ColorU::default()), + (1, bold, ColorU::default()), + (1, normal, ColorU::default()), + (1, bold, ColorU::default()), + (text.len() - 4, normal, ColorU::default()), ], ); @@ -95,12 +95,7 @@ impl gpui::Element for TextElement { background: Some(ColorU::white()), ..Default::default() }); - line.paint( - bounds.origin(), - bounds, - &[(0..text.len(), ColorU::black())], - ctx, - ); + line.paint(bounds.origin(), bounds, ctx); } fn dispatch_event( diff --git a/gpui/src/elements/label.rs b/gpui/src/elements/label.rs index 7ec49df414f30e820335051af99ce0440f87acc3..b936a94acfc7977c128b2c412a4595e22f111678 100644 --- a/gpui/src/elements/label.rs +++ b/gpui/src/elements/label.rs @@ -1,4 +1,5 @@ use serde_json::json; +use smallvec::{smallvec, SmallVec}; use crate::{ color::ColorU, @@ -13,7 +14,6 @@ use crate::{ AfterLayoutContext, DebugContext, Element, Event, EventContext, FontCache, LayoutContext, PaintContext, SizeConstraint, }; -use std::{ops::Range, sync::Arc}; pub struct Label { text: String, @@ -23,11 +23,6 @@ pub struct Label { highlights: Option, } -pub struct LayoutState { - line: Arc, - colors: Vec<(Range, ColorU)>, -} - pub struct Highlights { color: ColorU, indices: Vec, @@ -59,60 +54,56 @@ impl Label { self } - fn layout_text( + fn compute_runs( &self, font_cache: &FontCache, font_id: FontId, - ) -> (Vec<(Range, FontId)>, Vec<(Range, ColorU)>) { - let text_len = self.text.len(); - let mut styles; - let mut colors; + ) -> SmallVec<[(usize, FontId, ColorU); 8]> { if let Some(highlights) = self.highlights.as_ref() { - styles = Vec::new(); - colors = Vec::new(); let highlight_font_id = font_cache .select_font(self.family_id, &highlights.font_properties) .unwrap_or(font_id); - let mut pending_highlight: Option> = None; - for ix in &highlights.indices { - if let Some(pending_highlight) = pending_highlight.as_mut() { - if *ix == pending_highlight.end { - pending_highlight.end += 1; - } else { - styles.push((pending_highlight.clone(), highlight_font_id)); - colors.push((pending_highlight.clone(), highlights.color)); - styles.push((pending_highlight.end..*ix, font_id)); - colors.push((pending_highlight.end..*ix, ColorU::black())); - *pending_highlight = *ix..*ix + 1; + + let mut highlight_indices = highlights.indices.iter().copied().peekable(); + let mut runs = SmallVec::new(); + + for (char_ix, c) in self.text.char_indices() { + let mut font_id = font_id; + let mut color = ColorU::black(); + if let Some(highlight_ix) = highlight_indices.peek() { + if char_ix == *highlight_ix { + font_id = highlight_font_id; + color = highlights.color; + highlight_indices.next(); } - } else { - styles.push((0..*ix, font_id)); - colors.push((0..*ix, ColorU::black())); - pending_highlight = Some(*ix..*ix + 1); } - } - if let Some(pending_highlight) = pending_highlight.as_mut() { - styles.push((pending_highlight.clone(), highlight_font_id)); - colors.push((pending_highlight.clone(), highlights.color)); - if text_len > pending_highlight.end { - styles.push((pending_highlight.end..text_len, font_id)); - colors.push((pending_highlight.end..text_len, ColorU::black())); + + let push_new_run = + if let Some((last_len, last_font_id, last_color)) = runs.last_mut() { + if font_id == *last_font_id && color == *last_color { + *last_len += c.len_utf8(); + false + } else { + true + } + } else { + true + }; + + if push_new_run { + runs.push((c.len_utf8(), font_id, color)); } - } else { - styles.push((0..text_len, font_id)); - colors.push((0..text_len, ColorU::black())); } + + runs } else { - styles = vec![(0..text_len, font_id)]; - colors = vec![(0..text_len, ColorU::black())]; + smallvec![(self.text.len(), font_id, ColorU::black())] } - - (styles, colors) } } impl Element for Label { - type LayoutState = LayoutState; + type LayoutState = Line; type PaintState = (); fn layout( @@ -124,17 +115,17 @@ impl Element for Label { .font_cache .select_font(self.family_id, &self.font_properties) .unwrap(); - let (styles, colors) = self.layout_text(&ctx.font_cache, font_id); + let runs = self.compute_runs(&ctx.font_cache, font_id); let line = ctx.text_layout_cache - .layout_str(self.text.as_str(), self.font_size, styles.as_slice()); + .layout_str(self.text.as_str(), self.font_size, runs.as_slice()); let size = vec2f( - line.width.max(constraint.min.x()).min(constraint.max.x()), + line.width().max(constraint.min.x()).min(constraint.max.x()), ctx.font_cache.line_height(font_id, self.font_size).ceil(), ); - (size, LayoutState { line, colors }) + (size, line) } fn after_layout(&mut self, _: Vector2F, _: &mut Self::LayoutState, _: &mut AfterLayoutContext) { @@ -143,13 +134,12 @@ impl Element for Label { fn paint( &mut self, bounds: RectF, - layout: &mut Self::LayoutState, + line: &mut Self::LayoutState, ctx: &mut PaintContext, ) -> Self::PaintState { - layout.line.paint( + line.paint( bounds.origin(), RectF::new(vec2f(0., 0.), bounds.size()), - layout.colors.as_slice(), ctx, ) } @@ -226,28 +216,21 @@ mod tests { ], ); - let (styles, colors) = label.layout_text(app.font_cache().as_ref(), menlo_regular); - assert_eq!(styles.len(), colors.len()); - - let mut spans = Vec::new(); - for ((style_range, font_id), (color_range, color)) in styles.into_iter().zip(colors) { - assert_eq!(style_range, color_range); - spans.push((style_range, font_id, color)); - } + let runs = label.compute_runs(app.font_cache().as_ref(), menlo_regular); assert_eq!( - spans, + runs.as_slice(), &[ - (0..3, menlo_regular, black), - (3..4, menlo_bold, red), - (4..5, menlo_regular, black), - (5..6, menlo_bold, red), - (6..9, menlo_regular, black), - (9..10, menlo_bold, red), - (10..15, menlo_regular, black), - (15..16, menlo_bold, red), - (16..18, menlo_regular, black), - (18..19, menlo_bold, red), - (19..34, menlo_regular, black) + (3, menlo_regular, black), + (1, menlo_bold, red), + (1, menlo_regular, black), + (1, menlo_bold, red), + (3, menlo_regular, black), + (1, menlo_bold, red), + (5, menlo_regular, black), + (1, menlo_bold, red), + (2, menlo_regular, black), + (1, menlo_bold, red), + (15, menlo_regular, black), ] ); } diff --git a/gpui/src/platform/mac/fonts.rs b/gpui/src/platform/mac/fonts.rs index 50e9f3030ff3ce6d5d087551061ecb66b15610a3..31e2aa867678c7a2b00dbca43538d268e20c1c92 100644 --- a/gpui/src/platform/mac/fonts.rs +++ b/gpui/src/platform/mac/fonts.rs @@ -1,4 +1,5 @@ use crate::{ + color::ColorU, fonts::{FontId, GlyphId, Metrics, Properties}, geometry::{ rect::{RectF, RectI}, @@ -6,7 +7,7 @@ use crate::{ vector::{vec2f, vec2i, Vector2F}, }, platform, - text_layout::{Glyph, Line, Run}, + text_layout::{Glyph, LineLayout, Run}, }; use cocoa::appkit::{CGFloat, CGPoint}; use core_foundation::{ @@ -21,7 +22,7 @@ use core_graphics::{ use core_text::{line::CTLine, string_attributes::kCTFontAttributeName}; use font_kit::{canvas::RasterizationOptions, hinting::HintingOptions, source::SystemSource}; use parking_lot::RwLock; -use std::{char, convert::TryFrom}; +use std::{cell::RefCell, char, convert::TryFrom}; #[allow(non_upper_case_globals)] const kCGImageAlphaOnly: u32 = 7; @@ -80,8 +81,8 @@ impl platform::FontSystem for FontSystem { &self, text: &str, font_size: f32, - runs: &[(std::ops::Range, FontId)], - ) -> Line { + runs: &[(usize, FontId, ColorU)], + ) -> LineLayout { self.0.read().layout_str(text, font_size, runs) } } @@ -185,8 +186,8 @@ impl FontSystemState { &self, text: &str, font_size: f32, - runs: &[(std::ops::Range, FontId)], - ) -> Line { + runs: &[(usize, FontId, ColorU)], + ) -> LineLayout { let font_id_attr_name = CFString::from_static_string("zed_font_id"); let len = text.len(); @@ -205,16 +206,34 @@ impl FontSystemState { let mut utf8_and_utf16_ixs = utf8_and_utf16_ixs.clone(); string.replace_str(&CFString::new(text), CFRange::init(0, 0)); + let last_run: RefCell> = Default::default(); + let font_runs = runs + .iter() + .filter_map(|(len, font_id, _)| { + let mut last_run = last_run.borrow_mut(); + if let Some((last_len, last_font_id)) = last_run.as_mut() { + if font_id == last_font_id { + *last_len += *len; + None + } else { + let result = (*last_len, *last_font_id); + *last_len = *len; + *last_font_id = *font_id; + Some(result) + } + } else { + *last_run = Some((*len, *font_id)); + None + } + }) + .chain(std::iter::from_fn(|| last_run.borrow_mut().take())); + let mut utf8_ix = 0; let mut utf16_ix = 0; - for (range, font_id) in runs { - while utf8_ix < range.start { - let (next_utf8_ix, next_utf16_ix) = utf8_and_utf16_ixs.next().unwrap(); - utf8_ix = next_utf8_ix; - utf16_ix = next_utf16_ix; - } + for (run_len, font_id) in font_runs { + let utf8_end = utf16_ix + run_len; let utf16_start = utf16_ix; - while utf8_ix < range.end { + while utf8_ix < utf8_end { let (next_utf8_ix, next_utf16_ix) = utf8_and_utf16_ixs.next().unwrap(); utf8_ix = next_utf8_ix; utf16_ix = next_utf16_ix; @@ -279,7 +298,7 @@ impl FontSystemState { } let typographic_bounds = line.get_typographic_bounds(); - Line { + LineLayout { width: typographic_bounds.width as f32, ascent: typographic_bounds.ascent as f32, descent: typographic_bounds.descent as f32, @@ -308,9 +327,9 @@ mod tests { "hello world", 16.0, &[ - (0..2, menlo_bold), - (2..6, menlo_italic), - (6..11, menlo_regular), + (2, menlo_bold, Default::default()), + (4, menlo_italic, Default::default()), + (5, menlo_regular, Default::default()), ], ); assert_eq!(line.runs.len(), 3); @@ -336,9 +355,9 @@ mod tests { text, 16.0, &[ - (0..9, zapfino_regular), - (9..22, menlo_regular), - (22..text.len(), zapfino_regular), + (9, zapfino_regular, ColorU::default()), + (13, menlo_regular, ColorU::default()), + (text.len() - 22, zapfino_regular, ColorU::default()), ], ); assert_eq!( diff --git a/gpui/src/platform/mod.rs b/gpui/src/platform/mod.rs index fd62770c12c82b98bdc9ddad17bf8da44184f96d..a6c45b2753efd5b222f3a1b27030c95cff1e1e98 100644 --- a/gpui/src/platform/mod.rs +++ b/gpui/src/platform/mod.rs @@ -8,20 +8,20 @@ pub mod current { } use crate::{ + color::ColorU, executor, fonts::{FontId, GlyphId, Metrics as FontMetrics, Properties as FontProperties}, geometry::{ rect::{RectF, RectI}, vector::Vector2F, }, - text_layout::Line, + text_layout::LineLayout, ClipboardItem, Menu, Scene, }; use async_task::Runnable; pub use event::Event; use std::{ any::Any, - ops::Range, path::{Path, PathBuf}, rc::Rc, sync::Arc, @@ -122,5 +122,10 @@ pub trait FontSystem: Send + Sync { subpixel_shift: Vector2F, scale_factor: f32, ) -> Option<(RectI, Vec)>; - fn layout_str(&self, text: &str, font_size: f32, runs: &[(Range, FontId)]) -> Line; + fn layout_str( + &self, + text: &str, + font_size: f32, + runs: &[(usize, FontId, ColorU)], + ) -> LineLayout; } diff --git a/gpui/src/text_layout.rs b/gpui/src/text_layout.rs index c8daf1a6df8af615c0daecfe799e732ac4e9f9cb..3bb00cb41c8370208517370bf068753335d680f4 100644 --- a/gpui/src/text_layout.rs +++ b/gpui/src/text_layout.rs @@ -14,13 +14,12 @@ use std::{ borrow::Borrow, collections::HashMap, hash::{Hash, Hasher}, - ops::Range, sync::Arc, }; pub struct TextLayoutCache { - prev_frame: Mutex>>, - curr_frame: RwLock>>, + prev_frame: Mutex>>, + curr_frame: RwLock>>, fonts: Arc, } @@ -44,31 +43,31 @@ impl TextLayoutCache { &'a self, text: &'a str, font_size: f32, - runs: &'a [(Range, FontId)], - ) -> Arc { + runs: &'a [(usize, FontId, ColorU)], + ) -> Line { let key = &CacheKeyRef { text, font_size: OrderedFloat(font_size), runs, } as &dyn CacheKey; let curr_frame = self.curr_frame.upgradable_read(); - if let Some(line) = curr_frame.get(key) { - return line.clone(); + if let Some(layout) = curr_frame.get(key) { + return Line::new(layout.clone(), runs); } let mut curr_frame = RwLockUpgradableReadGuard::upgrade(curr_frame); - if let Some((key, line)) = self.prev_frame.lock().remove_entry(key) { - curr_frame.insert(key, line.clone()); - line.clone() + if let Some((key, layout)) = self.prev_frame.lock().remove_entry(key) { + curr_frame.insert(key, layout.clone()); + Line::new(layout.clone(), runs) } else { - let line = Arc::new(self.fonts.layout_str(text, font_size, runs)); + let layout = Arc::new(self.fonts.layout_str(text, font_size, runs)); let key = CacheKeyValue { text: text.into(), font_size: OrderedFloat(font_size), runs: SmallVec::from(runs), }; - curr_frame.insert(key, line.clone()); - line + curr_frame.insert(key, layout.clone()); + Line::new(layout, runs) } } } @@ -95,7 +94,7 @@ impl<'a> Hash for (dyn CacheKey + 'a) { struct CacheKeyValue { text: String, font_size: OrderedFloat, - runs: SmallVec<[(Range, FontId); 1]>, + runs: SmallVec<[(usize, FontId, ColorU); 1]>, } impl CacheKey for CacheKeyValue { @@ -124,7 +123,7 @@ impl<'a> Borrow for CacheKeyValue { struct CacheKeyRef<'a> { text: &'a str, font_size: OrderedFloat, - runs: &'a [(Range, FontId)], + runs: &'a [(usize, FontId, ColorU)], } impl<'a> CacheKey for CacheKeyRef<'a> { @@ -135,6 +134,12 @@ impl<'a> CacheKey for CacheKeyRef<'a> { #[derive(Default, Debug)] pub struct Line { + layout: Arc, + color_runs: SmallVec<[(u32, ColorU); 32]>, +} + +#[derive(Default, Debug)] +pub struct LineLayout { pub width: f32, pub ascent: f32, pub descent: f32, @@ -157,22 +162,34 @@ pub struct Glyph { } impl Line { + fn new(layout: Arc, runs: &[(usize, FontId, ColorU)]) -> Self { + let mut color_runs = SmallVec::new(); + for (len, _, color) in runs { + color_runs.push((*len as u32, *color)); + } + Self { layout, color_runs } + } + + pub fn width(&self) -> f32 { + self.layout.width + } + pub fn x_for_index(&self, index: usize) -> f32 { - for run in &self.runs { + for run in &self.layout.runs { for glyph in &run.glyphs { if glyph.index == index { return glyph.position.x(); } } } - self.width + self.layout.width } pub fn index_for_x(&self, x: f32) -> Option { - if x >= self.width { + if x >= self.layout.width { None } else { - for run in self.runs.iter().rev() { + for run in self.layout.runs.iter().rev() { for glyph in run.glyphs.iter().rev() { if glyph.position.x() <= x { return Some(glyph.index); @@ -183,21 +200,19 @@ impl Line { } } - pub fn paint( - &self, - origin: Vector2F, - bounds: RectF, - colors: &[(Range, ColorU)], - ctx: &mut PaintContext, - ) { - let mut colors = colors.iter().peekable(); - let mut color = ColorU::black(); + pub fn paint(&self, origin: Vector2F, bounds: RectF, ctx: &mut PaintContext) { + let padding_top = (bounds.height() - self.layout.ascent - self.layout.descent) / 2.; + let baseline_origin = vec2f(0., padding_top + self.layout.ascent); - let padding_top = (bounds.height() - self.ascent - self.descent) / 2.; - let baseline_origin = vec2f(0., padding_top + self.ascent); + let mut color_runs = self.color_runs.iter(); + let mut color_end = 0; + let mut color = ColorU::black(); - for run in &self.runs { - let max_glyph_width = ctx.font_cache.bounding_box(run.font_id, self.font_size).x(); + for run in &self.layout.runs { + let max_glyph_width = ctx + .font_cache + .bounding_box(run.font_id, self.layout.font_size) + .x(); for glyph in &run.glyphs { let glyph_origin = baseline_origin + glyph.position; @@ -209,18 +224,19 @@ impl Line { break; } - while let Some((range, next_color)) = colors.peek() { - if glyph.index >= range.end { - colors.next(); + if glyph.index >= color_end { + if let Some(next_run) = color_runs.next() { + color_end += next_run.0 as usize; + color = next_run.1; } else { - color = *next_color; - break; + color_end = self.layout.len; + color = ColorU::black(); } } ctx.scene.push_glyph(scene::Glyph { font_id: run.font_id, - font_size: self.font_size, + font_size: self.layout.font_size, id: glyph.id, origin: origin + glyph_origin, color, diff --git a/zed/src/editor/buffer_element.rs b/zed/src/editor/buffer_element.rs index ac5354f95ceb78933ea6de64db2b6f4863dd8368..fc5b7852e9e59d334498229e8d43f39427d1290d 100644 --- a/zed/src/editor/buffer_element.rs +++ b/zed/src/editor/buffer_element.rs @@ -14,10 +14,7 @@ use gpui::{ use json::json; use smallvec::SmallVec; use std::cmp::Ordering; -use std::{ - cmp::{self}, - sync::Arc, -}; +use std::cmp::{self}; pub struct BufferElement { view: WeakViewHandle, @@ -188,13 +185,12 @@ impl BufferElement { for (ix, line) in layout.line_number_layouts.iter().enumerate() { let line_origin = rect.origin() + vec2f( - rect.width() - line.width - layout.gutter_padding, + rect.width() - line.width() - layout.gutter_padding, ix as f32 * line_height - (scroll_top % line_height), ); line.paint( line_origin, - RectF::new(vec2f(0., 0.), vec2f(line.width, line_height)), - &[(0..line.len, ColorU::black())], + RectF::new(vec2f(0., 0.), vec2f(line.width(), line_height)), ctx, ); } @@ -259,7 +255,7 @@ impl BufferElement { + line_layout.x_for_index(range_end.column() as usize) - scroll_left } else { - content_origin.x() + line_layout.width + corner_radius * 2.0 + content_origin.x() + line_layout.width() + corner_radius * 2.0 - scroll_left }, } @@ -292,7 +288,6 @@ impl BufferElement { line.paint( content_origin + vec2f(-scroll_left, row as f32 * line_height - scroll_top), RectF::new(vec2f(scroll_left, 0.), vec2f(bounds.width(), line_height)), - &[(0..line.len, ColorU::black())], ctx, ); } @@ -377,8 +372,8 @@ impl Element for BufferElement { } Ok(layouts) => { for line in &layouts { - if line.width > max_visible_line_width { - max_visible_line_width = line.width; + if line.width() > max_visible_line_width { + max_visible_line_width = line.width(); } } @@ -506,8 +501,8 @@ pub struct LayoutState { gutter_size: Vector2F, gutter_padding: f32, text_size: Vector2F, - line_layouts: Vec>, - line_number_layouts: Vec>, + line_layouts: Vec, + line_number_layouts: Vec, max_visible_line_width: f32, autoscroll_horizontally: bool, } @@ -524,7 +519,7 @@ impl LayoutState { let longest_line_width = view .layout_line(row, font_cache, layout_cache, app) .unwrap() - .width; + .width(); longest_line_width.max(self.max_visible_line_width) + view.em_width(font_cache) } diff --git a/zed/src/editor/buffer_view.rs b/zed/src/editor/buffer_view.rs index 57dbb2992d6f78e1ea5035ad95f0086331c401ae..5f05defdf63cb112552189833055382b599c172c 100644 --- a/zed/src/editor/buffer_view.rs +++ b/zed/src/editor/buffer_view.rs @@ -5,9 +5,10 @@ use super::{ use crate::{settings::Settings, util::post_inc, workspace, worktree::FileHandle}; use anyhow::Result; use gpui::{ - fonts::Properties as FontProperties, geometry::vector::Vector2F, keymap::Binding, text_layout, - AppContext, ClipboardItem, Element, ElementBox, Entity, FontCache, ModelHandle, - MutableAppContext, Task, TextLayoutCache, View, ViewContext, WeakViewHandle, + color::ColorU, fonts::Properties as FontProperties, geometry::vector::Vector2F, + keymap::Binding, text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, + FontCache, ModelHandle, MutableAppContext, Task, TextLayoutCache, View, ViewContext, + WeakViewHandle, }; use parking_lot::Mutex; use postage::watch; @@ -448,7 +449,7 @@ impl BufferView { viewport_width: f32, scroll_width: f32, max_glyph_width: f32, - layouts: &[Arc], + layouts: &[text_layout::Line], ctx: &AppContext, ) { let mut target_left = std::f32::INFINITY; @@ -2077,9 +2078,9 @@ impl BufferView { .layout_str( "1".repeat(digit_count).as_str(), font_size, - &[(0..digit_count, font_id)], + &[(digit_count, font_id, ColorU::black())], ) - .width) + .width()) } pub fn layout_line_numbers( @@ -2088,7 +2089,7 @@ impl BufferView { font_cache: &FontCache, layout_cache: &TextLayoutCache, ctx: &AppContext, - ) -> Result>> { + ) -> Result> { let settings = self.settings.borrow(); let font_size = settings.buffer_font_size; let font_id = @@ -2114,7 +2115,7 @@ impl BufferView { layouts.push(layout_cache.layout_str( &line_number, font_size, - &[(0..line_number.len(), font_id)], + &[(line_number.len(), font_id, ColorU::black())], )); } @@ -2127,7 +2128,7 @@ impl BufferView { font_cache: &FontCache, layout_cache: &TextLayoutCache, ctx: &AppContext, - ) -> Result>> { + ) -> Result> { rows.end = cmp::min(rows.end, self.display_map.max_point(ctx).row() + 1); if rows.start >= rows.end { return Ok(Vec::new()); @@ -2151,7 +2152,7 @@ impl BufferView { layouts.push(layout_cache.layout_str( &line, font_size, - &[(0..line.len(), font_id)], + &[(line.len(), font_id, ColorU::black())], )); line.clear(); row += 1; @@ -2171,7 +2172,7 @@ impl BufferView { font_cache: &FontCache, layout_cache: &TextLayoutCache, app: &AppContext, - ) -> Result> { + ) -> Result { let settings = self.settings.borrow(); let font_id = font_cache.select_font(settings.buffer_font_family, &FontProperties::new())?; @@ -2181,7 +2182,7 @@ impl BufferView { Ok(layout_cache.layout_str( &line, settings.buffer_font_size, - &[(0..self.line_len(row, app) as usize, font_id)], + &[(self.line_len(row, app) as usize, font_id, ColorU::black())], )) } From b075b0108dc141239286eab9cb921604f0eac5f3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 21 May 2021 14:14:05 -0600 Subject: [PATCH 2/4] Clarify variable name --- gpui/src/text_layout.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gpui/src/text_layout.rs b/gpui/src/text_layout.rs index 3bb00cb41c8370208517370bf068753335d680f4..af30630fb24b8020bc313b2b3526205334ad2f0d 100644 --- a/gpui/src/text_layout.rs +++ b/gpui/src/text_layout.rs @@ -200,8 +200,8 @@ impl Line { } } - pub fn paint(&self, origin: Vector2F, bounds: RectF, ctx: &mut PaintContext) { - let padding_top = (bounds.height() - self.layout.ascent - self.layout.descent) / 2.; + pub fn paint(&self, origin: Vector2F, visible_bounds: RectF, ctx: &mut PaintContext) { + let padding_top = (visible_bounds.height() - self.layout.ascent - self.layout.descent) / 2.; let baseline_origin = vec2f(0., padding_top + self.layout.ascent); let mut color_runs = self.color_runs.iter(); @@ -217,10 +217,10 @@ impl Line { for glyph in &run.glyphs { let glyph_origin = baseline_origin + glyph.position; - if glyph_origin.x() + max_glyph_width < bounds.origin().x() { + if glyph_origin.x() + max_glyph_width < visible_bounds.origin().x() { continue; } - if glyph_origin.x() > bounds.upper_right().x() { + if glyph_origin.x() > visible_bounds.upper_right().x() { break; } From 2c122eb253e72b54fa2613e2ccc2678a7497347e Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 21 May 2021 14:36:44 -0600 Subject: [PATCH 3/4] Fix typo --- gpui/src/platform/mac/fonts.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gpui/src/platform/mac/fonts.rs b/gpui/src/platform/mac/fonts.rs index 31e2aa867678c7a2b00dbca43538d268e20c1c92..c33234090fa4be51768cfd6078ccff3d85304ab2 100644 --- a/gpui/src/platform/mac/fonts.rs +++ b/gpui/src/platform/mac/fonts.rs @@ -231,7 +231,7 @@ impl FontSystemState { let mut utf8_ix = 0; let mut utf16_ix = 0; for (run_len, font_id) in font_runs { - let utf8_end = utf16_ix + run_len; + let utf8_end = utf8_ix + run_len; let utf16_start = utf16_ix; while utf8_ix < utf8_end { let (next_utf8_ix, next_utf16_ix) = utf8_and_utf16_ixs.next().unwrap(); From 5d614e7e54b1ab8563bff435cabca532f7804b96 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 21 May 2021 14:36:52 -0600 Subject: [PATCH 4/4] Fix test assertions --- gpui/src/elements/label.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/gpui/src/elements/label.rs b/gpui/src/elements/label.rs index b936a94acfc7977c128b2c412a4595e22f111678..02d89200dda6ac2c9e78e3db2f2679de187bc954 100644 --- a/gpui/src/elements/label.rs +++ b/gpui/src/elements/label.rs @@ -220,17 +220,13 @@ mod tests { assert_eq!( runs.as_slice(), &[ - (3, menlo_regular, black), - (1, menlo_bold, red), - (1, menlo_regular, black), - (1, menlo_bold, red), - (3, menlo_regular, black), - (1, menlo_bold, red), - (5, menlo_regular, black), - (1, menlo_bold, red), - (2, menlo_regular, black), - (1, menlo_bold, red), - (15, menlo_regular, black), + (".α".len(), menlo_regular, black), + ("βγ".len(), menlo_bold, red), + ("δ".len(), menlo_regular, black), + ("ε".len(), menlo_bold, red), + (".ⓐ".len(), menlo_regular, black), + ("ⓑⓒ".len(), menlo_bold, red), + ("ⓓⓔ.abcde.".len(), menlo_regular, black), ] ); }