Allow individual corner radii on drop shadows

This commit is contained in:
Nathan Sobo 2023-08-12 10:58:04 -06:00
parent 40f478937e
commit 65123e6eed
6 changed files with 50 additions and 19 deletions

View file

@ -1129,7 +1129,7 @@ impl EditorElement {
bounds, bounds,
background: Some(color), background: Some(color),
border, border,
corner_radii: style.thumb.corner_radius.into(), corner_radii: style.thumb.corner_radii.into(),
}) })
}; };
let background_ranges = editor let background_ranges = editor
@ -1189,7 +1189,7 @@ impl EditorElement {
bounds, bounds,
background: Some(color), background: Some(color),
border, border,
corner_radii: style.thumb.corner_radius.into(), corner_radii: style.thumb.corner_radii.into(),
}) })
} }
} }
@ -1198,7 +1198,7 @@ impl EditorElement {
bounds: thumb_bounds, bounds: thumb_bounds,
border: style.thumb.border, border: style.thumb.border,
background: style.thumb.background_color, background: style.thumb.background_color,
corner_radii: style.thumb.corner_radius.into(), corner_radii: style.thumb.corner_radii.into(),
}); });
} }

View file

@ -9,7 +9,7 @@ use crate::{
}, },
json::ToJson, json::ToJson,
platform::CursorStyle, platform::CursorStyle,
scene::{self, Border, CursorRegion, Quad}, scene::{self, Border, CornerRadii, CursorRegion, Quad},
AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View,
ViewContext, ViewContext,
}; };
@ -30,7 +30,7 @@ pub struct ContainerStyle {
#[serde(default)] #[serde(default)]
pub border: Border, pub border: Border,
#[serde(default)] #[serde(default)]
pub corner_radius: f32, pub corner_radii: CornerRadii,
#[serde(default)] #[serde(default)]
pub shadow: Option<Shadow>, pub shadow: Option<Shadow>,
#[serde(default)] #[serde(default)]
@ -133,7 +133,10 @@ impl<V: View> Container<V> {
} }
pub fn with_corner_radius(mut self, radius: f32) -> Self { pub fn with_corner_radius(mut self, radius: f32) -> Self {
self.style.corner_radius = radius; self.style.corner_radii.top_left = radius;
self.style.corner_radii.top_right = radius;
self.style.corner_radii.bottom_right = radius;
self.style.corner_radii.bottom_left = radius;
self self
} }
@ -225,7 +228,7 @@ impl<V: View> Element<V> for Container<V> {
if let Some(shadow) = self.style.shadow.as_ref() { if let Some(shadow) = self.style.shadow.as_ref() {
scene.push_shadow(scene::Shadow { scene.push_shadow(scene::Shadow {
bounds: quad_bounds + shadow.offset, bounds: quad_bounds + shadow.offset,
corner_radius: self.style.corner_radius, corner_radii: self.style.corner_radii,
sigma: shadow.blur, sigma: shadow.blur,
color: shadow.color, color: shadow.color,
}); });
@ -248,7 +251,7 @@ impl<V: View> Element<V> for Container<V> {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.background_color, background: self.style.background_color,
border: Default::default(), border: Default::default(),
corner_radii: self.style.corner_radius.into(), corner_radii: self.style.corner_radii.into(),
}); });
self.child self.child
@ -259,7 +262,7 @@ impl<V: View> Element<V> for Container<V> {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.overlay_color, background: self.style.overlay_color,
border: self.style.border, border: self.style.border,
corner_radii: self.style.corner_radius.into(), corner_radii: self.style.corner_radii.into(),
}); });
scene.pop_layer(); scene.pop_layer();
} else { } else {
@ -267,7 +270,7 @@ impl<V: View> Element<V> for Container<V> {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.background_color, background: self.style.background_color,
border: self.style.border, border: self.style.border,
corner_radii: self.style.corner_radius.into(), corner_radii: self.style.corner_radii.into(),
}); });
let child_origin = child_origin let child_origin = child_origin
@ -284,7 +287,7 @@ impl<V: View> Element<V> for Container<V> {
bounds: quad_bounds, bounds: quad_bounds,
background: self.style.overlay_color, background: self.style.overlay_color,
border: Default::default(), border: Default::default(),
corner_radii: self.style.corner_radius.into(), corner_radii: self.style.corner_radii.into(),
}); });
scene.pop_layer(); scene.pop_layer();
} }
@ -328,7 +331,7 @@ impl ToJson for ContainerStyle {
"padding": self.padding.to_json(), "padding": self.padding.to_json(),
"background_color": self.background_color.to_json(), "background_color": self.background_color.to_json(),
"border": self.border.to_json(), "border": self.border.to_json(),
"corner_radius": self.corner_radius, "corner_radius": self.corner_radii,
"shadow": self.shadow.to_json(), "shadow": self.shadow.to_json(),
}) })
} }

