Skip to content

Commit

Permalink
Changed linear gradient builder to not have a result.
Browse files Browse the repository at this point in the history
  • Loading branch information
bungoboingo committed Mar 23, 2023
1 parent f60c065 commit 8b6be3d
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 80 deletions.
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
63 changes: 23 additions & 40 deletions core/src/gradient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -54,34 +54,30 @@ 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)]
pub struct 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<ColorStop>; 8],
}

/// A [`Linear`] builder.
#[derive(Debug)]
pub struct Builder {
angle: Radians,
stops: [ColorStop; 8],
error: Option<BuilderError>,
stops: [Option<ColorStop>; 8],
}

impl Builder {
/// Creates a new [`Builder`].
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],
}
}

Expand All @@ -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
Expand All @@ -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<Gradient, BuilderError> {
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),
}
}
3 changes: 1 addition & 2 deletions examples/solar_system/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,7 @@ impl<Message> canvas::Program<Message> 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);

Expand Down
2 changes: 0 additions & 2 deletions examples/tour/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
50 changes: 23 additions & 27 deletions graphics/src/gradient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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`].
///
Expand All @@ -42,16 +42,15 @@ pub mod linear {
pub end: Point,

/// [`ColorStop`]s along the linear gradient path.
pub color_stops: [ColorStop; 8],
pub color_stops: [Option<ColorStop>; 8],
}

/// A [`Linear`] builder.
#[derive(Debug)]
pub struct Builder {
start: Point,
end: Point,
stops: [ColorStop; 8],
error: Option<BuilderError>,
stops: [Option<ColorStop>; 8],
}

impl Builder {
Expand All @@ -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],
}
}

Expand All @@ -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
Expand All @@ -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<Gradient, BuilderError> {
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,
})
}
}
}
2 changes: 1 addition & 1 deletion tiny_skia/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion tiny_skia/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 5 additions & 3 deletions wgpu/src/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
7 changes: 4 additions & 3 deletions wgpu/src/layer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 8b6be3d

Please sign in to comment.