From cc906c83cdf896d94b7ccf91258466714be631f6 Mon Sep 17 00:00:00 2001 From: Nick Senger Date: Wed, 8 Nov 2023 19:12:53 -0800 Subject: [PATCH 1/9] feat: quad shadows --- core/src/element.rs | 1 + core/src/lib.rs | 2 + core/src/renderer.rs | 5 +- core/src/shadow.rs | 15 ++++ examples/custom_quad/src/main.rs | 53 +++++++++++- examples/custom_widget/src/main.rs | 1 + examples/loading_spinners/src/linear.rs | 3 + examples/modal/src/main.rs | 1 + graphics/src/damage.rs | 25 +++++- graphics/src/primitive.rs | 6 ++ graphics/src/renderer.rs | 3 + src/lib.rs | 3 +- tiny_skia/src/backend.rs | 106 ++++++++++++++++++++++++ wgpu/src/layer.rs | 6 ++ wgpu/src/quad.rs | 9 ++ wgpu/src/quad/solid.rs | 6 ++ wgpu/src/shader/quad.wgsl | 18 ++-- wgpu/src/shader/quad/solid.wgsl | 36 ++++++-- widget/src/button.rs | 2 + widget/src/checkbox.rs | 1 + widget/src/container.rs | 1 + widget/src/overlay/menu.rs | 2 + widget/src/pane_grid.rs | 3 + widget/src/pick_list.rs | 1 + widget/src/progress_bar.rs | 2 + widget/src/radio.rs | 2 + widget/src/rule.rs | 1 + widget/src/scrollable.rs | 2 + widget/src/slider.rs | 3 + widget/src/text_editor.rs | 3 + widget/src/text_input.rs | 3 + widget/src/toggler.rs | 2 + widget/src/vertical_slider.rs | 3 + 33 files changed, 305 insertions(+), 25 deletions(-) create mode 100644 core/src/shadow.rs diff --git a/core/src/element.rs b/core/src/element.rs index 8b5102186a..b264ad7765 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -540,6 +540,7 @@ where border_color: color, border_width: 1.0, border_radius: 0.0.into(), + shadow: Default::default() }, Color::TRANSPARENT, ); diff --git a/core/src/lib.rs b/core/src/lib.rs index 864df6e6c3..b326d0f3ba 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -27,6 +27,7 @@ pub mod layout; pub mod mouse; pub mod overlay; pub mod renderer; +pub mod shadow; pub mod svg; pub mod text; pub mod time; @@ -70,6 +71,7 @@ pub use pixels::Pixels; pub use point::Point; pub use rectangle::Rectangle; pub use renderer::Renderer; +pub use shadow::Shadow; pub use shell::Shell; pub use size::Size; pub use text::Text; diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 1b327e563c..481048b066 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -5,7 +5,7 @@ mod null; #[cfg(debug_assertions)] pub use null::Null; -use crate::{Background, BorderRadius, Color, Rectangle, Vector}; +use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Vector}; /// A component that can be used by widgets to draw themselves on a screen. pub trait Renderer: Sized { @@ -45,6 +45,9 @@ pub struct Quad { /// The border color of the [`Quad`]. pub border_color: Color, + + /// The shadow of the [`Quad`]. + pub shadow: Shadow, } /// The styling attributes of a [`Renderer`]. diff --git a/core/src/shadow.rs b/core/src/shadow.rs new file mode 100644 index 0000000000..238ea36a00 --- /dev/null +++ b/core/src/shadow.rs @@ -0,0 +1,15 @@ +//! Shadow +use crate::{Color, Vector}; + +/// A shadow +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct Shadow { + /// The color of the shadow + pub color: Color, + + /// The offset of the shadow + pub offset: Vector, + + /// The blur_radius of the shadow + pub blur_radius: f32, +} diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index cc9ad528a7..01f4aa10af 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -3,21 +3,28 @@ mod quad { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::mouse; + use iced::{mouse, Shadow}; use iced::{Color, Element, Length, Rectangle, Size}; pub struct CustomQuad { size: f32, radius: [f32; 4], border_width: f32, + shadow: Shadow, } impl CustomQuad { - pub fn new(size: f32, radius: [f32; 4], border_width: f32) -> Self { + pub fn new( + size: f32, + radius: [f32; 4], + border_width: f32, + shadow: Shadow, + ) -> Self { Self { size, radius, border_width, + shadow, } } } @@ -58,6 +65,7 @@ mod quad { border_radius: self.radius.into(), border_width: self.border_width, border_color: Color::from_rgb(1.0, 0.0, 0.0), + shadow: self.shadow, }, Color::BLACK, ); @@ -75,7 +83,9 @@ mod quad { } use iced::widget::{column, container, slider, text}; -use iced::{Alignment, Element, Length, Sandbox, Settings}; +use iced::{ + Alignment, Color, Element, Length, Sandbox, Settings, Shadow, Vector, +}; pub fn main() -> iced::Result { Example::run(Settings::default()) @@ -84,6 +94,7 @@ pub fn main() -> iced::Result { struct Example { radius: [f32; 4], border_width: f32, + shadow: Shadow, } #[derive(Debug, Clone, Copy)] @@ -94,6 +105,9 @@ enum Message { RadiusBottomRightChanged(f32), RadiusBottomLeftChanged(f32), BorderWidthChanged(f32), + ShadowXOffsetChanged(f32), + ShadowYOffsetChanged(f32), + ShadowBlurRadiusChanged(f32), } impl Sandbox for Example { @@ -103,6 +117,11 @@ impl Sandbox for Example { Self { radius: [50.0; 4], border_width: 0.0, + shadow: Shadow { + color: Color::from_rgba(0.0, 0.0, 0.0, 0.8), + offset: Vector::new(0.0, 8.0), + blur_radius: 16.0, + }, } } @@ -128,14 +147,33 @@ impl Sandbox for Example { Message::BorderWidthChanged(width) => { self.border_width = width; } + Message::ShadowXOffsetChanged(x) => { + self.shadow.offset.x = x; + } + Message::ShadowYOffsetChanged(y) => { + self.shadow.offset.y = y; + } + Message::ShadowBlurRadiusChanged(s) => { + self.shadow.blur_radius = s; + } } } fn view(&self) -> Element { let [tl, tr, br, bl] = self.radius; + let Shadow { + offset: Vector { x: sx, y: sy }, + blur_radius: sr, + .. + } = self.shadow; let content = column![ - quad::CustomQuad::new(200.0, self.radius, self.border_width), + quad::CustomQuad::new( + 200.0, + self.radius, + self.border_width, + self.shadow + ), text(format!("Radius: {tl:.2}/{tr:.2}/{br:.2}/{bl:.2}")), slider(1.0..=100.0, tl, Message::RadiusTopLeftChanged).step(0.01), slider(1.0..=100.0, tr, Message::RadiusTopRightChanged).step(0.01), @@ -145,6 +183,13 @@ impl Sandbox for Example { .step(0.01), slider(1.0..=10.0, self.border_width, Message::BorderWidthChanged) .step(0.01), + text(format!("Shadow: {sx:.2}x{sy:.2}, {sr:.2}")), + slider(-100.0..=100.0, sx, Message::ShadowXOffsetChanged) + .step(0.01), + slider(-100.0..=100.0, sy, Message::ShadowYOffsetChanged) + .step(0.01), + slider(0.0..=100.0, sr, Message::ShadowBlurRadiusChanged) + .step(0.01), ] .padding(20) .spacing(20) diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index 7ffb4cd018..f5c34d6b2e 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -65,6 +65,7 @@ mod circle { border_radius: self.radius.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Color::BLACK, ); diff --git a/examples/loading_spinners/src/linear.rs b/examples/loading_spinners/src/linear.rs index 497e0834ee..86469681b9 100644 --- a/examples/loading_spinners/src/linear.rs +++ b/examples/loading_spinners/src/linear.rs @@ -228,6 +228,7 @@ where border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Background::Color(custom_style.track_color), ); @@ -244,6 +245,7 @@ where border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Background::Color(custom_style.bar_color), ), @@ -261,6 +263,7 @@ where border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Background::Color(custom_style.bar_color), ), diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 963c839ea6..531a19b54e 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -477,6 +477,7 @@ mod modal { border_radius: BorderRadius::default(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Color { a: 0.80, diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs index 59e9f5b4c0..2aec9b251d 100644 --- a/graphics/src/damage.rs +++ b/graphics/src/damage.rs @@ -78,9 +78,28 @@ impl Damage for Primitive { // damage bounds (?) raw.clip_bounds.expand(1.5) } - Self::Quad { bounds, .. } - | Self::Image { bounds, .. } - | Self::Svg { bounds, .. } => bounds.expand(1.0), + Self::Quad { + bounds, + shadow_offset, + shadow_blur_radius, + .. + } => { + let bounds_with_shadow = Rectangle { + x: bounds.x + shadow_offset.x.min(0.0) - shadow_blur_radius, + y: bounds.y + shadow_offset.y.min(0.0) - shadow_blur_radius, + width: bounds.width + + shadow_offset.x.abs() + + shadow_blur_radius * 2.0, + height: bounds.height + + shadow_offset.y.abs() + + shadow_blur_radius * 2.0, + }; + + bounds_with_shadow.expand(1.0) + } + Self::Image { bounds, .. } | Self::Svg { bounds, .. } => { + bounds.expand(1.0) + } Self::Clip { bounds, .. } => bounds.expand(1.0), Self::Group { primitives } => primitives .iter() diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index 20affaaf66..795d960985 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -71,6 +71,12 @@ pub enum Primitive { border_width: f32, /// The border color of the quad border_color: Color, + /// The shadow color of the quad + shadow_color: Color, + /// The shadow offset of the quad + shadow_offset: Vector, + /// The shadow blur radius of the quad + shadow_blur_radius: f32, }, /// An image primitive Image { diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 1b0f5c5b3a..bd640097a6 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -127,6 +127,9 @@ impl iced_core::Renderer for Renderer { border_radius: quad.border_radius.into(), border_width: quad.border_width, border_color: quad.border_color, + shadow_color: quad.shadow.color, + shadow_offset: quad.shadow.offset, + shadow_blur_radius: quad.shadow.blur_radius, }); } diff --git a/src/lib.rs b/src/lib.rs index 446590ec7c..02bb227a62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -191,7 +191,8 @@ pub use crate::core::alignment; pub use crate::core::gradient; pub use crate::core::{ color, Alignment, Background, BorderRadius, Color, ContentFit, Degrees, - Gradient, Length, Padding, Pixels, Point, Radians, Rectangle, Size, Vector, + Gradient, Length, Padding, Pixels, Point, Radians, Rectangle, Shadow, Size, + Vector, }; pub mod clipboard { diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index d1393b4d7a..b62f20d512 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -1,3 +1,5 @@ +use tiny_skia::Size; + use crate::core::{Background, Color, Gradient, Rectangle, Vector}; use crate::graphics::backend; use crate::graphics::text; @@ -153,6 +155,9 @@ impl Backend { border_radius, border_width, border_color, + shadow_color, + shadow_offset, + shadow_blur_radius, } => { let physical_bounds = (*bounds + translation) * scale_factor; @@ -182,6 +187,107 @@ impl Backend { } let path = rounded_rectangle(*bounds, fill_border_radius); + if shadow_color.a > 0.0 { + fn smoothstep(a: f32, b: f32, x: f32) -> f32 { + let x = ((x - a) / (b - a)).clamp(0.0, 1.0); + + x * x * (3.0 - 2.0 * x) + } + + fn rounded_box_sdf( + to_center: Vector, + size: Size, + radii: &[f32], + ) -> f32 { + let radius = + match (to_center.x > 0.0, to_center.y > 0.0) { + (true, true) => radii[2], + (true, false) => radii[1], + (false, true) => radii[3], + (false, false) => radii[0], + }; + + let x = (to_center.x.abs() - size.width() + radius) + .max(0.0); + let y = (to_center.y.abs() - size.height() + radius) + .max(0.0); + + (x.powf(2.0) + y.powf(2.0)).sqrt() - radius + } + + let shadow_bounds = (Rectangle { + x: bounds.x + shadow_offset.x - shadow_blur_radius, + y: bounds.y + shadow_offset.y - shadow_blur_radius, + width: bounds.width + shadow_blur_radius * 2.0, + height: bounds.height + shadow_blur_radius * 2.0, + } + translation) + * scale_factor; + + let radii = fill_border_radius + .into_iter() + .map(|radius| radius * scale_factor) + .collect::>(); + let (x, y, width, height) = ( + shadow_bounds.x as u32, + shadow_bounds.y as u32, + shadow_bounds.width as u32, + shadow_bounds.height as u32, + ); + let half_width = physical_bounds.width / 2.0; + let half_height = physical_bounds.height / 2.0; + + let colors = (y..y + height) + .flat_map(|y| { + (x..x + width).map(move |x| (x as f32, y as f32)) + }) + .filter_map(|(x, y)| { + Size::from_wh(half_width, half_height).map(|size| { + let shadow_distance = rounded_box_sdf( + Vector::new( + x - physical_bounds.position().x + - (shadow_offset.x * scale_factor) + - half_width, + y - physical_bounds.position().y + - (shadow_offset.y * scale_factor) + - half_height, + ), + size, + &radii, + ); + let shadow_alpha = 1.0 + - smoothstep( + -shadow_blur_radius * scale_factor, + *shadow_blur_radius * scale_factor, + shadow_distance, + ); + + let mut color = into_color(*shadow_color); + color.apply_opacity(shadow_alpha); + + color.to_color_u8().premultiply() + }) + }) + .collect(); + + if let Some(p) = tiny_skia::IntSize::from_wh(width, height) + .and_then(|size| { + tiny_skia::Pixmap::from_vec( + bytemuck::cast_vec(colors), + size, + ) + }) + { + pixels.draw_pixmap( + x as i32, + y as i32, + p.as_ref(), + &Default::default(), + Default::default(), + None, + ) + } + } + pixels.fill_path( &path, &tiny_skia::Paint { diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 4ad12a883c..7b54601bb4 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -198,6 +198,9 @@ impl<'a> Layer<'a> { border_radius, border_width, border_color, + shadow_color, + shadow_offset, + shadow_blur_radius, } => { let layer = &mut layers[current_layer]; @@ -210,6 +213,9 @@ impl<'a> Layer<'a> { border_color: color::pack(*border_color), border_radius: *border_radius, border_width: *border_width, + shadow_color: shadow_color.into_linear(), + shadow_offset: (*shadow_offset).into(), + shadow_blur_radius: *shadow_blur_radius, }; layer.quads.add(quad, background); diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 4bcf9a6658..cda1bec974 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -201,6 +201,15 @@ pub struct Quad { /// The border width of the [`Quad`]. pub border_width: f32, + + /// The shadow color of the [`Quad`]. + pub shadow_color: [f32; 4], + + /// The shadow offset of the [`Quad`]. + pub shadow_offset: [f32; 2], + + /// The shadow blur radius of the [`Quad`]. + pub shadow_blur_radius: f32, } /// A group of [`Quad`]s rendered together. diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index 90e7f98e3d..771eee34fb 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -105,6 +105,12 @@ impl Pipeline { 4 => Float32x4, // Border width 5 => Float32, + // Shadow color + 6 => Float32x4, + // Shadow offset + 7 => Float32x2, + // Shadow blur radius + 8 => Float32, ), }], }, diff --git a/wgpu/src/shader/quad.wgsl b/wgpu/src/shader/quad.wgsl index f919cfe24e..4de7336267 100644 --- a/wgpu/src/shader/quad.wgsl +++ b/wgpu/src/shader/quad.wgsl @@ -11,19 +11,15 @@ fn distance_alg( size: vec2, radius: f32 ) -> f32 { - var inner_size: vec2 = size - vec2(radius, radius) * 2.0; + var inner_half_size: vec2 = (size - vec2(radius, radius) * 2.0) / 2.0; var top_left: vec2 = position + vec2(radius, radius); - var bottom_right: vec2 = top_left + inner_size; - - var top_left_distance: vec2 = top_left - frag_coord; - var bottom_right_distance: vec2 = frag_coord - bottom_right; - - var dist: vec2 = vec2( - max(max(top_left_distance.x, bottom_right_distance.x), 0.0), - max(max(top_left_distance.y, bottom_right_distance.y), 0.0) - ); + return rounded_box_sdf(frag_coord - top_left - inner_half_size, inner_half_size, 0.0); +} - return sqrt(dist.x * dist.x + dist.y * dist.y); +// Given a vector from a point to the center of a rounded rectangle of the given `size` and +// border `radius`, determines the point's distance from the nearest edge of the rounded rectangle +fn rounded_box_sdf(to_center: vec2, size: vec2, radius: f32) -> f32 { + return length(max(abs(to_center) - size + vec2(radius, radius), vec2(0.0, 0.0))) - radius; } // Based on the fragement position and the center of the quad, select one of the 4 radi. diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl index f84dd7abb7..cb4a38162e 100644 --- a/wgpu/src/shader/quad/solid.wgsl +++ b/wgpu/src/shader/quad/solid.wgsl @@ -6,6 +6,9 @@ struct SolidVertexInput { @location(3) border_color: vec4, @location(4) border_radius: vec4, @location(5) border_width: f32, + @location(6) shadow_color: vec4, + @location(7) shadow_offset: vec2, + @location(8) shadow_blur_radius: f32, } struct SolidVertexOutput { @@ -16,14 +19,19 @@ struct SolidVertexOutput { @location(3) scale: vec2, @location(4) border_radius: vec4, @location(5) border_width: f32, + @location(6) shadow_color: vec4, + @location(7) shadow_offset: vec2, + @location(8) shadow_blur_radius: f32, } @vertex fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { var out: SolidVertexOutput; - var pos: vec2 = input.pos * globals.scale; - var scale: vec2 = input.scale * globals.scale; + var pos: vec2 = (input.pos + min(input.shadow_offset, vec2(0.0, 0.0)) - input.shadow_blur_radius) * globals.scale; + var quad_pos: vec2 = input.pos * globals.scale; + var scale: vec2 = (input.scale + vec2(abs(input.shadow_offset.x), abs(input.shadow_offset.y)) + input.shadow_blur_radius * 2.0) * globals.scale; + var quad_scale: vec2 = input.scale * globals.scale; var min_border_radius = min(input.scale.x, input.scale.y) * 0.5; var border_radius: vec4 = vec4( @@ -43,10 +51,13 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { out.position = globals.transform * transform * vec4(vertex_position(input.vertex_index), 0.0, 1.0); out.color = input.color; out.border_color = input.border_color; - out.pos = pos; - out.scale = scale; + out.pos = quad_pos; + out.scale = quad_scale; out.border_radius = border_radius * globals.scale; out.border_width = input.border_width * globals.scale; + out.shadow_color = input.shadow_color; + out.shadow_offset = input.shadow_offset * globals.scale; + out.shadow_blur_radius = input.shadow_blur_radius * globals.scale; return out; } @@ -95,5 +106,20 @@ fn solid_fs_main( dist ); - return vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); + let quad_color = vec4(mixed_color.x, mixed_color.y, mixed_color.z, mixed_color.w * radius_alpha); + + if input.shadow_color.a > 0.0 { + let shadow_distance = rounded_box_sdf(input.position.xy - input.pos - input.shadow_offset - (input.scale / 2.0), input.scale / 2.0, border_radius); + let shadow_alpha = 1.0 - smoothstep(-input.shadow_blur_radius, input.shadow_blur_radius, shadow_distance); + let shadow_color = input.shadow_color; + let base_color = select( + vec4(shadow_color.x, shadow_color.y, shadow_color.z, 0.0), + quad_color, + quad_color.a > 0.0 + ); + + return mix(base_color, shadow_color, (1.0 - radius_alpha) * shadow_alpha); + } else { + return quad_color; + } } diff --git a/widget/src/button.rs b/widget/src/button.rs index 0ebb8dcc39..44628a6ab5 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -404,6 +404,7 @@ where border_radius: styling.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, Background::Color([0.0, 0.0, 0.0, 0.5].into()), ); @@ -415,6 +416,7 @@ where border_radius: styling.border_radius, border_width: styling.border_width, border_color: styling.border_color, + shadow: Default::default(), }, styling .background diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 0353b3adb7..5cc79b0898 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -287,6 +287,7 @@ where border_radius: custom_style.border_radius, border_width: custom_style.border_width, border_color: custom_style.border_color, + shadow: Default::default(), }, custom_style.background, ); diff --git a/widget/src/container.rs b/widget/src/container.rs index cffb0458a9..519d4f150b 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -344,6 +344,7 @@ pub fn draw_background( border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, + shadow: Default::default(), }, appearance .background diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index f83eebea37..03935e598e 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -309,6 +309,7 @@ where border_color: appearance.border_color, border_width: appearance.border_width, border_radius: appearance.border_radius, + shadow: Default::default(), }, appearance.background, ); @@ -519,6 +520,7 @@ where border_color: Color::TRANSPARENT, border_width: 0.0, border_radius: appearance.border_radius, + shadow: Default::default(), }, appearance.selected_background, ); diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index cf1f0455e4..fc30716df0 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -921,6 +921,7 @@ pub fn draw( .border_radius, border_width: hovered_region_style.border_width, border_color: hovered_region_style.border_color, + shadow: Default::default(), }, theme.hovered_region(style).background, ); @@ -950,6 +951,7 @@ pub fn draw( border_radius: hovered_region_style.border_radius, border_width: hovered_region_style.border_width, border_color: hovered_region_style.border_color, + shadow: Default::default(), }, theme.hovered_region(style).background, ); @@ -1013,6 +1015,7 @@ pub fn draw( border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, highlight.color, ); diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 2e3aab6fe9..8931aa9937 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -656,6 +656,7 @@ pub fn draw<'a, T, Renderer>( border_color: style.border_color, border_width: style.border_width, border_radius: style.border_radius, + shadow: Default::default(), }, style.background, ); diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 15f1277b8a..1e0f2a8287 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -133,6 +133,7 @@ where border_radius: style.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.background, ); @@ -147,6 +148,7 @@ where border_radius: style.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.bar, ); diff --git a/widget/src/radio.rs b/widget/src/radio.rs index f91b20b159..0a33825f0f 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -315,6 +315,7 @@ where border_radius: (size / 2.0).into(), border_width: custom_style.border_width, border_color: custom_style.border_color, + shadow: Default::default(), }, custom_style.background, ); @@ -331,6 +332,7 @@ where border_radius: (dot_size / 2.0).into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, custom_style.dot_color, ); diff --git a/widget/src/rule.rs b/widget/src/rule.rs index cded9cb1d1..4a83e9d1a1 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -127,6 +127,7 @@ where border_radius: style.radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.color, ); diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 70db490a96..82602a4147 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -912,6 +912,7 @@ pub fn draw( border_radius: style.border_radius, border_width: style.border_width, border_color: style.border_color, + shadow: Default::default(), }, style .background @@ -932,6 +933,7 @@ pub fn draw( border_radius: style.scroller.border_radius, border_width: style.scroller.border_width, border_color: style.scroller.border_color, + shadow: Default::default(), }, style.scroller.color, ); diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 1bc946611d..d89f50e04c 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -401,6 +401,7 @@ pub fn draw( border_radius: style.rail.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.rail.colors.0, ); @@ -416,6 +417,7 @@ pub fn draw( border_radius: style.rail.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.rail.colors.1, ); @@ -431,6 +433,7 @@ pub fn draw( border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, + shadow: Default::default(), }, style.handle.color, ); diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 09a0cac0bf..3f3ccf72b5 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -470,6 +470,7 @@ where border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, + shadow: Default::default(), }, appearance.background, ); @@ -511,6 +512,7 @@ where border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, theme.value_color(&self.style), ); @@ -526,6 +528,7 @@ where border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, theme.selection_color(&self.style), ); diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index c3dce8bef6..f8e6c7f842 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -1085,6 +1085,7 @@ pub fn draw( border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, + shadow: Default::default(), }, appearance.background, ); @@ -1134,6 +1135,7 @@ pub fn draw( border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, theme.value_color(style), )) @@ -1175,6 +1177,7 @@ pub fn draw( border_radius: 0.0.into(), border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, theme.selection_color(style), )), diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index 941159ea6a..f7fb5d5880 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -317,6 +317,7 @@ where border_color: style .background_border .unwrap_or(style.background), + shadow: Default::default(), }, style.background, ); @@ -341,6 +342,7 @@ where border_color: style .foreground_border .unwrap_or(style.foreground), + shadow: Default::default(), }, style.foreground, ); diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index a3029d766b..4fdad86179 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -400,6 +400,7 @@ pub fn draw( border_radius: style.rail.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.rail.colors.1, ); @@ -415,6 +416,7 @@ pub fn draw( border_radius: style.rail.border_radius, border_width: 0.0, border_color: Color::TRANSPARENT, + shadow: Default::default(), }, style.rail.colors.0, ); @@ -430,6 +432,7 @@ pub fn draw( border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, + shadow: Default::default(), }, style.handle.color, ); From 83902921a3065e8dadfaca23c2e03dd770d93780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 12:02:04 +0100 Subject: [PATCH 2/9] Run `cargo fmt` --- core/src/element.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/element.rs b/core/src/element.rs index b264ad7765..a39919d346 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -540,7 +540,7 @@ where border_color: color, border_width: 1.0, border_radius: 0.0.into(), - shadow: Default::default() + shadow: Default::default(), }, Color::TRANSPARENT, ); From b7b457a575cdd103915994f640c50262ce30a7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 12:11:18 +0100 Subject: [PATCH 3/9] Make `shadow` optional in `renderer::Quad` --- core/src/renderer.rs | 16 ++++++++++++++-- core/src/shadow.rs | 4 ++-- examples/custom_quad/src/main.rs | 2 +- graphics/src/damage.rs | 21 ++++++++++----------- graphics/src/primitive.rs | 12 +++++------- graphics/src/renderer.rs | 4 +--- tiny_skia/src/backend.rs | 24 +++++++++++------------- wgpu/src/layer.rs | 20 +++++++++++++------- 8 files changed, 57 insertions(+), 46 deletions(-) diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 481048b066..1ca62559ea 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -5,7 +5,7 @@ mod null; #[cfg(debug_assertions)] pub use null::Null; -use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Vector}; +use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Size, Vector}; /// A component that can be used by widgets to draw themselves on a screen. pub trait Renderer: Sized { @@ -47,7 +47,19 @@ pub struct Quad { pub border_color: Color, /// The shadow of the [`Quad`]. - pub shadow: Shadow, + pub shadow: Option, +} + +impl Default for Quad { + fn default() -> Self { + Self { + bounds: Rectangle::with_size(Size::ZERO), + border_radius: 0.0.into(), + border_width: 0.0, + border_color: Color::TRANSPARENT, + shadow: None, + } + } } /// The styling attributes of a [`Renderer`]. diff --git a/core/src/shadow.rs b/core/src/shadow.rs index 238ea36a00..de8ce1c314 100644 --- a/core/src/shadow.rs +++ b/core/src/shadow.rs @@ -2,7 +2,7 @@ use crate::{Color, Vector}; /// A shadow -#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct Shadow { /// The color of the shadow pub color: Color, @@ -10,6 +10,6 @@ pub struct Shadow { /// The offset of the shadow pub offset: Vector, - /// The blur_radius of the shadow + /// The blur radius of the shadow pub blur_radius: f32, } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index 01f4aa10af..e3f110bbc1 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -65,7 +65,7 @@ mod quad { border_radius: self.radius.into(), border_width: self.border_width, border_color: Color::from_rgb(1.0, 0.0, 0.0), - shadow: self.shadow, + shadow: Some(self.shadow), }, Color::BLACK, ); diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs index 2aec9b251d..cced0c97bf 100644 --- a/graphics/src/damage.rs +++ b/graphics/src/damage.rs @@ -80,26 +80,25 @@ impl Damage for Primitive { } Self::Quad { bounds, - shadow_offset, - shadow_blur_radius, + shadow: Some(shadow), .. } => { let bounds_with_shadow = Rectangle { - x: bounds.x + shadow_offset.x.min(0.0) - shadow_blur_radius, - y: bounds.y + shadow_offset.y.min(0.0) - shadow_blur_radius, + x: bounds.x + shadow.offset.x.min(0.0) - shadow.blur_radius, + y: bounds.y + shadow.offset.y.min(0.0) - shadow.blur_radius, width: bounds.width - + shadow_offset.x.abs() - + shadow_blur_radius * 2.0, + + shadow.offset.x.abs() + + shadow.blur_radius * 2.0, height: bounds.height - + shadow_offset.y.abs() - + shadow_blur_radius * 2.0, + + shadow.offset.y.abs() + + shadow.blur_radius * 2.0, }; bounds_with_shadow.expand(1.0) } - Self::Image { bounds, .. } | Self::Svg { bounds, .. } => { - bounds.expand(1.0) - } + Self::Quad { bounds, .. } + | Self::Image { bounds, .. } + | Self::Svg { bounds, .. } => bounds.expand(1.0), Self::Clip { bounds, .. } => bounds.expand(1.0), Self::Group { primitives } => primitives .iter() diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index 795d960985..a428c31aa9 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -3,7 +3,9 @@ use crate::core::alignment; use crate::core::image; use crate::core::svg; use crate::core::text; -use crate::core::{Background, Color, Font, Pixels, Point, Rectangle, Vector}; +use crate::core::{ + Background, Color, Font, Pixels, Point, Rectangle, Shadow, Vector, +}; use crate::text::editor; use crate::text::paragraph; @@ -71,12 +73,8 @@ pub enum Primitive { border_width: f32, /// The border color of the quad border_color: Color, - /// The shadow color of the quad - shadow_color: Color, - /// The shadow offset of the quad - shadow_offset: Vector, - /// The shadow blur radius of the quad - shadow_blur_radius: f32, + /// The [`Shadow`] of the quad + shadow: Option, }, /// An image primitive Image { diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index bd640097a6..6f31233143 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -127,9 +127,7 @@ impl iced_core::Renderer for Renderer { border_radius: quad.border_radius.into(), border_width: quad.border_width, border_color: quad.border_color, - shadow_color: quad.shadow.color, - shadow_offset: quad.shadow.offset, - shadow_blur_radius: quad.shadow.blur_radius, + shadow: quad.shadow, }); } diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index b62f20d512..ae1abc8410 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -155,9 +155,7 @@ impl Backend { border_radius, border_width, border_color, - shadow_color, - shadow_offset, - shadow_blur_radius, + shadow, } => { let physical_bounds = (*bounds + translation) * scale_factor; @@ -187,7 +185,7 @@ impl Backend { } let path = rounded_rectangle(*bounds, fill_border_radius); - if shadow_color.a > 0.0 { + if let Some(shadow) = shadow { fn smoothstep(a: f32, b: f32, x: f32) -> f32 { let x = ((x - a) / (b - a)).clamp(0.0, 1.0); @@ -216,10 +214,10 @@ impl Backend { } let shadow_bounds = (Rectangle { - x: bounds.x + shadow_offset.x - shadow_blur_radius, - y: bounds.y + shadow_offset.y - shadow_blur_radius, - width: bounds.width + shadow_blur_radius * 2.0, - height: bounds.height + shadow_blur_radius * 2.0, + x: bounds.x + shadow.offset.x - shadow.blur_radius, + y: bounds.y + shadow.offset.y - shadow.blur_radius, + width: bounds.width + shadow.blur_radius * 2.0, + height: bounds.height + shadow.blur_radius * 2.0, } + translation) * scale_factor; @@ -245,10 +243,10 @@ impl Backend { let shadow_distance = rounded_box_sdf( Vector::new( x - physical_bounds.position().x - - (shadow_offset.x * scale_factor) + - (shadow.offset.x * scale_factor) - half_width, y - physical_bounds.position().y - - (shadow_offset.y * scale_factor) + - (shadow.offset.y * scale_factor) - half_height, ), size, @@ -256,12 +254,12 @@ impl Backend { ); let shadow_alpha = 1.0 - smoothstep( - -shadow_blur_radius * scale_factor, - *shadow_blur_radius * scale_factor, + -shadow.blur_radius * scale_factor, + shadow.blur_radius * scale_factor, shadow_distance, ); - let mut color = into_color(*shadow_color); + let mut color = into_color(shadow.color); color.apply_opacity(shadow_alpha); color.to_color_u8().premultiply() diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 7b54601bb4..cb91878d73 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -12,7 +12,9 @@ pub use text::Text; use crate::core; use crate::core::alignment; -use crate::core::{Color, Font, Pixels, Point, Rectangle, Size, Vector}; +use crate::core::{ + Color, Font, Pixels, Point, Rectangle, Shadow, Size, Vector, +}; use crate::graphics; use crate::graphics::color; use crate::graphics::Viewport; @@ -198,12 +200,16 @@ impl<'a> Layer<'a> { border_radius, border_width, border_color, - shadow_color, - shadow_offset, - shadow_blur_radius, + shadow, } => { let layer = &mut layers[current_layer]; + let shadow = shadow.unwrap_or_else(|| Shadow { + color: Color::TRANSPARENT, + offset: Vector::ZERO, + blur_radius: 0.0, + }); + let quad = Quad { position: [ bounds.x + translation.x, @@ -213,9 +219,9 @@ impl<'a> Layer<'a> { border_color: color::pack(*border_color), border_radius: *border_radius, border_width: *border_width, - shadow_color: shadow_color.into_linear(), - shadow_offset: (*shadow_offset).into(), - shadow_blur_radius: *shadow_blur_radius, + shadow_color: shadow.color.into_linear(), + shadow_offset: shadow.offset.into(), + shadow_blur_radius: shadow.blur_radius, }; layer.quads.add(quad, background); From 370b2f6df799c948188d3949e34112258b2a8498 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 12:25:07 +0100 Subject: [PATCH 4/9] Use `Default` implementation of `renderer::Quad` --- core/src/element.rs | 3 +-- examples/custom_widget/src/main.rs | 4 +--- examples/loading_spinners/src/linear.rs | 17 ++++------------- examples/modal/src/main.rs | 4 +--- tiny_skia/src/backend.rs | 25 +++++++++++++------------ widget/src/button.rs | 6 ++---- widget/src/checkbox.rs | 2 +- widget/src/container.rs | 2 +- widget/src/overlay/menu.rs | 8 +++----- widget/src/pane_grid.rs | 13 +++++-------- widget/src/pick_list.rs | 2 +- widget/src/progress_bar.rs | 10 +++------- widget/src/radio.rs | 9 +++------ widget/src/rule.rs | 8 ++------ widget/src/scrollable.rs | 4 ++-- widget/src/slider.rs | 14 +++++--------- widget/src/text_editor.rs | 15 ++++----------- widget/src/text_input.rs | 16 +++++----------- widget/src/toggler.rs | 4 ++-- widget/src/vertical_slider.rs | 13 ++++--------- 20 files changed, 63 insertions(+), 116 deletions(-) diff --git a/core/src/element.rs b/core/src/element.rs index a39919d346..e57ad77710 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -539,8 +539,7 @@ where bounds: layout.bounds(), border_color: color, border_width: 1.0, - border_radius: 0.0.into(), - shadow: Default::default(), + ..renderer::Quad::default() }, Color::TRANSPARENT, ); diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index f5c34d6b2e..6578183d3a 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -63,9 +63,7 @@ mod circle { renderer::Quad { bounds: layout.bounds(), border_radius: self.radius.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Color::BLACK, ); diff --git a/examples/loading_spinners/src/linear.rs b/examples/loading_spinners/src/linear.rs index 86469681b9..03aee9b191 100644 --- a/examples/loading_spinners/src/linear.rs +++ b/examples/loading_spinners/src/linear.rs @@ -225,10 +225,7 @@ where width: bounds.width, height: bounds.height, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Background::Color(custom_style.track_color), ); @@ -242,10 +239,7 @@ where width: self.easing.y_at_x(*progress) * bounds.width, height: bounds.height, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Background::Color(custom_style.bar_color), ), @@ -260,10 +254,7 @@ where * bounds.width, height: bounds.height, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Background::Color(custom_style.bar_color), ), @@ -291,7 +282,7 @@ pub struct Appearance { pub bar_color: Color, } -impl std::default::Default for Appearance { +impl Default for Appearance { fn default() -> Self { Self { track_color: Color::TRANSPARENT, diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 531a19b54e..59287c0638 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -475,9 +475,7 @@ mod modal { renderer::Quad { bounds: layout.bounds(), border_radius: BorderRadius::default(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Color { a: 0.80, diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index ae1abc8410..5321d8c664 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -267,22 +267,23 @@ impl Backend { }) .collect(); - if let Some(p) = tiny_skia::IntSize::from_wh(width, height) - .and_then(|size| { - tiny_skia::Pixmap::from_vec( - bytemuck::cast_vec(colors), - size, - ) - }) - { + if let Some(pixmap) = tiny_skia::IntSize::from_wh( + width, height, + ) + .and_then(|size| { + tiny_skia::Pixmap::from_vec( + bytemuck::cast_vec(colors), + size, + ) + }) { pixels.draw_pixmap( x as i32, y as i32, - p.as_ref(), - &Default::default(), - Default::default(), + pixmap.as_ref(), + &tiny_skia::PixmapPaint::default(), + tiny_skia::Transform::default(), None, - ) + ); } } diff --git a/widget/src/button.rs b/widget/src/button.rs index 44628a6ab5..f9e59f2341 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -402,9 +402,7 @@ where ..bounds }, border_radius: styling.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, Background::Color([0.0, 0.0, 0.0, 0.5].into()), ); @@ -416,7 +414,7 @@ where border_radius: styling.border_radius, border_width: styling.border_width, border_color: styling.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, styling .background diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 5cc79b0898..80397c134a 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -287,7 +287,7 @@ where border_radius: custom_style.border_radius, border_width: custom_style.border_width, border_color: custom_style.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, custom_style.background, ); diff --git a/widget/src/container.rs b/widget/src/container.rs index 519d4f150b..b3d2f360f4 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -344,7 +344,7 @@ pub fn draw_background( border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, appearance .background diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 03935e598e..2086e9931b 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -10,7 +10,7 @@ use crate::core::text::{self, Text}; use crate::core::touch; use crate::core::widget::Tree; use crate::core::{ - Clipboard, Color, Length, Padding, Pixels, Point, Rectangle, Size, Vector, + Clipboard, Length, Padding, Pixels, Point, Rectangle, Size, Vector, }; use crate::core::{Element, Shell, Widget}; use crate::scrollable::{self, Scrollable}; @@ -309,7 +309,7 @@ where border_color: appearance.border_color, border_width: appearance.border_width, border_radius: appearance.border_radius, - shadow: Default::default(), + ..renderer::Quad::default() }, appearance.background, ); @@ -517,10 +517,8 @@ where width: bounds.width - appearance.border_width * 2.0, ..bounds }, - border_color: Color::TRANSPARENT, - border_width: 0.0, border_radius: appearance.border_radius, - shadow: Default::default(), + ..renderer::Quad::default() }, appearance.selected_background, ); diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index fc30716df0..38ae17f043 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -42,8 +42,8 @@ use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Color, Element, Layout, Length, Pixels, Point, Rectangle, Shell, - Size, Vector, Widget, + Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, Shell, Size, + Vector, Widget, }; /// A collection of panes distributed using either vertical or horizontal splits @@ -921,7 +921,7 @@ pub fn draw( .border_radius, border_width: hovered_region_style.border_width, border_color: hovered_region_style.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.hovered_region(style).background, ); @@ -951,7 +951,7 @@ pub fn draw( border_radius: hovered_region_style.border_radius, border_width: hovered_region_style.border_width, border_color: hovered_region_style.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.hovered_region(style).background, ); @@ -1012,10 +1012,7 @@ pub fn draw( height: split_region.height, }, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, highlight.color, ); diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 8931aa9937..ef0c0eb34c 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -656,7 +656,7 @@ pub fn draw<'a, T, Renderer>( border_color: style.border_color, border_width: style.border_width, border_radius: style.border_radius, - shadow: Default::default(), + ..renderer::Quad::default() }, style.background, ); diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 1e0f2a8287..1d48ff7300 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -3,7 +3,7 @@ use crate::core::layout; use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{Color, Element, Layout, Length, Rectangle, Size, Widget}; +use crate::core::{Element, Layout, Length, Rectangle, Size, Widget}; use std::ops::RangeInclusive; @@ -131,9 +131,7 @@ where renderer::Quad { bounds: Rectangle { ..bounds }, border_radius: style.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.background, ); @@ -146,9 +144,7 @@ where ..bounds }, border_radius: style.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.bar, ); diff --git a/widget/src/radio.rs b/widget/src/radio.rs index 0a33825f0f..a782812ed2 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -9,8 +9,7 @@ use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Color, Element, Layout, Length, Pixels, Rectangle, Shell, Size, - Widget, + Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, }; pub use iced_style::radio::{Appearance, StyleSheet}; @@ -315,7 +314,7 @@ where border_radius: (size / 2.0).into(), border_width: custom_style.border_width, border_color: custom_style.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, custom_style.background, ); @@ -330,9 +329,7 @@ where height: bounds.height - dot_size, }, border_radius: (dot_size / 2.0).into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, custom_style.dot_color, ); diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 4a83e9d1a1..813b0e46d7 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -3,9 +3,7 @@ use crate::core::layout; use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{ - Color, Element, Layout, Length, Pixels, Rectangle, Size, Widget, -}; +use crate::core::{Element, Layout, Length, Pixels, Rectangle, Size, Widget}; pub use crate::style::rule::{Appearance, FillMode, StyleSheet}; @@ -125,9 +123,7 @@ where renderer::Quad { bounds, border_radius: style.radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.color, ); diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 82602a4147..beaad704fd 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -912,7 +912,7 @@ pub fn draw( border_radius: style.border_radius, border_width: style.border_width, border_color: style.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, style .background @@ -933,7 +933,7 @@ pub fn draw( border_radius: style.scroller.border_radius, border_width: style.scroller.border_width, border_color: style.scroller.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, style.scroller.color, ); diff --git a/widget/src/slider.rs b/widget/src/slider.rs index d89f50e04c..d12e0ebe67 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -8,8 +8,8 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Color, Element, Layout, Length, Pixels, Point, Rectangle, Shell, - Size, Widget, + Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, Shell, Size, + Widget, }; use std::ops::RangeInclusive; @@ -399,9 +399,7 @@ pub fn draw( height: style.rail.width, }, border_radius: style.rail.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.rail.colors.0, ); @@ -415,9 +413,7 @@ pub fn draw( height: style.rail.width, }, border_radius: style.rail.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.rail.colors.1, ); @@ -433,7 +429,7 @@ pub fn draw( border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, style.handle.color, ); diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 3f3ccf72b5..01ab126282 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -10,8 +10,7 @@ use crate::core::text::highlighter::{self, Highlighter}; use crate::core::text::{self, LineHeight}; use crate::core::widget::{self, Widget}; use crate::core::{ - Clipboard, Color, Element, Length, Padding, Pixels, Rectangle, Shell, Size, - Vector, + Clipboard, Element, Length, Padding, Pixels, Rectangle, Shell, Size, Vector, }; use std::cell::RefCell; @@ -470,7 +469,7 @@ where border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, appearance.background, ); @@ -509,10 +508,7 @@ where ) .into(), }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.value_color(&self.style), ); @@ -525,10 +521,7 @@ where renderer.fill_quad( renderer::Quad { bounds: range, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.selection_color(&self.style), ); diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index f8e6c7f842..7b15f58ca2 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -26,8 +26,8 @@ use crate::core::widget::operation::{self, Operation}; use crate::core::widget::tree::{self, Tree}; use crate::core::window; use crate::core::{ - Clipboard, Color, Element, Layout, Length, Padding, Pixels, Point, - Rectangle, Shell, Size, Vector, Widget, + Clipboard, Element, Layout, Length, Padding, Pixels, Point, Rectangle, + Shell, Size, Vector, Widget, }; use crate::runtime::Command; @@ -1085,7 +1085,7 @@ pub fn draw( border_radius: appearance.border_radius, border_width: appearance.border_width, border_color: appearance.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, appearance.background, ); @@ -1132,10 +1132,7 @@ pub fn draw( width: 1.0, height: text_bounds.height, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.value_color(style), )) @@ -1174,10 +1171,7 @@ pub fn draw( width, height: text_bounds.height, }, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, theme.selection_color(style), )), diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index f7fb5d5880..0bafffe1fc 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -317,7 +317,7 @@ where border_color: style .background_border .unwrap_or(style.background), - shadow: Default::default(), + ..renderer::Quad::default() }, style.background, ); @@ -342,7 +342,7 @@ where border_color: style .foreground_border .unwrap_or(style.foreground), - shadow: Default::default(), + ..renderer::Quad::default() }, style.foreground, ); diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 4fdad86179..7a461b082b 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -13,8 +13,7 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Color, Element, Length, Pixels, Point, Rectangle, Shell, Size, - Widget, + Clipboard, Element, Length, Pixels, Point, Rectangle, Shell, Size, Widget, }; /// An vertical bar and a handle that selects a single value from a range of @@ -398,9 +397,7 @@ pub fn draw( height: offset + handle_width / 2.0, }, border_radius: style.rail.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.rail.colors.1, ); @@ -414,9 +411,7 @@ pub fn draw( height: bounds.height - offset - handle_width / 2.0, }, border_radius: style.rail.border_radius, - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: Default::default(), + ..renderer::Quad::default() }, style.rail.colors.0, ); @@ -432,7 +427,7 @@ pub fn draw( border_radius: handle_border_radius, border_width: style.handle.border_width, border_color: style.handle.border_color, - shadow: Default::default(), + ..renderer::Quad::default() }, style.handle.color, ); From 4d502012b3e3ed9d9ef80f21078d53d182cdaa1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 12:39:41 +0100 Subject: [PATCH 5/9] Skip transparent shadows in `iced_tiny_skia` --- tiny_skia/src/backend.rs | 195 ++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 94 deletions(-) diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 5321d8c664..bad6221fb8 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -186,104 +186,91 @@ impl Backend { let path = rounded_rectangle(*bounds, fill_border_radius); if let Some(shadow) = shadow { - fn smoothstep(a: f32, b: f32, x: f32) -> f32 { - let x = ((x - a) / (b - a)).clamp(0.0, 1.0); - - x * x * (3.0 - 2.0 * x) - } - - fn rounded_box_sdf( - to_center: Vector, - size: Size, - radii: &[f32], - ) -> f32 { - let radius = - match (to_center.x > 0.0, to_center.y > 0.0) { - (true, true) => radii[2], - (true, false) => radii[1], - (false, true) => radii[3], - (false, false) => radii[0], - }; - - let x = (to_center.x.abs() - size.width() + radius) - .max(0.0); - let y = (to_center.y.abs() - size.height() + radius) - .max(0.0); - - (x.powf(2.0) + y.powf(2.0)).sqrt() - radius - } + if shadow.color.a > 0.0 { + let shadow_bounds = (Rectangle { + x: bounds.x + shadow.offset.x - shadow.blur_radius, + y: bounds.y + shadow.offset.y - shadow.blur_radius, + width: bounds.width + shadow.blur_radius * 2.0, + height: bounds.height + shadow.blur_radius * 2.0, + } + translation) + * scale_factor; + + let radii = fill_border_radius + .into_iter() + .map(|radius| radius * scale_factor) + .collect::>(); + let (x, y, width, height) = ( + shadow_bounds.x as u32, + shadow_bounds.y as u32, + shadow_bounds.width as u32, + shadow_bounds.height as u32, + ); + let half_width = physical_bounds.width / 2.0; + let half_height = physical_bounds.height / 2.0; - let shadow_bounds = (Rectangle { - x: bounds.x + shadow.offset.x - shadow.blur_radius, - y: bounds.y + shadow.offset.y - shadow.blur_radius, - width: bounds.width + shadow.blur_radius * 2.0, - height: bounds.height + shadow.blur_radius * 2.0, - } + translation) - * scale_factor; - - let radii = fill_border_radius - .into_iter() - .map(|radius| radius * scale_factor) - .collect::>(); - let (x, y, width, height) = ( - shadow_bounds.x as u32, - shadow_bounds.y as u32, - shadow_bounds.width as u32, - shadow_bounds.height as u32, - ); - let half_width = physical_bounds.width / 2.0; - let half_height = physical_bounds.height / 2.0; - - let colors = (y..y + height) - .flat_map(|y| { - (x..x + width).map(move |x| (x as f32, y as f32)) - }) - .filter_map(|(x, y)| { - Size::from_wh(half_width, half_height).map(|size| { - let shadow_distance = rounded_box_sdf( - Vector::new( - x - physical_bounds.position().x - - (shadow.offset.x * scale_factor) - - half_width, - y - physical_bounds.position().y - - (shadow.offset.y * scale_factor) - - half_height, - ), - size, - &radii, - ); - let shadow_alpha = 1.0 - - smoothstep( - -shadow.blur_radius * scale_factor, - shadow.blur_radius * scale_factor, - shadow_distance, - ); - - let mut color = into_color(shadow.color); - color.apply_opacity(shadow_alpha); - - color.to_color_u8().premultiply() + let colors = (y..y + height) + .flat_map(|y| { + (x..x + width) + .map(move |x| (x as f32, y as f32)) }) - }) - .collect(); + .filter_map(|(x, y)| { + Size::from_wh(half_width, half_height).map( + |size| { + let shadow_distance = rounded_box_sdf( + Vector::new( + x - physical_bounds + .position() + .x + - (shadow.offset.x + * scale_factor) + - half_width, + y - physical_bounds + .position() + .y + - (shadow.offset.y + * scale_factor) + - half_height, + ), + size, + &radii, + ); + let shadow_alpha = 1.0 + - smoothstep( + -shadow.blur_radius + * scale_factor, + shadow.blur_radius + * scale_factor, + shadow_distance, + ); + + let mut color = + into_color(shadow.color); + color.apply_opacity(shadow_alpha); + + color.to_color_u8().premultiply() + }, + ) + }) + .collect(); - if let Some(pixmap) = tiny_skia::IntSize::from_wh( - width, height, - ) - .and_then(|size| { - tiny_skia::Pixmap::from_vec( - bytemuck::cast_vec(colors), - size, + if let Some(pixmap) = tiny_skia::IntSize::from_wh( + width, height, ) - }) { - pixels.draw_pixmap( - x as i32, - y as i32, - pixmap.as_ref(), - &tiny_skia::PixmapPaint::default(), - tiny_skia::Transform::default(), - None, - ); + .and_then(|size| { + tiny_skia::Pixmap::from_vec( + bytemuck::cast_vec(colors), + size, + ) + }) { + pixels.draw_pixmap( + x as i32, + y as i32, + pixmap.as_ref(), + &tiny_skia::PixmapPaint::default(), + tiny_skia::Transform::default(), + None, + ); + } } } @@ -969,6 +956,26 @@ fn adjust_clip_mask(clip_mask: &mut tiny_skia::Mask, bounds: Rectangle) { ); } +fn smoothstep(a: f32, b: f32, x: f32) -> f32 { + let x = ((x - a) / (b - a)).clamp(0.0, 1.0); + + x * x * (3.0 - 2.0 * x) +} + +fn rounded_box_sdf(to_center: Vector, size: Size, radii: &[f32]) -> f32 { + let radius = match (to_center.x > 0.0, to_center.y > 0.0) { + (true, true) => radii[2], + (true, false) => radii[1], + (false, true) => radii[3], + (false, false) => radii[0], + }; + + let x = (to_center.x.abs() - size.width() + radius).max(0.0); + let y = (to_center.y.abs() - size.height() + radius).max(0.0); + + (x.powf(2.0) + y.powf(2.0)).sqrt() - radius +} + impl iced_graphics::Backend for Backend { type Primitive = primitive::Custom; } From 25f182f933ea6b7c112c8f9a450a98dc9b9eebdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 13:29:25 +0100 Subject: [PATCH 6/9] Introduce `Border` struct analogous to `Shadow` --- core/src/border.rs | 54 ++++++++++ core/src/element.rs | 10 +- core/src/lib.rs | 6 +- core/src/renderer.rs | 22 ++-- core/src/shadow.rs | 11 +- examples/custom_quad/src/main.rs | 14 +-- examples/custom_widget/src/main.rs | 4 +- examples/modal/src/main.rs | 6 +- examples/pane_grid/src/main.rs | 16 ++- examples/scrollable/src/main.rs | 16 +-- graphics/src/damage.rs | 6 +- graphics/src/primitive.rs | 12 +-- graphics/src/renderer.rs | 4 +- src/lib.rs | 7 +- style/src/button.rs | 14 +-- style/src/checkbox.rs | 10 +- style/src/container.rs | 31 ++---- style/src/menu.rs | 10 +- style/src/pane_grid.rs | 12 +-- style/src/pick_list.rs | 10 +- style/src/progress_bar.rs | 5 +- style/src/rule.rs | 5 +- style/src/scrollable.rs | 18 +--- style/src/slider.rs | 7 +- style/src/text_editor.rs | 12 +-- style/src/text_input.rs | 10 +- style/src/theme.rs | 128 ++++++++++++---------- tiny_skia/src/backend.rs | 167 +++++++++++++---------------- wgpu/src/layer.rs | 20 +--- widget/src/button.rs | 24 +---- widget/src/checkbox.rs | 4 +- widget/src/container.rs | 6 +- widget/src/overlay/menu.rs | 12 +-- widget/src/pane_grid.rs | 9 +- widget/src/pick_list.rs | 4 +- widget/src/progress_bar.rs | 6 +- widget/src/radio.rs | 13 ++- widget/src/rule.rs | 6 +- widget/src/scrollable.rs | 16 ++- widget/src/slider.rs | 16 +-- widget/src/text_editor.rs | 4 +- widget/src/text_input.rs | 4 +- widget/src/toggler.rs | 24 ++--- widget/src/vertical_slider.rs | 15 +-- 44 files changed, 384 insertions(+), 426 deletions(-) create mode 100644 core/src/border.rs diff --git a/core/src/border.rs b/core/src/border.rs new file mode 100644 index 0000000000..2182334129 --- /dev/null +++ b/core/src/border.rs @@ -0,0 +1,54 @@ +//! Draw lines around containers. +use crate::Color; + +/// A border. +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct Border { + /// The color of the border. + pub color: Color, + + /// The width of the border. + pub width: f32, + + /// The radius of the border. + pub radius: Radius, +} + +impl Border { + /// Creates a new default [`Border`] with the given [`Radius`]. + pub fn with_radius(radius: impl Into) -> Self { + Self { + radius: radius.into(), + ..Self::default() + } + } +} + +/// The border radii for the corners of a graphics primitive in the order: +/// top-left, top-right, bottom-right, bottom-left. +#[derive(Debug, Clone, Copy, PartialEq, Default)] +pub struct Radius([f32; 4]); + +impl From for Radius { + fn from(w: f32) -> Self { + Self([w; 4]) + } +} + +impl From for Radius { + fn from(w: u8) -> Self { + Self([f32::from(w); 4]) + } +} + +impl From<[f32; 4]> for Radius { + fn from(radi: [f32; 4]) -> Self { + Self(radi) + } +} + +impl From for [f32; 4] { + fn from(radi: Radius) -> Self { + radi.0 + } +} diff --git a/core/src/element.rs b/core/src/element.rs index e57ad77710..4d4bfa369d 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -6,7 +6,8 @@ use crate::renderer; use crate::widget; use crate::widget::tree::{self, Tree}; use crate::{ - Clipboard, Color, Layout, Length, Rectangle, Shell, Size, Vector, Widget, + Border, Clipboard, Color, Layout, Length, Rectangle, Shell, Size, Vector, + Widget, }; use std::any::Any; @@ -537,8 +538,11 @@ where renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border_color: color, - border_width: 1.0, + border: Border { + color, + width: 1.0, + ..Border::default() + }, ..renderer::Quad::default() }, Color::TRANSPARENT, diff --git a/core/src/lib.rs b/core/src/lib.rs index b326d0f3ba..bbc973f053 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -17,6 +17,7 @@ rustdoc::broken_intra_doc_links )] pub mod alignment; +pub mod border; pub mod clipboard; pub mod event; pub mod font; @@ -27,7 +28,6 @@ pub mod layout; pub mod mouse; pub mod overlay; pub mod renderer; -pub mod shadow; pub mod svg; pub mod text; pub mod time; @@ -37,7 +37,6 @@ pub mod window; mod angle; mod background; -mod border_radius; mod color; mod content_fit; mod element; @@ -47,6 +46,7 @@ mod padding; mod pixels; mod point; mod rectangle; +mod shadow; mod shell; mod size; mod vector; @@ -54,7 +54,7 @@ mod vector; pub use alignment::Alignment; pub use angle::{Degrees, Radians}; pub use background::Background; -pub use border_radius::BorderRadius; +pub use border::Border; pub use clipboard::Clipboard; pub use color::Color; pub use content_fit::ContentFit; diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 1ca62559ea..a2a66aa86a 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -5,7 +5,7 @@ mod null; #[cfg(debug_assertions)] pub use null::Null; -use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Size, Vector}; +use crate::{Background, Border, Color, Rectangle, Shadow, Size, Vector}; /// A component that can be used by widgets to draw themselves on a screen. pub trait Renderer: Sized { @@ -37,27 +37,19 @@ pub struct Quad { /// The bounds of the [`Quad`]. pub bounds: Rectangle, - /// The border radius of the [`Quad`]. - pub border_radius: BorderRadius, + /// The [`Border`] of the [`Quad`]. + pub border: Border, - /// The border width of the [`Quad`]. - pub border_width: f32, - - /// The border color of the [`Quad`]. - pub border_color: Color, - - /// The shadow of the [`Quad`]. - pub shadow: Option, + /// The [`Shadow`] of the [`Quad`]. + pub shadow: Shadow, } impl Default for Quad { fn default() -> Self { Self { bounds: Rectangle::with_size(Size::ZERO), - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - shadow: None, + border: Border::default(), + shadow: Shadow::default(), } } } diff --git a/core/src/shadow.rs b/core/src/shadow.rs index de8ce1c314..803101edd5 100644 --- a/core/src/shadow.rs +++ b/core/src/shadow.rs @@ -1,15 +1,14 @@ -//! Shadow use crate::{Color, Vector}; -/// A shadow -#[derive(Debug, Clone, Copy, PartialEq)] +/// A shadow. +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct Shadow { - /// The color of the shadow + /// The color of the shadow. pub color: Color, - /// The offset of the shadow + /// The offset of the shadow. pub offset: Vector, - /// The blur radius of the shadow + /// The blur radius of the shadow. pub blur_radius: f32, } diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs index e3f110bbc1..14f62caa1d 100644 --- a/examples/custom_quad/src/main.rs +++ b/examples/custom_quad/src/main.rs @@ -3,8 +3,8 @@ mod quad { use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; - use iced::{mouse, Shadow}; - use iced::{Color, Element, Length, Rectangle, Size}; + use iced::mouse; + use iced::{Border, Color, Element, Length, Rectangle, Shadow, Size}; pub struct CustomQuad { size: f32, @@ -62,10 +62,12 @@ mod quad { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border_radius: self.radius.into(), - border_width: self.border_width, - border_color: Color::from_rgb(1.0, 0.0, 0.0), - shadow: Some(self.shadow), + border: Border { + radius: self.radius.into(), + width: self.border_width, + color: Color::from_rgb(1.0, 0.0, 0.0), + }, + shadow: self.shadow, }, Color::BLACK, ); diff --git a/examples/custom_widget/src/main.rs b/examples/custom_widget/src/main.rs index 6578183d3a..d5ecebaf8d 100644 --- a/examples/custom_widget/src/main.rs +++ b/examples/custom_widget/src/main.rs @@ -13,7 +13,7 @@ mod circle { use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; use iced::mouse; - use iced::{Color, Element, Length, Rectangle, Size}; + use iced::{Border, Color, Element, Length, Rectangle, Size}; pub struct Circle { radius: f32, @@ -62,7 +62,7 @@ mod circle { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border_radius: self.radius.into(), + border: Border::with_radius(self.radius), ..renderer::Quad::default() }, Color::BLACK, diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 59287c0638..c9d5df2977 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -231,10 +231,7 @@ mod modal { use iced::alignment::Alignment; use iced::event; use iced::mouse; - use iced::{ - BorderRadius, Color, Element, Event, Length, Point, Rectangle, Size, - Vector, - }; + use iced::{Color, Element, Event, Length, Point, Rectangle, Size, Vector}; /// A widget that centers a modal element over some base element pub struct Modal<'a, Message, Renderer> { @@ -474,7 +471,6 @@ mod modal { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border_radius: BorderRadius::default(), ..renderer::Quad::default() }, Color { diff --git a/examples/pane_grid/src/main.rs b/examples/pane_grid/src/main.rs index d5e5bcbec8..742dc344c7 100644 --- a/examples/pane_grid/src/main.rs +++ b/examples/pane_grid/src/main.rs @@ -348,7 +348,7 @@ fn view_controls<'a>( mod style { use iced::widget::container; - use iced::Theme; + use iced::{Border, Theme}; pub fn title_bar_active(theme: &Theme) -> container::Appearance { let palette = theme.extended_palette(); @@ -375,8 +375,11 @@ mod style { container::Appearance { background: Some(palette.background.weak.color.into()), - border_width: 2.0, - border_color: palette.background.strong.color, + border: Border { + width: 2.0, + color: palette.background.strong.color, + ..Border::default() + }, ..Default::default() } } @@ -386,8 +389,11 @@ mod style { container::Appearance { background: Some(palette.background.weak.color.into()), - border_width: 2.0, - border_color: palette.primary.strong.color, + border: Border { + width: 2.0, + color: palette.primary.strong.color, + ..Border::default() + }, ..Default::default() } } diff --git a/examples/scrollable/src/main.rs b/examples/scrollable/src/main.rs index 4b57a5a4f6..ff69191724 100644 --- a/examples/scrollable/src/main.rs +++ b/examples/scrollable/src/main.rs @@ -1,10 +1,14 @@ +use iced::executor; +use iced::theme; use iced::widget::scrollable::{Properties, Scrollbar, Scroller}; use iced::widget::{ button, column, container, horizontal_space, progress_bar, radio, row, scrollable, slider, text, vertical_space, }; -use iced::{executor, theme, Alignment, Color}; -use iced::{Application, Command, Element, Length, Settings, Theme}; +use iced::{ + Alignment, Application, Border, Color, Command, Element, Length, Settings, + Theme, +}; use once_cell::sync::Lazy; @@ -373,14 +377,10 @@ impl scrollable::StyleSheet for ScrollbarCustomStyle { background: style .active(&theme::Scrollable::default()) .background, - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::default(), + border: Border::with_radius(2), scroller: Scroller { color: Color::from_rgb8(250, 85, 134), - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::default(), + border: Border::with_radius(2), }, } } else { diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs index cced0c97bf..ba9192efcc 100644 --- a/graphics/src/damage.rs +++ b/graphics/src/damage.rs @@ -78,11 +78,7 @@ impl Damage for Primitive { // damage bounds (?) raw.clip_bounds.expand(1.5) } - Self::Quad { - bounds, - shadow: Some(shadow), - .. - } => { + Self::Quad { bounds, shadow, .. } if shadow.color.a > 0.0 => { let bounds_with_shadow = Rectangle { x: bounds.x + shadow.offset.x.min(0.0) - shadow.blur_radius, y: bounds.y + shadow.offset.y.min(0.0) - shadow.blur_radius, diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index a428c31aa9..aed59e1a91 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -4,7 +4,7 @@ use crate::core::image; use crate::core::svg; use crate::core::text; use crate::core::{ - Background, Color, Font, Pixels, Point, Rectangle, Shadow, Vector, + Background, Border, Color, Font, Pixels, Point, Rectangle, Shadow, Vector, }; use crate::text::editor; use crate::text::paragraph; @@ -67,14 +67,10 @@ pub enum Primitive { bounds: Rectangle, /// The background of the quad background: Background, - /// The border radii of the quad - border_radius: [f32; 4], - /// The border width of the quad - border_width: f32, - /// The border color of the quad - border_color: Color, + /// The [`Border`] of the quad + border: Border, /// The [`Shadow`] of the quad - shadow: Option, + shadow: Shadow, }, /// An image primitive Image { diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 6f31233143..3ba41c3feb 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -124,9 +124,7 @@ impl iced_core::Renderer for Renderer { self.primitives.push(Primitive::Quad { bounds: quad.bounds, background: background.into(), - border_radius: quad.border_radius.into(), - border_width: quad.border_width, - border_color: quad.border_color, + border: quad.border, shadow: quad.shadow, }); } diff --git a/src/lib.rs b/src/lib.rs index 02bb227a62..eb1bd3bda7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -188,11 +188,12 @@ pub mod multi_window; pub use style::theme; pub use crate::core::alignment; +pub use crate::core::border; +pub use crate::core::color; pub use crate::core::gradient; pub use crate::core::{ - color, Alignment, Background, BorderRadius, Color, ContentFit, Degrees, - Gradient, Length, Padding, Pixels, Point, Radians, Rectangle, Shadow, Size, - Vector, + Alignment, Background, Border, Color, ContentFit, Degrees, Gradient, + Length, Padding, Pixels, Point, Radians, Rectangle, Shadow, Size, Vector, }; pub mod clipboard { diff --git a/style/src/button.rs b/style/src/button.rs index e49ad94ac1..d8732263c9 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -1,5 +1,5 @@ //! Change the apperance of a button. -use iced_core::{Background, BorderRadius, Color, Vector}; +use iced_core::{Background, Border, Color, Vector}; /// The appearance of a button. #[derive(Debug, Clone, Copy)] @@ -8,12 +8,8 @@ pub struct Appearance { pub shadow_offset: Vector, /// The [`Background`] of the button. pub background: Option, - /// The border radius of the button. - pub border_radius: BorderRadius, - /// The border width of the button. - pub border_width: f32, - /// The border [`Color`] of the button. - pub border_color: Color, + /// The [`Border`] of the butoon. + pub border: Border, /// The text [`Color`] of the button. pub text_color: Color, } @@ -23,9 +19,7 @@ impl std::default::Default for Appearance { Self { shadow_offset: Vector::default(), background: None, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::default(), text_color: Color::BLACK, } } diff --git a/style/src/checkbox.rs b/style/src/checkbox.rs index cf52c05d63..d96ea4adb9 100644 --- a/style/src/checkbox.rs +++ b/style/src/checkbox.rs @@ -1,5 +1,5 @@ //! Change the appearance of a checkbox. -use iced_core::{Background, BorderRadius, Color}; +use iced_core::{Background, Border, Color}; /// The appearance of a checkbox. #[derive(Debug, Clone, Copy)] @@ -8,12 +8,8 @@ pub struct Appearance { pub background: Background, /// The icon [`Color`] of the checkbox. pub icon_color: Color, - /// The border radius of the checkbox. - pub border_radius: BorderRadius, - /// The border width of the checkbox. - pub border_width: f32, - /// The border [`Color`] of the checkbox. - pub border_color: Color, + /// The [`Border`] of hte checkbox. + pub border: Border, /// The text [`Color`] of the checkbox. pub text_color: Option, } diff --git a/style/src/container.rs b/style/src/container.rs index 490a9dabea..a490c187d0 100644 --- a/style/src/container.rs +++ b/style/src/container.rs @@ -1,19 +1,15 @@ //! Change the appearance of a container. -use crate::core::{Background, BorderRadius, Color, Pixels}; +use crate::core::{Background, Border, Color, Pixels}; /// The appearance of a container. -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct Appearance { /// The text [`Color`] of the container. pub text_color: Option, /// The [`Background`] of the container. pub background: Option, - /// The border radius of the container. - pub border_radius: BorderRadius, - /// The border width of the container. - pub border_width: f32, - /// The border [`Color`] of the container. - pub border_color: Color, + /// The [`Border`] of the container. + pub border: Border, } impl Appearance { @@ -25,8 +21,11 @@ impl Appearance { width: impl Into, ) -> Self { Self { - border_color: color.into(), - border_width: width.into().0, + border: Border { + color: color.into(), + width: width.into().0, + ..Border::default() + }, ..self } } @@ -40,18 +39,6 @@ impl Appearance { } } -impl std::default::Default for Appearance { - fn default() -> Self { - Self { - text_color: None, - background: None, - border_radius: 0.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, - } - } -} - /// A set of rules that dictate the [`Appearance`] of a container. pub trait StyleSheet { /// The supported style of the [`StyleSheet`]. diff --git a/style/src/menu.rs b/style/src/menu.rs index dbf19dae37..be60a3f8f6 100644 --- a/style/src/menu.rs +++ b/style/src/menu.rs @@ -1,5 +1,5 @@ //! Change the appearance of menus. -use iced_core::{Background, BorderRadius, Color}; +use iced_core::{Background, Border, Color}; /// The appearance of a menu. #[derive(Debug, Clone, Copy)] @@ -8,12 +8,8 @@ pub struct Appearance { pub text_color: Color, /// The [`Background`] of the menu. pub background: Background, - /// The border width of the menu. - pub border_width: f32, - /// The border radius of the menu. - pub border_radius: BorderRadius, - /// The border [`Color`] of the menu. - pub border_color: Color, + /// The [`Border`] of the menu. + pub border: Border, /// The text [`Color`] of a selected option in the menu. pub selected_text_color: Color, /// The background [`Color`] of a selected option in the menu. diff --git a/style/src/pane_grid.rs b/style/src/pane_grid.rs index dfdc918666..3557058435 100644 --- a/style/src/pane_grid.rs +++ b/style/src/pane_grid.rs @@ -1,17 +1,13 @@ //! Change the appearance of a pane grid. -use iced_core::{Background, BorderRadius, Color}; +use iced_core::{Background, Border, Color}; /// The appearance of the hovered region of a pane grid. #[derive(Debug, Clone, Copy)] pub struct Appearance { - /// The [`Background`] of the hovered pane region. + /// The [`Background`] of the pane region. pub background: Background, - /// The border width of the hovered pane region. - pub border_width: f32, - /// The border [`Color`] of the hovered pane region. - pub border_color: Color, - /// The border radius of the hovered pane region. - pub border_radius: BorderRadius, + /// The [`Border`] of the pane region. + pub border: Border, } /// A line. diff --git a/style/src/pick_list.rs b/style/src/pick_list.rs index 961c1e939e..8f008f4a31 100644 --- a/style/src/pick_list.rs +++ b/style/src/pick_list.rs @@ -1,5 +1,5 @@ //! Change the appearance of a pick list. -use iced_core::{Background, BorderRadius, Color}; +use iced_core::{Background, Border, Color}; /// The appearance of a pick list. #[derive(Debug, Clone, Copy)] @@ -12,12 +12,8 @@ pub struct Appearance { pub handle_color: Color, /// The [`Background`] of the pick list. pub background: Background, - /// The border radius of the pick list. - pub border_radius: BorderRadius, - /// The border width of the pick list. - pub border_width: f32, - /// The border color of the pick list. - pub border_color: Color, + /// The [`Border`] of the pick list. + pub border: Border, } /// A set of rules that dictate the style of a container. diff --git a/style/src/progress_bar.rs b/style/src/progress_bar.rs index c05a6ee473..b62512d8a5 100644 --- a/style/src/progress_bar.rs +++ b/style/src/progress_bar.rs @@ -1,5 +1,6 @@ //! Change the appearance of a progress bar. -use iced_core::{Background, BorderRadius}; +use crate::core::border; +use crate::core::Background; /// The appearance of a progress bar. #[derive(Debug, Clone, Copy)] @@ -9,7 +10,7 @@ pub struct Appearance { /// The [`Background`] of the bar of the progress bar. pub bar: Background, /// The border radius of the progress bar. - pub border_radius: BorderRadius, + pub border_radius: border::Radius, } /// A set of rules that dictate the style of a progress bar. diff --git a/style/src/rule.rs b/style/src/rule.rs index efbe74447f..12980da7cb 100644 --- a/style/src/rule.rs +++ b/style/src/rule.rs @@ -1,5 +1,6 @@ //! Change the appearance of a rule. -use iced_core::{BorderRadius, Color}; +use crate::core::border; +use crate::core::Color; /// The appearance of a rule. #[derive(Debug, Clone, Copy)] @@ -9,7 +10,7 @@ pub struct Appearance { /// The width (thickness) of the rule line. pub width: u16, /// The radius of the line corners. - pub radius: BorderRadius, + pub radius: border::Radius, /// The [`FillMode`] of the rule. pub fill_mode: FillMode, } diff --git a/style/src/scrollable.rs b/style/src/scrollable.rs index 952c11e18c..6f37305f12 100644 --- a/style/src/scrollable.rs +++ b/style/src/scrollable.rs @@ -1,17 +1,13 @@ //! Change the appearance of a scrollable. -use iced_core::{Background, BorderRadius, Color}; +use crate::core::{Background, Border, Color}; /// The appearance of a scrollable. #[derive(Debug, Clone, Copy)] pub struct Scrollbar { /// The [`Background`] of a scrollable. pub background: Option, - /// The border radius of a scrollable. - pub border_radius: BorderRadius, - /// The border width of a scrollable. - pub border_width: f32, - /// The border [`Color`] of a scrollable. - pub border_color: Color, + /// The [`Border`] of a scrollable. + pub border: Border, /// The appearance of the [`Scroller`] of a scrollable. pub scroller: Scroller, } @@ -21,12 +17,8 @@ pub struct Scrollbar { pub struct Scroller { /// The [`Color`] of the scroller. pub color: Color, - /// The border radius of the scroller. - pub border_radius: BorderRadius, - /// The border width of the scroller. - pub border_width: f32, - /// The border [`Color`] of the scroller. - pub border_color: Color, + /// The [`Border`] of the scroller. + pub border: Border, } /// A set of rules that dictate the style of a scrollable. diff --git a/style/src/slider.rs b/style/src/slider.rs index f006855883..bf1c732961 100644 --- a/style/src/slider.rs +++ b/style/src/slider.rs @@ -1,5 +1,6 @@ //! Change the apperance of a slider. -use iced_core::{BorderRadius, Color}; +use crate::core::border; +use crate::core::Color; /// The appearance of a slider. #[derive(Debug, Clone, Copy)] @@ -18,7 +19,7 @@ pub struct Rail { /// The width of the stroke of a slider rail. pub width: f32, /// The border radius of the corners of the rail. - pub border_radius: BorderRadius, + pub border_radius: border::Radius, } /// The appearance of the handle of a slider. @@ -47,7 +48,7 @@ pub enum HandleShape { /// The width of the rectangle. width: u16, /// The border radius of the corners of the rectangle. - border_radius: BorderRadius, + border_radius: border::Radius, }, } diff --git a/style/src/text_editor.rs b/style/src/text_editor.rs index f6bae7e674..87f481e30b 100644 --- a/style/src/text_editor.rs +++ b/style/src/text_editor.rs @@ -1,17 +1,13 @@ //! Change the appearance of a text editor. -use crate::core::{Background, BorderRadius, Color}; +use crate::core::{Background, Border, Color}; /// The appearance of a text input. #[derive(Debug, Clone, Copy)] pub struct Appearance { - /// The [`Background`] of the text input. + /// The [`Background`] of the text editor. pub background: Background, - /// The border radius of the text input. - pub border_radius: BorderRadius, - /// The border width of the text input. - pub border_width: f32, - /// The border [`Color`] of the text input. - pub border_color: Color, + /// The [`Border`] of the text editor. + pub border: Border, } /// A set of rules that dictate the style of a text input. diff --git a/style/src/text_input.rs b/style/src/text_input.rs index 90251b5cba..8ba9957f51 100644 --- a/style/src/text_input.rs +++ b/style/src/text_input.rs @@ -1,17 +1,13 @@ //! Change the appearance of a text input. -use iced_core::{Background, BorderRadius, Color}; +use iced_core::{Background, Border, Color}; /// The appearance of a text input. #[derive(Debug, Clone, Copy)] pub struct Appearance { /// The [`Background`] of the text input. pub background: Background, - /// The border radius of the text input. - pub border_radius: BorderRadius, - /// The border width of the text input. - pub border_width: f32, - /// The border [`Color`] of the text input. - pub border_color: Color, + /// The [`Border`] of the text input. + pub border: Border, /// The icon [`Color`] of the text input. pub icon_color: Color, } diff --git a/style/src/theme.rs b/style/src/theme.rs index f78587e5db..d90efb0ad5 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -21,7 +21,7 @@ use crate::text_editor; use crate::text_input; use crate::toggler; -use iced_core::{Background, Color, Vector}; +use crate::core::{Background, Border, Color, Vector}; use std::fmt; use std::rc::Rc; @@ -199,7 +199,7 @@ impl button::StyleSheet for Theme { let palette = self.extended_palette(); let appearance = button::Appearance { - border_radius: 2.0.into(), + border: Border::with_radius(2), ..button::Appearance::default() }; @@ -388,9 +388,11 @@ fn checkbox_appearance( base.color }), icon_color, - border_radius: 2.0.into(), - border_width: 1.0, - border_color: accent.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: accent.color, + }, text_color: None, } } @@ -431,9 +433,7 @@ impl container::StyleSheet for Theme { container::Appearance { text_color: None, background: Some(palette.background.weak.color.into()), - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::with_radius(2), } } Container::Custom(custom) => custom.appearance(self), @@ -555,9 +555,11 @@ impl menu::StyleSheet for Theme { menu::Appearance { text_color: palette.background.weak.text, background: palette.background.weak.color.into(), - border_width: 1.0, - border_radius: 0.0.into(), - border_color: palette.background.strong.color, + border: Border { + width: 1.0, + radius: 0.0.into(), + color: palette.background.strong.color, + }, selected_text_color: palette.primary.strong.text, selected_background: palette.primary.strong.color.into(), } @@ -602,9 +604,11 @@ impl pick_list::StyleSheet for Theme { background: palette.background.weak.color.into(), placeholder_color: palette.background.strong.color, handle_color: palette.background.weak.text, - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.strong.color, + }, } } PickList::Custom(custom, _) => custom.active(self), @@ -621,9 +625,11 @@ impl pick_list::StyleSheet for Theme { background: palette.background.weak.color.into(), placeholder_color: palette.background.strong.color, handle_color: palette.background.weak.text, - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.primary.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.primary.strong.color, + }, } } PickList::Custom(custom, _) => custom.hovered(self), @@ -776,9 +782,11 @@ impl pane_grid::StyleSheet for Theme { a: 0.5, ..palette.primary.base.color }), - border_width: 2.0, - border_color: palette.primary.strong.color, - border_radius: 0.0.into(), + border: Border { + width: 2.0, + color: palette.primary.strong.color, + radius: 0.0.into(), + }, } } PaneGrid::Custom(custom) => custom.hovered_region(self), @@ -986,14 +994,10 @@ impl scrollable::StyleSheet for Theme { scrollable::Scrollbar { background: Some(palette.background.weak.color.into()), - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::with_radius(2), scroller: scrollable::Scroller { color: palette.background.strong.color, - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::with_radius(2), }, } } @@ -1013,14 +1017,10 @@ impl scrollable::StyleSheet for Theme { scrollable::Scrollbar { background: Some(palette.background.weak.color.into()), - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::with_radius(2), scroller: scrollable::Scroller { color: palette.primary.strong.color, - border_radius: 2.0.into(), - border_width: 0.0, - border_color: Color::TRANSPARENT, + border: Border::with_radius(2), }, } } else { @@ -1120,9 +1120,11 @@ impl text_input::StyleSheet for Theme { text_input::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.strong.color, + }, icon_color: palette.background.weak.text, } } @@ -1136,9 +1138,11 @@ impl text_input::StyleSheet for Theme { text_input::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.base.text, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.base.text, + }, icon_color: palette.background.weak.text, } } @@ -1152,9 +1156,11 @@ impl text_input::StyleSheet for Theme { text_input::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.primary.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.primary.strong.color, + }, icon_color: palette.background.weak.text, } } @@ -1198,9 +1204,11 @@ impl text_input::StyleSheet for Theme { text_input::Appearance { background: palette.background.weak.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.strong.color, + }, icon_color: palette.background.strong.color, } } @@ -1236,9 +1244,11 @@ impl text_editor::StyleSheet for Theme { text_editor::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.strong.color, + }, } } @@ -1251,9 +1261,11 @@ impl text_editor::StyleSheet for Theme { text_editor::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.base.text, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.base.text, + }, } } @@ -1266,9 +1278,11 @@ impl text_editor::StyleSheet for Theme { text_editor::Appearance { background: palette.background.base.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.primary.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.primary.strong.color, + }, } } @@ -1311,9 +1325,11 @@ impl text_editor::StyleSheet for Theme { text_editor::Appearance { background: palette.background.weak.color.into(), - border_radius: 2.0.into(), - border_width: 1.0, - border_color: palette.background.strong.color, + border: Border { + radius: 2.0.into(), + width: 1.0, + color: palette.background.strong.color, + }, } } diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index bad6221fb8..ea4a3ec6fe 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -152,9 +152,7 @@ impl Backend { Primitive::Quad { bounds, background, - border_radius, - border_width, - border_color, + border, shadow, } => { let physical_bounds = (*bounds + translation) * scale_factor; @@ -173,11 +171,12 @@ impl Backend { .post_scale(scale_factor, scale_factor); // Make sure the border radius is not larger than the bounds - let border_width = border_width + let border_width = border + .width .min(bounds.width / 2.0) .min(bounds.height / 2.0); - let mut fill_border_radius = *border_radius; + let mut fill_border_radius = <[f32; 4]>::from(border.radius); for radius in &mut fill_border_radius { *radius = (*radius) .min(bounds.width / 2.0) @@ -185,92 +184,78 @@ impl Backend { } let path = rounded_rectangle(*bounds, fill_border_radius); - if let Some(shadow) = shadow { - if shadow.color.a > 0.0 { - let shadow_bounds = (Rectangle { - x: bounds.x + shadow.offset.x - shadow.blur_radius, - y: bounds.y + shadow.offset.y - shadow.blur_radius, - width: bounds.width + shadow.blur_radius * 2.0, - height: bounds.height + shadow.blur_radius * 2.0, - } + translation) - * scale_factor; - - let radii = fill_border_radius - .into_iter() - .map(|radius| radius * scale_factor) - .collect::>(); - let (x, y, width, height) = ( - shadow_bounds.x as u32, - shadow_bounds.y as u32, - shadow_bounds.width as u32, - shadow_bounds.height as u32, - ); - let half_width = physical_bounds.width / 2.0; - let half_height = physical_bounds.height / 2.0; - - let colors = (y..y + height) - .flat_map(|y| { - (x..x + width) - .map(move |x| (x as f32, y as f32)) - }) - .filter_map(|(x, y)| { - Size::from_wh(half_width, half_height).map( - |size| { - let shadow_distance = rounded_box_sdf( - Vector::new( - x - physical_bounds - .position() - .x - - (shadow.offset.x - * scale_factor) - - half_width, - y - physical_bounds - .position() - .y - - (shadow.offset.y - * scale_factor) - - half_height, - ), - size, - &radii, - ); - let shadow_alpha = 1.0 - - smoothstep( - -shadow.blur_radius - * scale_factor, - shadow.blur_radius - * scale_factor, - shadow_distance, - ); - - let mut color = - into_color(shadow.color); - color.apply_opacity(shadow_alpha); - - color.to_color_u8().premultiply() - }, - ) + if shadow.color.a > 0.0 { + let shadow_bounds = (Rectangle { + x: bounds.x + shadow.offset.x - shadow.blur_radius, + y: bounds.y + shadow.offset.y - shadow.blur_radius, + width: bounds.width + shadow.blur_radius * 2.0, + height: bounds.height + shadow.blur_radius * 2.0, + } + translation) + * scale_factor; + + let radii = fill_border_radius + .into_iter() + .map(|radius| radius * scale_factor) + .collect::>(); + let (x, y, width, height) = ( + shadow_bounds.x as u32, + shadow_bounds.y as u32, + shadow_bounds.width as u32, + shadow_bounds.height as u32, + ); + let half_width = physical_bounds.width / 2.0; + let half_height = physical_bounds.height / 2.0; + + let colors = (y..y + height) + .flat_map(|y| { + (x..x + width).map(move |x| (x as f32, y as f32)) + }) + .filter_map(|(x, y)| { + Size::from_wh(half_width, half_height).map(|size| { + let shadow_distance = rounded_box_sdf( + Vector::new( + x - physical_bounds.position().x + - (shadow.offset.x * scale_factor) + - half_width, + y - physical_bounds.position().y + - (shadow.offset.y * scale_factor) + - half_height, + ), + size, + &radii, + ); + let shadow_alpha = 1.0 + - smoothstep( + -shadow.blur_radius * scale_factor, + shadow.blur_radius * scale_factor, + shadow_distance, + ); + + let mut color = into_color(shadow.color); + color.apply_opacity(shadow_alpha); + + color.to_color_u8().premultiply() }) - .collect(); + }) + .collect(); - if let Some(pixmap) = tiny_skia::IntSize::from_wh( - width, height, + if let Some(pixmap) = tiny_skia::IntSize::from_wh( + width, height, + ) + .and_then(|size| { + tiny_skia::Pixmap::from_vec( + bytemuck::cast_vec(colors), + size, ) - .and_then(|size| { - tiny_skia::Pixmap::from_vec( - bytemuck::cast_vec(colors), - size, - ) - }) { - pixels.draw_pixmap( - x as i32, - y as i32, - pixmap.as_ref(), - &tiny_skia::PixmapPaint::default(), - tiny_skia::Transform::default(), - None, - ); - } + }) { + pixels.draw_pixmap( + x as i32, + y as i32, + pixmap.as_ref(), + &tiny_skia::PixmapPaint::default(), + tiny_skia::Transform::default(), + None, + ); } } @@ -344,7 +329,7 @@ impl Backend { }; // Make sure the border radius is correct - let mut border_radius = *border_radius; + let mut border_radius = <[f32; 4]>::from(border.radius); let mut is_simple_border = true; for radius in &mut border_radius { @@ -370,7 +355,7 @@ impl Backend { &border_path, &tiny_skia::Paint { shader: tiny_skia::Shader::SolidColor( - into_color(*border_color), + into_color(border.color), ), anti_alias: true, ..tiny_skia::Paint::default() @@ -426,7 +411,7 @@ impl Backend { &border_radius_path, &tiny_skia::Paint { shader: tiny_skia::Shader::SolidColor( - into_color(*border_color), + into_color(border.color), ), anti_alias: true, ..tiny_skia::Paint::default() diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index cb91878d73..e213c95f18 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -12,9 +12,7 @@ pub use text::Text; use crate::core; use crate::core::alignment; -use crate::core::{ - Color, Font, Pixels, Point, Rectangle, Shadow, Size, Vector, -}; +use crate::core::{Color, Font, Pixels, Point, Rectangle, Size, Vector}; use crate::graphics; use crate::graphics::color; use crate::graphics::Viewport; @@ -197,28 +195,20 @@ impl<'a> Layer<'a> { Primitive::Quad { bounds, background, - border_radius, - border_width, - border_color, + border, shadow, } => { let layer = &mut layers[current_layer]; - let shadow = shadow.unwrap_or_else(|| Shadow { - color: Color::TRANSPARENT, - offset: Vector::ZERO, - blur_radius: 0.0, - }); - let quad = Quad { position: [ bounds.x + translation.x, bounds.y + translation.y, ], size: [bounds.width, bounds.height], - border_color: color::pack(*border_color), - border_radius: *border_radius, - border_width: *border_width, + border_color: color::pack(border.color), + border_radius: border.radius.into(), + border_width: border.width, shadow_color: shadow.color.into_linear(), shadow_offset: shadow.offset.into(), shadow_blur_radius: shadow.blur_radius, diff --git a/widget/src/button.rs b/widget/src/button.rs index f9e59f2341..f052ebab64 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -11,7 +11,7 @@ use crate::core::widget::tree::{self, Tree}; use crate::core::widget::Operation; use crate::core::{ Background, Clipboard, Color, Element, Layout, Length, Padding, Rectangle, - Shell, Size, Vector, Widget, + Shell, Size, Widget, }; pub use iced_style::button::{Appearance, StyleSheet}; @@ -391,29 +391,11 @@ where style_sheet.active(style) }; - if styling.background.is_some() || styling.border_width > 0.0 { - if styling.shadow_offset != Vector::default() { - // TODO: Implement proper shadow support - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle { - x: bounds.x + styling.shadow_offset.x, - y: bounds.y + styling.shadow_offset.y, - ..bounds - }, - border_radius: styling.border_radius, - ..renderer::Quad::default() - }, - Background::Color([0.0, 0.0, 0.0, 0.5].into()), - ); - } - + if styling.background.is_some() || styling.border.width > 0.0 { renderer.fill_quad( renderer::Quad { bounds, - border_radius: styling.border_radius, - border_width: styling.border_width, - border_color: styling.border_color, + border: styling.border, ..renderer::Quad::default() }, styling diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 80397c134a..762683143f 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -284,9 +284,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: custom_style.border_radius, - border_width: custom_style.border_width, - border_color: custom_style.border_color, + border: custom_style.border, ..renderer::Quad::default() }, custom_style.background, diff --git a/widget/src/container.rs b/widget/src/container.rs index b3d2f360f4..b87f1d9f3a 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -337,13 +337,11 @@ pub fn draw_background( ) where Renderer: crate::core::Renderer, { - if appearance.background.is_some() || appearance.border_width > 0.0 { + if appearance.background.is_some() || appearance.border.width > 0.0 { renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius, - border_width: appearance.border_width, - border_color: appearance.border_color, + border: appearance.border, ..renderer::Quad::default() }, appearance diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 2086e9931b..678bb7b52d 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -10,7 +10,7 @@ use crate::core::text::{self, Text}; use crate::core::touch; use crate::core::widget::Tree; use crate::core::{ - Clipboard, Length, Padding, Pixels, Point, Rectangle, Size, Vector, + Border, Clipboard, Length, Padding, Pixels, Point, Rectangle, Size, Vector, }; use crate::core::{Element, Shell, Widget}; use crate::scrollable::{self, Scrollable}; @@ -306,9 +306,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_color: appearance.border_color, - border_width: appearance.border_width, - border_radius: appearance.border_radius, + border: appearance.border, ..renderer::Quad::default() }, appearance.background, @@ -513,11 +511,11 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { - x: bounds.x + appearance.border_width, - width: bounds.width - appearance.border_width * 2.0, + x: bounds.x + appearance.border.width, + width: bounds.width - appearance.border.width * 2.0, ..bounds }, - border_radius: appearance.border_radius, + border: Border::with_radius(appearance.border.radius), ..renderer::Quad::default() }, appearance.selected_background, diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 38ae17f043..3fda0e32f7 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -917,10 +917,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds, - border_radius: hovered_region_style - .border_radius, - border_width: hovered_region_style.border_width, - border_color: hovered_region_style.border_color, + border: hovered_region_style.border, ..renderer::Quad::default() }, theme.hovered_region(style).background, @@ -948,9 +945,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds, - border_radius: hovered_region_style.border_radius, - border_width: hovered_region_style.border_width, - border_color: hovered_region_style.border_color, + border: hovered_region_style.border, ..renderer::Quad::default() }, theme.hovered_region(style).background, diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index ef0c0eb34c..4d4e14d355 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -653,9 +653,7 @@ pub fn draw<'a, T, Renderer>( renderer.fill_quad( renderer::Quad { bounds, - border_color: style.border_color, - border_width: style.border_width, - border_radius: style.border_radius, + border: style.border, ..renderer::Quad::default() }, style.background, diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 1d48ff7300..eb15644e6c 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -3,7 +3,7 @@ use crate::core::layout; use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{Element, Layout, Length, Rectangle, Size, Widget}; +use crate::core::{Border, Element, Layout, Length, Rectangle, Size, Widget}; use std::ops::RangeInclusive; @@ -130,7 +130,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { ..bounds }, - border_radius: style.border_radius, + border: Border::with_radius(style.border_radius), ..renderer::Quad::default() }, style.background, @@ -143,7 +143,7 @@ where width: active_progress_width, ..bounds }, - border_radius: style.border_radius, + border: Border::with_radius(style.border_radius), ..renderer::Quad::default() }, style.bar, diff --git a/widget/src/radio.rs b/widget/src/radio.rs index a782812ed2..ceb51eadff 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -9,7 +9,8 @@ use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, Widget, + Border, Clipboard, Element, Layout, Length, Pixels, Rectangle, Shell, Size, + Widget, }; pub use iced_style::radio::{Appearance, StyleSheet}; @@ -311,9 +312,11 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: (size / 2.0).into(), - border_width: custom_style.border_width, - border_color: custom_style.border_color, + border: Border { + radius: (size / 2.0).into(), + width: custom_style.border_width, + color: custom_style.border_color, + }, ..renderer::Quad::default() }, custom_style.background, @@ -328,7 +331,7 @@ where width: bounds.width - dot_size, height: bounds.height - dot_size, }, - border_radius: (dot_size / 2.0).into(), + border: Border::with_radius(dot_size / 2.0), ..renderer::Quad::default() }, custom_style.dot_color, diff --git a/widget/src/rule.rs b/widget/src/rule.rs index 813b0e46d7..c958c44d96 100644 --- a/widget/src/rule.rs +++ b/widget/src/rule.rs @@ -3,7 +3,9 @@ use crate::core::layout; use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; -use crate::core::{Element, Layout, Length, Pixels, Rectangle, Size, Widget}; +use crate::core::{ + Border, Element, Layout, Length, Pixels, Rectangle, Size, Widget, +}; pub use crate::style::rule::{Appearance, FillMode, StyleSheet}; @@ -122,7 +124,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: style.radius, + border: Border::with_radius(style.radius), ..renderer::Quad::default() }, style.color, diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index beaad704fd..b7b6c3d282 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -903,15 +903,13 @@ pub fn draw( if scrollbar.bounds.width > 0.0 && scrollbar.bounds.height > 0.0 && (style.background.is_some() - || (style.border_color != Color::TRANSPARENT - && style.border_width > 0.0)) + || (style.border.color != Color::TRANSPARENT + && style.border.width > 0.0)) { renderer.fill_quad( renderer::Quad { bounds: scrollbar.bounds, - border_radius: style.border_radius, - border_width: style.border_width, - border_color: style.border_color, + border: style.border, ..renderer::Quad::default() }, style @@ -924,15 +922,13 @@ pub fn draw( if scrollbar.scroller.bounds.width > 0.0 && scrollbar.scroller.bounds.height > 0.0 && (style.scroller.color != Color::TRANSPARENT - || (style.scroller.border_color != Color::TRANSPARENT - && style.scroller.border_width > 0.0)) + || (style.scroller.border.color != Color::TRANSPARENT + && style.scroller.border.width > 0.0)) { renderer.fill_quad( renderer::Quad { bounds: scrollbar.scroller.bounds, - border_radius: style.scroller.border_radius, - border_width: style.scroller.border_width, - border_color: style.scroller.border_color, + border: style.scroller.border, ..renderer::Quad::default() }, style.scroller.color, diff --git a/widget/src/slider.rs b/widget/src/slider.rs index d12e0ebe67..79b0a7d866 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -8,8 +8,8 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, Shell, Size, - Widget, + Border, Clipboard, Element, Layout, Length, Pixels, Point, Rectangle, + Shell, Size, Widget, }; use std::ops::RangeInclusive; @@ -398,7 +398,7 @@ pub fn draw( width: offset + handle_width / 2.0, height: style.rail.width, }, - border_radius: style.rail.border_radius, + border: Border::with_radius(style.rail.border_radius), ..renderer::Quad::default() }, style.rail.colors.0, @@ -412,7 +412,7 @@ pub fn draw( width: bounds.width - offset - handle_width / 2.0, height: style.rail.width, }, - border_radius: style.rail.border_radius, + border: Border::with_radius(style.rail.border_radius), ..renderer::Quad::default() }, style.rail.colors.1, @@ -426,9 +426,11 @@ pub fn draw( width: handle_width, height: handle_height, }, - border_radius: handle_border_radius, - border_width: style.handle.border_width, - border_color: style.handle.border_color, + border: Border { + radius: handle_border_radius, + width: style.handle.border_width, + color: style.handle.border_color, + }, ..renderer::Quad::default() }, style.handle.color, diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 01ab126282..6b71623847 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -466,9 +466,7 @@ where renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius, - border_width: appearance.border_width, - border_color: appearance.border_color, + border: appearance.border, ..renderer::Quad::default() }, appearance.background, diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 7b15f58ca2..02715989ea 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -1082,9 +1082,7 @@ pub fn draw( renderer.fill_quad( renderer::Quad { bounds, - border_radius: appearance.border_radius, - border_width: appearance.border_width, - border_color: appearance.border_color, + border: appearance.border, ..renderer::Quad::default() }, appearance.background, diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index 0bafffe1fc..58cd38ab74 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -9,8 +9,8 @@ use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Element, Event, Layout, Length, Pixels, Rectangle, Shell, Size, - Widget, + Border, Clipboard, Element, Event, Layout, Length, Pixels, Rectangle, + Shell, Size, Widget, }; pub use crate::style::toggler::{Appearance, StyleSheet}; @@ -312,11 +312,11 @@ where renderer.fill_quad( renderer::Quad { bounds: toggler_background_bounds, - border_radius: border_radius.into(), - border_width: 1.0, - border_color: style - .background_border - .unwrap_or(style.background), + border: Border { + radius: border_radius.into(), + width: 1.0, + color: style.background_border.unwrap_or(style.background), + }, ..renderer::Quad::default() }, style.background, @@ -337,11 +337,11 @@ where renderer.fill_quad( renderer::Quad { bounds: toggler_foreground_bounds, - border_radius: border_radius.into(), - border_width: 1.0, - border_color: style - .foreground_border - .unwrap_or(style.foreground), + border: Border { + radius: border_radius.into(), + width: 1.0, + color: style.foreground_border.unwrap_or(style.foreground), + }, ..renderer::Quad::default() }, style.foreground, diff --git a/widget/src/vertical_slider.rs b/widget/src/vertical_slider.rs index 7a461b082b..52428c10b6 100644 --- a/widget/src/vertical_slider.rs +++ b/widget/src/vertical_slider.rs @@ -13,7 +13,8 @@ use crate::core::renderer; use crate::core::touch; use crate::core::widget::tree::{self, Tree}; use crate::core::{ - Clipboard, Element, Length, Pixels, Point, Rectangle, Shell, Size, Widget, + Border, Clipboard, Element, Length, Pixels, Point, Rectangle, Shell, Size, + Widget, }; /// An vertical bar and a handle that selects a single value from a range of @@ -396,7 +397,7 @@ pub fn draw( width: style.rail.width, height: offset + handle_width / 2.0, }, - border_radius: style.rail.border_radius, + border: Border::with_radius(style.rail.border_radius), ..renderer::Quad::default() }, style.rail.colors.1, @@ -410,7 +411,7 @@ pub fn draw( width: style.rail.width, height: bounds.height - offset - handle_width / 2.0, }, - border_radius: style.rail.border_radius, + border: Border::with_radius(style.rail.border_radius), ..renderer::Quad::default() }, style.rail.colors.0, @@ -424,9 +425,11 @@ pub fn draw( width: handle_height, height: handle_width, }, - border_radius: handle_border_radius, - border_width: style.handle.border_width, - border_color: style.handle.border_color, + border: Border { + radius: handle_border_radius, + width: style.handle.border_width, + color: style.handle.border_color, + }, ..renderer::Quad::default() }, style.handle.color, From e736038d5ff9adb9c011326879d4c772338d12d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 13:32:19 +0100 Subject: [PATCH 7/9] Add `Shadow` to `button::Appearance` --- style/src/button.rs | 11 +++++++---- widget/src/button.rs | 6 +++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/style/src/button.rs b/style/src/button.rs index d8732263c9..0d7a668aca 100644 --- a/style/src/button.rs +++ b/style/src/button.rs @@ -1,5 +1,5 @@ //! Change the apperance of a button. -use iced_core::{Background, Border, Color, Vector}; +use iced_core::{Background, Border, Color, Shadow, Vector}; /// The appearance of a button. #[derive(Debug, Clone, Copy)] @@ -8,10 +8,12 @@ pub struct Appearance { pub shadow_offset: Vector, /// The [`Background`] of the button. pub background: Option, - /// The [`Border`] of the butoon. - pub border: Border, /// The text [`Color`] of the button. pub text_color: Color, + /// The [`Border`] of the buton. + pub border: Border, + /// The [`Shadow`] of the butoon. + pub shadow: Shadow, } impl std::default::Default for Appearance { @@ -19,8 +21,9 @@ impl std::default::Default for Appearance { Self { shadow_offset: Vector::default(), background: None, - border: Border::default(), text_color: Color::BLACK, + border: Border::default(), + shadow: Shadow::default(), } } } diff --git a/widget/src/button.rs b/widget/src/button.rs index f052ebab64..cd1411691a 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -391,11 +391,15 @@ where style_sheet.active(style) }; - if styling.background.is_some() || styling.border.width > 0.0 { + if styling.background.is_some() + || styling.shadow.color.a > 0.0 + || styling.border.width > 0.0 + { renderer.fill_quad( renderer::Quad { bounds, border: styling.border, + shadow: styling.shadow, ..renderer::Quad::default() }, styling From bf375587aa52808cdabf4191571f20784315ea99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 13:34:07 +0100 Subject: [PATCH 8/9] Add `Shadow` to `container::Appearance` --- style/src/container.rs | 4 +++- style/src/theme.rs | 3 ++- widget/src/button.rs | 3 +-- widget/src/container.rs | 7 +++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/style/src/container.rs b/style/src/container.rs index a490c187d0..00649c25eb 100644 --- a/style/src/container.rs +++ b/style/src/container.rs @@ -1,5 +1,5 @@ //! Change the appearance of a container. -use crate::core::{Background, Border, Color, Pixels}; +use crate::core::{Background, Border, Color, Pixels, Shadow}; /// The appearance of a container. #[derive(Debug, Clone, Copy, Default)] @@ -10,6 +10,8 @@ pub struct Appearance { pub background: Option, /// The [`Border`] of the container. pub border: Border, + /// The [`Shadow`] of the container. + pub shadow: Shadow, } impl Appearance { diff --git a/style/src/theme.rs b/style/src/theme.rs index d90efb0ad5..8d1ff23779 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -21,7 +21,7 @@ use crate::text_editor; use crate::text_input; use crate::toggler; -use crate::core::{Background, Border, Color, Vector}; +use crate::core::{Background, Border, Color, Shadow, Vector}; use std::fmt; use std::rc::Rc; @@ -434,6 +434,7 @@ impl container::StyleSheet for Theme { text_color: None, background: Some(palette.background.weak.color.into()), border: Border::with_radius(2), + shadow: Shadow::default(), } } Container::Custom(custom) => custom.appearance(self), diff --git a/widget/src/button.rs b/widget/src/button.rs index cd1411691a..14626dd378 100644 --- a/widget/src/button.rs +++ b/widget/src/button.rs @@ -392,15 +392,14 @@ where }; if styling.background.is_some() - || styling.shadow.color.a > 0.0 || styling.border.width > 0.0 + || styling.shadow.color.a > 0.0 { renderer.fill_quad( renderer::Quad { bounds, border: styling.border, shadow: styling.shadow, - ..renderer::Quad::default() }, styling .background diff --git a/widget/src/container.rs b/widget/src/container.rs index b87f1d9f3a..f2d1aabaa9 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -337,12 +337,15 @@ pub fn draw_background( ) where Renderer: crate::core::Renderer, { - if appearance.background.is_some() || appearance.border.width > 0.0 { + if appearance.background.is_some() + || appearance.border.width > 0.0 + || appearance.shadow.color.a > 0.0 + { renderer.fill_quad( renderer::Quad { bounds, border: appearance.border, - ..renderer::Quad::default() + shadow: appearance.shadow, }, appearance .background From 1c1667c3c99fa9b1009ef416b9b3c7e5a1d53a97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Sat, 20 Jan 2024 13:41:51 +0100 Subject: [PATCH 9/9] Inline `quad_pos` and `quad_scale` definitions --- wgpu/src/shader/quad/solid.wgsl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/wgpu/src/shader/quad/solid.wgsl b/wgpu/src/shader/quad/solid.wgsl index cb4a38162e..1274f81481 100644 --- a/wgpu/src/shader/quad/solid.wgsl +++ b/wgpu/src/shader/quad/solid.wgsl @@ -29,9 +29,7 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { var out: SolidVertexOutput; var pos: vec2 = (input.pos + min(input.shadow_offset, vec2(0.0, 0.0)) - input.shadow_blur_radius) * globals.scale; - var quad_pos: vec2 = input.pos * globals.scale; var scale: vec2 = (input.scale + vec2(abs(input.shadow_offset.x), abs(input.shadow_offset.y)) + input.shadow_blur_radius * 2.0) * globals.scale; - var quad_scale: vec2 = input.scale * globals.scale; var min_border_radius = min(input.scale.x, input.scale.y) * 0.5; var border_radius: vec4 = vec4( @@ -51,8 +49,8 @@ fn solid_vs_main(input: SolidVertexInput) -> SolidVertexOutput { out.position = globals.transform * transform * vec4(vertex_position(input.vertex_index), 0.0, 1.0); out.color = input.color; out.border_color = input.border_color; - out.pos = quad_pos; - out.scale = quad_scale; + out.pos = input.pos * globals.scale; + out.scale = input.scale * globals.scale; out.border_radius = border_radius * globals.scale; out.border_width = input.border_width * globals.scale; out.shadow_color = input.shadow_color;