View file

@ -509,10 +509,14 @@ impl Renderer {
}; };
for (ix, shadow) in shadows.iter().enumerate() { for (ix, shadow) in shadows.iter().enumerate() {
let shape_bounds = shadow.bounds * scale_factor; let shape_bounds = shadow.bounds * scale_factor;
let corner_radii = shadow.corner_radii * scale_factor;
let shader_shadow = shaders::GPUIShadow { let shader_shadow = shaders::GPUIShadow {
origin: shape_bounds.origin().to_float2(), origin: shape_bounds.origin().to_float2(),
size: shape_bounds.size().to_float2(), size: shape_bounds.size().to_float2(),
corner_radius: shadow.corner_radius * scale_factor, corner_radius_top_left: corner_radii.top_left,
corner_radius_top_right: corner_radii.top_right,
corner_radius_bottom_right: corner_radii.bottom_right,
corner_radius_bottom_left: corner_radii.bottom_left,
sigma: shadow.sigma, sigma: shadow.sigma,
color: shadow.color.to_uchar4(), color: shadow.color.to_uchar4(),
}; };

View file

@ -34,7 +34,10 @@ typedef enum {
typedef struct { typedef struct {
vector_float2 origin; vector_float2 origin;
vector_float2 size; vector_float2 size;
float corner_radius; float corner_radius_top_left;
float corner_radius_top_right;
float corner_radius_bottom_right;
float corner_radius_bottom_left;
float sigma; float sigma;
vector_uchar4 color; vector_uchar4 color;
} GPUIShadow; } GPUIShadow;

View file

@ -146,7 +146,10 @@ struct ShadowFragmentInput {
float4 position [[position]]; float4 position [[position]];
vector_float2 origin; vector_float2 origin;
vector_float2 size; vector_float2 size;
float corner_radius; float corner_radius_top_left;
float corner_radius_top_right;
float corner_radius_bottom_right;
float corner_radius_bottom_left;
float sigma; float sigma;
vector_uchar4 color; vector_uchar4 color;
}; };
@ -169,7 +172,10 @@ vertex ShadowFragmentInput shadow_vertex(
device_position, device_position,
shadow.origin, shadow.origin,
shadow.size, shadow.size,
shadow.corner_radius, shadow.corner_radius_top_left,
shadow.corner_radius_top_right,
shadow.corner_radius_bottom_right,
shadow.corner_radius_bottom_left,
shadow.sigma, shadow.sigma,
shadow.color, shadow.color,
}; };
@ -179,10 +185,24 @@ fragment float4 shadow_fragment(
ShadowFragmentInput input [[stage_in]] ShadowFragmentInput input [[stage_in]]
) { ) {
float sigma = input.sigma; float sigma = input.sigma;
float corner_radius = input.corner_radius;
float2 half_size = input.size / 2.; float2 half_size = input.size / 2.;
float2 center = input.origin + half_size; float2 center = input.origin + half_size;
float2 point = input.position.xy - center; float2 point = input.position.xy - center;
float2 center_to_point = input.position.xy - center;
float corner_radius;
if (center_to_point.x < 0.) {
if (center_to_point.y < 0.) {
corner_radius = input.corner_radius_top_left;
} else {
corner_radius = input.corner_radius_bottom_left;
}
} else {
if (center_to_point.y < 0.) {
corner_radius = input.corner_radius_top_right;
} else {
corner_radius = input.corner_radius_bottom_right;
}
}
// The signal is only non-zero in a limited range, so don't waste samples // The signal is only non-zero in a limited range, so don't waste samples
float low = point.y - half_size.y; float low = point.y - half_size.y;

View file

@ -6,6 +6,7 @@ use collections::HashSet;
use derive_more::Mul; use derive_more::Mul;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::Deserialize; use serde::Deserialize;
use serde_derive::Serialize;
use serde_json::json; use serde_json::json;
use std::{borrow::Cow, sync::Arc}; use std::{borrow::Cow, sync::Arc};
@ -69,7 +70,7 @@ pub struct Quad {
pub corner_radii: CornerRadii, pub corner_radii: CornerRadii,
} }
#[derive(Default, Debug, Mul, Clone, Copy)] #[derive(Default, Debug, Mul, Clone, Copy, Deserialize, Serialize, JsonSchema)]
pub struct CornerRadii { pub struct CornerRadii {
pub top_left: f32, pub top_left: f32,
pub top_right: f32, pub top_right: f32,
@ -91,7 +92,7 @@ impl From<f32> for CornerRadii {
#[derive(Debug)] #[derive(Debug)]
pub struct Shadow { pub struct Shadow {
pub bounds: RectF, pub bounds: RectF,
pub corner_radius: f32, pub corner_radii: CornerRadii,
pub sigma: f32, pub sigma: f32,
pub color: Color, pub color: Color,
} }