diff --git a/crates/gpui3/src/geometry.rs b/crates/gpui3/src/geometry.rs index a1e931357a69a5dc6f199d89f48468fe5dcf6891..ec468bc50a698dded7690cd352a3aa967248f5a8 100644 --- a/crates/gpui3/src/geometry.rs +++ b/crates/gpui3/src/geometry.rs @@ -159,6 +159,13 @@ pub struct Bounds { unsafe impl Zeroable for Bounds {} unsafe impl Pod for Bounds {} +impl, S: Clone> MulAssign for Bounds { + fn mul_assign(&mut self, rhs: S) { + self.origin *= rhs.clone(); + self.size *= rhs; + } +} + impl> Bounds { pub fn upper_right(&self) -> Point { Point { diff --git a/crates/gpui3/src/platform/mac/shaders.metal b/crates/gpui3/src/platform/mac/shaders.metal index 1f562071b082317a8b94ed0758b821ec04c9c446..e77f6085bac97d308bb94436c783e5fc272bc215 100644 --- a/crates/gpui3/src/platform/mac/shaders.metal +++ b/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) { diff --git a/crates/gpui3/src/platform/mac/window.rs b/crates/gpui3/src/platform/mac/window.rs index d62d724e2c05fa36d30b7e0dde1ef133f49b18ef..4571d41d4a9e0aa0414d9af78371ec1fd6cc9c46 100644 --- a/crates/gpui3/src/platform/mac/window.rs +++ b/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 { diff --git a/crates/gpui3/src/scene.rs b/crates/gpui3/src/scene.rs index cf739fc29974e5373375b0f5bf117392ff4e66c9..ad02d50e53d38a3498549b6818a5c7287a345ae5 100644 --- a/crates/gpui3/src/scene.rs +++ b/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;