Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/geometry.rs         |  4 ++++
crates/gpui3/src/scene.rs            |  6 +++---
crates/gpui3/src/text_system/line.rs | 29 ++++++++++++++++++++++++++---
crates/gpui3/src/window.rs           | 27 +++++++++++++++++++--------
4 files changed, 52 insertions(+), 14 deletions(-)

Detailed changes

crates/gpui3/src/geometry.rs 🔗

@@ -478,6 +478,10 @@ impl Pixels {
         Self(self.0.round())
     }
 
+    pub fn floor(&self) -> Self {
+        Self(self.0.floor())
+    }
+
     pub fn to_device_pixels(&self, scale: f32) -> DevicePixels {
         DevicePixels((self.0 * scale).ceil() as u32)
     }

crates/gpui3/src/scene.rs 🔗

@@ -10,7 +10,7 @@ pub type StackingOrder = SmallVec<[u32; 16]>;
 
 #[derive(Debug)]
 pub struct Scene {
-    scale_factor: f32,
+    pub(crate) scale_factor: f32,
     pub(crate) layers: BTreeMap<StackingOrder, SceneLayer>,
 }
 
@@ -29,8 +29,8 @@ impl Scene {
         }
     }
 
-    pub fn insert(&mut self, order: StackingOrder, primitive: impl Into<Primitive>) {
-        let layer = self.layers.entry(order).or_default();
+    pub fn insert(&mut self, stacking_order: StackingOrder, primitive: impl Into<Primitive>) {
+        let layer = self.layers.entry(stacking_order).or_default();
 
         let primitive = primitive.into();
         match primitive {

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

@@ -1,10 +1,12 @@
 use crate::{
-    black, point, px, Bounds, FontId, Hsla, Layout, Pixels, Point, RasterizedGlyphId, RunStyle,
-    ShapedBoundary, ShapedLine, ShapedRun, UnderlineStyle, WindowContext,
+    black, point, px, Bounds, FontId, Hsla, Layout, MonochromeSprite, Pixels, Point,
+    RasterizedGlyphId, RunStyle, ShapedBoundary, ShapedLine, ShapedRun, UnderlineStyle,
+    WindowContext,
 };
 use anyhow::Result;
 use smallvec::SmallVec;
 use std::sync::Arc;
+use util::ResultExt;
 
 #[derive(Default, Debug, Clone)]
 pub struct Line {
@@ -174,7 +176,28 @@ impl Line {
                         //     origin: glyph_origin,
                         // });
                     } else {
-                        todo!()
+                        if let Some((tile, bounds)) = cx
+                            .rasterize_glyph(
+                                run.font_id,
+                                glyph.id,
+                                self.layout.font_size,
+                                cx.scale_factor(),
+                                glyph_origin,
+                            )
+                            .log_err()
+                        {
+                            let layer_id = cx.current_layer_id();
+                            cx.scene().insert(
+                                layer_id,
+                                MonochromeSprite {
+                                    order: layout.order,
+                                    bounds,
+                                    color,
+                                    tile,
+                                },
+                            );
+                        }
+
                         // cx.scene().insert(Symbol {
                         //     order: layout.order,
                         //     origin,

crates/gpui3/src/window.rs 🔗

@@ -22,7 +22,7 @@ pub struct Window {
     layout_engine: TaffyLayoutEngine,
     pub(crate) root_view: Option<AnyView<()>>,
     mouse_position: Point<Pixels>,
-    current_stacking_order: StackingOrder,
+    current_layer_id: StackingOrder,
     pub(crate) scene: Scene,
     pub(crate) dirty: bool,
 }
@@ -63,7 +63,7 @@ impl Window {
             layout_engine: TaffyLayoutEngine::new(),
             root_view: None,
             mouse_position,
-            current_stacking_order: SmallVec::new(),
+            current_layer_id: SmallVec::new(),
             scene: Scene::new(scale_factor),
             dirty: true,
         }
@@ -122,6 +122,10 @@ impl<'a, 'w> WindowContext<'a, 'w> {
             .map(Into::into)?)
     }
 
+    pub fn scale_factor(&self) -> f32 {
+        self.window.scene.scale_factor
+    }
+
     pub fn rem_size(&self) -> Pixels {
         self.window.rem_size
     }
@@ -135,14 +139,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
     }
 
     pub fn stack<R>(&mut self, order: u32, f: impl FnOnce(&mut Self) -> R) -> R {
-        self.window.current_stacking_order.push(order);
+        self.window.current_layer_id.push(order);
         let result = f(self);
-        self.window.current_stacking_order.pop();
+        self.window.current_layer_id.pop();
         result
     }
 
-    pub fn current_stack_order(&self) -> StackingOrder {
-        self.window.current_stacking_order.clone()
+    pub fn current_layer_id(&self) -> StackingOrder {
+        self.window.current_layer_id.clone()
     }
 
     pub fn run_on_main<R>(
@@ -169,7 +173,7 @@ impl<'a, 'w> WindowContext<'a, 'w> {
         font_size: Pixels,
         scale_factor: f32,
         target_position: Point<Pixels>,
-    ) -> Result<(AtlasTile, Point<DevicePixels>)> {
+    ) -> Result<(AtlasTile, Bounds<Pixels>)> {
         let target_position = target_position * scale_factor;
         let subpixel_variant = Point {
             x: (target_position.x.0.fract() * SUBPIXEL_VARIANTS as f32).floor() as u8,
@@ -192,7 +196,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
                 Ok((bounds.size, pixels))
             })?;
 
-        Ok((tile, offset))
+        // Align bounding box surrounding glyph to pixel grid
+        let mut origin = (target_position * scale_factor).map(|p| p.floor());
+        // Position glyph within bounding box
+        origin += offset.map(|o| px(u32::from(o) as f32));
+        let size = tile.bounds_in_atlas.size.map(|b| px(b.0 as f32));
+        let bounds = Bounds { origin, size };
+
+        Ok((tile, bounds))
     }
 
     pub(crate) fn draw(&mut self) -> Result<()> {