From 8b6be3d07c5ce4e364702a8f87f60ed5b029b21c Mon Sep 17 00:00:00 2001 From: Bingus Date: Wed, 22 Mar 2023 19:15:03 -0700 Subject: [PATCH] Changed linear gradient builder to not have a result. --- core/Cargo.toml | 2 +- core/src/gradient.rs | 63 +++++++++++-------------------- examples/solar_system/src/main.rs | 3 +- examples/tour/src/main.rs | 2 - graphics/src/gradient.rs | 50 +++++++++++------------- tiny_skia/src/backend.rs | 2 +- tiny_skia/src/geometry.rs | 2 +- wgpu/src/geometry.rs | 8 ++-- wgpu/src/layer.rs | 7 ++-- 9 files changed, 59 insertions(+), 80 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index dac3182868..82bb87f704 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -9,7 +9,7 @@ repository = "https://github.com/iced-rs/iced" [dependencies] bitflags = "1.2" -thiserror = "1" +log = "0.4" twox-hash = { version = "1.5", default-features = false } [dependencies.palette] diff --git a/core/src/gradient.rs b/core/src/gradient.rs index 7e90c2d83f..eac9f6f4ec 100644 --- a/core/src/gradient.rs +++ b/core/src/gradient.rs @@ -26,7 +26,7 @@ impl Gradient { pub fn mul_alpha(mut self, alpha_multiplier: f32) -> Self { match &mut self { Gradient::Linear(linear) => { - for stop in &mut linear.color_stops { + for stop in linear.color_stops.iter_mut().flatten() { stop.color.a *= alpha_multiplier; } } @@ -54,6 +54,7 @@ pub mod linear { //! Linear gradient builder & definition. use crate::gradient::{ColorStop, Gradient}; use crate::{Color, Radians}; + use std::cmp::Ordering; /// A linear gradient that can be used as a [`Background`]. #[derive(Debug, Clone, Copy, PartialEq)] @@ -61,15 +62,14 @@ pub mod linear { /// How the [`Gradient`] is angled within its bounds. pub angle: Radians, /// [`ColorStop`]s along the linear gradient path. - pub color_stops: [ColorStop; 8], + pub color_stops: [Option; 8], } /// A [`Linear`] builder. #[derive(Debug)] pub struct Builder { angle: Radians, - stops: [ColorStop; 8], - error: Option, + stops: [Option; 8], } impl Builder { @@ -77,11 +77,7 @@ pub mod linear { pub fn new(angle: Radians) -> Self { Self { angle, - stops: std::array::from_fn(|_| ColorStop { - offset: 2.0, //default offset = invalid - color: Default::default(), - }), - error: None, + stops: [None; 8], } } @@ -92,20 +88,27 @@ pub mod linear { /// Any stop added after the 8th will be silently ignored. pub fn add_stop(mut self, offset: f32, color: Color) -> Self { if offset.is_finite() && (0.0..=1.0).contains(&offset) { - match self.stops.binary_search_by(|stop| { - stop.offset.partial_cmp(&offset).unwrap() + match self.stops.binary_search_by(|stop| match stop { + None => Ordering::Greater, + Some(stop) => stop.offset.partial_cmp(&offset).unwrap(), }) { - Ok(_) => { - self.error = Some(BuilderError::DuplicateOffset(offset)) + Ok(index) => { + if index < 8 { + self.stops[index] = + Some(ColorStop { offset, color }); + } } Err(index) => { if index < 8 { - self.stops[index] = ColorStop { offset, color }; + self.stops[index] = + Some(ColorStop { offset, color }); } } } } else { - self.error = Some(BuilderError::InvalidOffset(offset)) + log::warn!( + "Gradient: ColorStop must be within 0.0..=1.0 range." + ); }; self @@ -128,31 +131,11 @@ pub mod linear { /// Builds the linear [`Gradient`] of this [`Builder`]. /// /// Returns `BuilderError` if gradient in invalid. - pub fn build(self) -> Result { - if self.stops.is_empty() { - Err(BuilderError::MissingColorStop) - } else if let Some(error) = self.error { - Err(error) - } else { - Ok(Gradient::Linear(Linear { - angle: self.angle, - color_stops: self.stops, - })) - } + pub fn build(self) -> Gradient { + Gradient::Linear(Linear { + angle: self.angle, + color_stops: self.stops, + }) } } - - /// An error that happened when building a [`Linear`] gradient. - #[derive(Debug, thiserror::Error)] - pub enum BuilderError { - #[error("Gradients must contain at least one color stop.")] - /// Gradients must contain at least one color stop. - MissingColorStop, - #[error("Offset {0} must be a unique, finite number.")] - /// Offsets in a gradient must all be unique & finite. - DuplicateOffset(f32), - #[error("Offset {0} must be between 0.0..=1.0.")] - /// Offsets in a gradient must be between 0.0..=1.0. - InvalidOffset(f32), - } } diff --git a/examples/solar_system/src/main.rs b/examples/solar_system/src/main.rs index c09cd8cfbc..42606e3f96 100644 --- a/examples/solar_system/src/main.rs +++ b/examples/solar_system/src/main.rs @@ -215,8 +215,7 @@ impl canvas::Program for State { ) .add_stop(0.2, Color::from_rgb(0.15, 0.50, 1.0)) .add_stop(0.8, Color::from_rgb(0.0, 0.20, 0.47)) - .build() - .expect("Build Earth fill gradient"); + .build(); frame.fill(&earth, earth_fill); diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index 13a84ec6f6..0d668cbce3 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -690,7 +690,6 @@ impl widget::button::StyleSheet for CustomButtonStyle { .add_stop(0.0, Palette::LIGHT.primary) .add_stop(1.0, Color::from_rgb8(54, 80, 168)) .build() - .expect("Build gradient") .into(), text_color: Color::WHITE, border_radius: 5.0, @@ -703,7 +702,6 @@ impl widget::button::StyleSheet for CustomButtonStyle { .add_stop(0.0, Color::from_rgb8(194, 194, 194)) .add_stop(1.0, Color::from_rgb8(126, 126, 126)) .build() - .expect("Build gradient") .into(), text_color: Color::WHITE, border_radius: 5.0, diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs index adfe414f2d..8ddad8f99d 100644 --- a/graphics/src/gradient.rs +++ b/graphics/src/gradient.rs @@ -25,9 +25,9 @@ impl Gradient { pub mod linear { //! Linear gradient builder & definition. use crate::Gradient; - use iced_core::gradient::linear::BuilderError; use iced_core::gradient::ColorStop; use iced_core::{Color, Point}; + use std::cmp::Ordering; /// A linear gradient that can be used in the style of [`Fill`] or [`Stroke`]. /// @@ -42,7 +42,7 @@ pub mod linear { pub end: Point, /// [`ColorStop`]s along the linear gradient path. - pub color_stops: [ColorStop; 8], + pub color_stops: [Option; 8], } /// A [`Linear`] builder. @@ -50,8 +50,7 @@ pub mod linear { pub struct Builder { start: Point, end: Point, - stops: [ColorStop; 8], - error: Option, + stops: [Option; 8], } impl Builder { @@ -60,11 +59,7 @@ pub mod linear { Self { start, end, - stops: std::array::from_fn(|_| ColorStop { - offset: 2.0, //default offset = invalid - color: Default::default(), - }), - error: None, + stops: [None; 8], } } @@ -75,20 +70,27 @@ pub mod linear { /// Any stop added after the 8th will be silently ignored. pub fn add_stop(mut self, offset: f32, color: Color) -> Self { if offset.is_finite() && (0.0..=1.0).contains(&offset) { - match self.stops.binary_search_by(|stop| { - stop.offset.partial_cmp(&offset).unwrap() + match self.stops.binary_search_by(|stop| match stop { + None => Ordering::Greater, + Some(stop) => stop.offset.partial_cmp(&offset).unwrap(), }) { - Ok(_) => { - self.error = Some(BuilderError::DuplicateOffset(offset)) + Ok(index) => { + if index < 8 { + self.stops[index] = + Some(ColorStop { offset, color }); + } } Err(index) => { if index < 8 { - self.stops[index] = ColorStop { offset, color }; + self.stops[index] = + Some(ColorStop { offset, color }); } } } } else { - self.error = Some(BuilderError::InvalidOffset(offset)) + log::warn!( + "Gradient: ColorStop must be within 0.0..=1.0 range." + ); }; self @@ -111,18 +113,12 @@ pub mod linear { /// Builds the linear [`Gradient`] of this [`Builder`]. /// /// Returns `BuilderError` if gradient in invalid. - pub fn build(self) -> Result { - if self.stops.is_empty() { - Err(BuilderError::MissingColorStop) - } else if let Some(error) = self.error { - Err(error) - } else { - Ok(Gradient::Linear(Linear { - start: self.start, - end: self.end, - color_stops: self.stops, - })) - } + pub fn build(self) -> Gradient { + Gradient::Linear(Linear { + start: self.start, + end: self.end, + color_stops: self.stops, + }) } } } diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 7acab649af..ee10cc1984 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -337,7 +337,7 @@ fn into_gradient<'a>( linear .color_stops .into_iter() - .filter(|stop| stop.offset <= 1.0) + .flatten() .map(|stop| { tiny_skia::GradientStop::new( stop.offset, diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index bf03fae375..7e07ee67bf 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -230,7 +230,7 @@ pub fn into_paint(style: Style) -> tiny_skia::Paint<'static> { linear .color_stops .into_iter() - .filter(|stop| stop.offset <= 1.0) + .flatten() .map(|stop| { tiny_skia::GradientStop::new( stop.offset, diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 44b1a89f57..5e98bcd6ee 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -626,15 +626,17 @@ fn pack_gradient(gradient: &Gradient) -> [f32; 44] { let mut pack: [f32; 44] = [0.0; 44]; let mut offsets: [f32; 8] = [2.0; 8]; - for (index, stop) in linear.color_stops.iter().enumerate().take(8) { - let [r, g, b, a] = stop.color.into_linear(); + for (index, stop) in linear.color_stops.iter().enumerate() { + let [r, g, b, a] = stop + .map_or(crate::core::Color::default(), |s| s.color) + .into_linear(); pack[(index * 4)] = r; pack[(index * 4) + 1] = g; pack[(index * 4) + 2] = b; pack[(index * 4) + 3] = a; - offsets[index] = stop.offset; + offsets[index] = stop.map_or(2.0, |s| s.offset); } pack[32] = offsets[0]; diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index f982818e80..d9a9c82d2f 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -309,14 +309,15 @@ fn pack_gradient( crate::core::Gradient::Linear(linear) => { let mut pack: [f32; 44] = [0.0; 44]; - for (index, stop) in linear.color_stops.iter().enumerate().take(8) { - let [r, g, b, a] = stop.color.into_linear(); + for (index, stop) in linear.color_stops.iter().enumerate() { + let [r, g, b, a] = + stop.map_or(Color::default(), |s| s.color).into_linear(); pack[(index * 4)] = r; pack[(index * 4) + 1] = g; pack[(index * 4) + 2] = b; pack[(index * 4) + 3] = a; - pack[32 + index] = stop.offset; + pack[32 + index] = stop.map_or(2.0, |s| s.offset); } let (start, end) = linear.angle.to_distance(&bounds);