Checkpoint

Antonio Scandurra created

Change summary

crates/gpui3/src/geometry.rs                |  7 ++++
crates/gpui3/src/platform/mac/shaders.metal | 37 +++++++++++++++++++++-
crates/gpui3/src/platform/mac/window.rs     |  7 +++-
crates/gpui3/src/scene.rs                   |  5 +-
4 files changed, 49 insertions(+), 7 deletions(-)

Detailed changes

crates/gpui3/src/geometry.rs 🔗

@@ -159,6 +159,13 @@ pub struct Bounds<T: Clone + Debug> {
 unsafe impl<T: Clone + Debug + Zeroable + Pod> Zeroable for Bounds<T> {}
 unsafe impl<T: Clone + Debug + Zeroable + Pod> Pod for Bounds<T> {}
 
+impl<T: Clone + Debug + Mul<S, Output = T>, S: Clone> MulAssign<S> for Bounds<T> {
+    fn mul_assign(&mut self, rhs: S) {
+        self.origin *= rhs.clone();
+        self.size *= rhs;
+    }
+}
+
 impl<T: Clone + Debug + Add<T, Output = T>> Bounds<T> {
     pub fn upper_right(&self) -> Point<T> {
         Point {

crates/gpui3/src/platform/mac/shaders.metal 🔗

@@ -23,6 +23,11 @@ vertex QuadVertexOutput quad_vertex(
     float2 unit_vertex = unit_vertices[unit_vertex_id];
     Quad quad = quads[quad_id];
     float2 position_2d = unit_vertex * float2(quad.bounds.size.width, quad.bounds.size.height) + float2(quad.bounds.origin.x, quad.bounds.origin.y);
+    position_2d.x = max(quad.clip_bounds.origin.x, position_2d.x);
+    position_2d.x = min(quad.clip_bounds.origin.x + quad.clip_bounds.size.width, position_2d.x);
+    position_2d.y = max(quad.clip_bounds.origin.y, position_2d.y);
+    position_2d.y = min(quad.clip_bounds.origin.y + quad.clip_bounds.size.height, position_2d.y);
+
     float2 viewport_size = float2((float)uniforms->viewport_size.width, (float)uniforms->viewport_size.height);
     float4 device_position = to_device_position(position_2d, viewport_size);
     float4 background_color = hsla_to_rgba(quad.background);
@@ -35,13 +40,40 @@ vertex QuadVertexOutput quad_vertex(
     };
 }
 
+float quad_sdf(float2 point, Bounds_Pixels bounds, Corners_Pixels corner_radii) {
+    float2 half_size = float2(bounds.size.width, bounds.size.height) / 2.;
+    float2 center = float2(bounds.origin.x, bounds.origin.y) + half_size;
+    float2 center_to_point = point - center;
+    float corner_radius;
+    if (center_to_point.x < 0.) {
+        if (center_to_point.y < 0.) {
+            corner_radius = corner_radii.top_left;
+        } else {
+            corner_radius = corner_radii.bottom_left;
+        }
+    } else {
+        if (center_to_point.y < 0.) {
+            corner_radius = corner_radii.top_right;
+        } else {
+            corner_radius = corner_radii.bottom_right;
+        }
+    }
+
+    float2 rounded_edge_to_point = abs(center_to_point) - half_size + corner_radius;
+    float distance = length(max(0., rounded_edge_to_point))
+                     + min(0., max(rounded_edge_to_point.x, rounded_edge_to_point.y))
+                     - corner_radius;
+
+    return distance;
+}
+
 fragment float4 quad_fragment(
     QuadVertexOutput input [[stage_in]],
     constant Quad *quads [[buffer(QuadInputIndex_Quads)]]
 ) {
     Quad quad = quads[input.quad_id];
     float2 half_size = float2(quad.bounds.size.width, quad.bounds.size.height) / 2.;
-    float2 center = float2( quad.bounds.origin.x, quad.bounds.origin.y ) + half_size;
+    float2 center = float2(quad.bounds.origin.x, quad.bounds.origin.y) + half_size;
     float2 center_to_point = input.position.xy - center;
     float corner_radius;
     if (center_to_point.x < 0.) {
@@ -91,7 +123,8 @@ fragment float4 quad_fragment(
         color = float4(premultiplied_output_rgb, output_alpha);
     }
 
-    return color * float4(1., 1., 1., saturate(0.5 - distance));
+    float clip_distance = quad_sdf(input.position.xy, quad.clip_bounds, quad.clip_corner_radii);
+    return color * float4(1., 1., 1., saturate(0.5 - distance) * saturate(0.5 - clip_distance));
 }
 
 float4 hsla_to_rgba(Hsla hsla) {

crates/gpui3/src/platform/mac/window.rs 🔗

@@ -1357,10 +1357,13 @@ extern "C" fn display_layer(this: &Object, _: Sel, _: id) {
                 size: size(100., 100.).map(px),
             },
             clip_bounds: Bounds {
-                origin: point(10., 10.).map(px),
+                origin: point(20., 20.).map(px),
                 size: size(100., 100.).map(px),
             },
-            clip_corner_radii: Default::default(),
+            clip_corner_radii: crate::Corners {
+                top_left: px(10.),
+                ..Default::default()
+            },
             background: crate::rgb(0x00ff00).into(),
             border_color: Default::default(),
             corner_radii: crate::Corners {

crates/gpui3/src/scene.rs 🔗

@@ -96,9 +96,8 @@ impl Quad {
     }
 
     pub fn scale(&mut self, factor: f32) {
-        self.bounds.origin *= factor;
-        self.bounds.size *= factor;
-        self.clip_bounds.origin *= factor;
+        self.bounds *= factor;
+        self.clip_bounds *= factor;
         self.clip_corner_radii *= factor;
         self.corner_radii *= factor;
         self.border_widths *= factor;