From 6551a0b2ab6c831dd1d3646ecf55180339275e22 Mon Sep 17 00:00:00 2001 From: Bingus Date: Thu, 11 May 2023 09:12:06 -0700 Subject: Added support for gradients as background variants + other optimizations. --- graphics/src/geometry/fill.rs | 3 +- graphics/src/geometry/style.rs | 3 +- graphics/src/gradient.rs | 119 +++++++++++++++++++++++++++++++++++++++++ graphics/src/lib.rs | 2 + graphics/src/primitive.rs | 32 ++++++----- graphics/src/triangle.rs | 1 - 6 files changed, 144 insertions(+), 16 deletions(-) create mode 100644 graphics/src/gradient.rs delete mode 100644 graphics/src/triangle.rs (limited to 'graphics') diff --git a/graphics/src/geometry/fill.rs b/graphics/src/geometry/fill.rs index 2e8c1669..6aa1f28b 100644 --- a/graphics/src/geometry/fill.rs +++ b/graphics/src/geometry/fill.rs @@ -1,7 +1,8 @@ //! Fill [crate::widget::canvas::Geometry] with a certain style. -use iced_core::{Color, Gradient}; +use iced_core::Color; pub use crate::geometry::Style; +use crate::Gradient; /// The style used to fill geometry. #[derive(Debug, Clone)] diff --git a/graphics/src/geometry/style.rs b/graphics/src/geometry/style.rs index be9ee376..ece6b32a 100644 --- a/graphics/src/geometry/style.rs +++ b/graphics/src/geometry/style.rs @@ -1,4 +1,5 @@ -use iced_core::{Color, Gradient}; +use crate::Gradient; +use iced_core::Color; /// The coloring style of some drawing. #[derive(Debug, Clone, PartialEq)] diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs new file mode 100644 index 00000000..21bcd2c6 --- /dev/null +++ b/graphics/src/gradient.rs @@ -0,0 +1,119 @@ +//! A gradient that can be used as a [`Fill`] for a mesh. +//! +//! For a gradient that you can use as a background variant for a widget, see [`Gradient`]. +//! +//! [`Gradient`]: crate::core::Gradient; +use crate::core::Point; +pub use linear::Linear; + +#[derive(Debug, Clone, PartialEq)] +/// A fill which linearly interpolates colors along a direction. +/// +/// For a gradient which can be used as a fill for a background of a widget, see [`crate::core::Gradient`]. +pub enum Gradient { + /// A linear gradient interpolates colors along a direction from its `start` to its `end` + /// point. + Linear(Linear), +} + +impl Gradient { + /// Creates a new linear [`linear::Builder`]. + /// + /// The `start` and `end` [`Point`]s define the absolute position of the [`Gradient`]. + pub fn linear(start: Point, end: Point) -> linear::Builder { + linear::Builder::new(start, end) + } +} + +pub mod linear { + //! Linear gradient builder & definition. + use crate::Gradient; + 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`]. + /// + /// [`Fill`]: crate::geometry::Fill; + /// [`Stroke`]: crate::geometry::Stroke; + #[derive(Debug, Clone, Copy, PartialEq)] + pub struct Linear { + /// The absolute starting position of the gradient. + pub start: Point, + + /// The absolute ending position of the gradient. + pub end: Point, + + /// [`ColorStop`]s along the linear gradient direction. + pub color_stops: [Option; 8], + } + + /// A [`Linear`] builder. + #[derive(Debug)] + pub struct Builder { + start: Point, + end: Point, + stops: [Option; 8], + } + + impl Builder { + /// Creates a new [`Builder`]. + pub fn new(start: Point, end: Point) -> Self { + Self { + start, + end, + stops: [None; 8], + } + } + + /// Adds a new [`ColorStop`], defined by an offset and a color, to the gradient. + /// + /// Any `offset` that is not within `0.0..=1.0` will be silently ignored. + /// + /// 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) { + let (Ok(index) | Err(index)) = + self.stops.binary_search_by(|stop| match stop { + None => Ordering::Greater, + Some(stop) => stop.offset.partial_cmp(&offset).unwrap(), + }); + + if index < 8 { + self.stops[index] = Some(ColorStop { offset, color }); + } + } else { + log::warn!( + "Gradient: ColorStop must be within 0.0..=1.0 range." + ); + }; + + self + } + + /// Adds multiple [`ColorStop`]s to the gradient. + /// + /// Any stop added after the 8th will be silently ignored. + pub fn add_stops( + mut self, + stops: impl IntoIterator, + ) -> Self { + for stop in stops.into_iter() { + self = self.add_stop(stop.offset, stop.color) + } + + self + } + + /// Builds the linear [`Gradient`] of this [`Builder`]. + /// + /// Returns `BuilderError` if gradient in invalid. + pub fn build(self) -> Gradient { + Gradient::Linear(Linear { + start: self.start, + end: self.end, + color_stops: self.stops, + }) + } + } +} diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index 91f50282..ae338936 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -23,6 +23,7 @@ #![cfg_attr(docsrs, feature(doc_cfg))] mod antialiasing; mod error; +mod gradient; mod transformation; mod viewport; @@ -42,6 +43,7 @@ pub use antialiasing::Antialiasing; pub use backend::Backend; pub use compositor::Compositor; pub use error::Error; +pub use gradient::Gradient; pub use primitive::Primitive; pub use renderer::Renderer; pub use transformation::Transformation; diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index d4446c87..9728db39 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -3,7 +3,7 @@ use crate::core::alignment; use crate::core::image; use crate::core::svg; use crate::core::text; -use crate::core::{Background, Color, Font, Gradient, Rectangle, Size, Vector}; +use crate::core::{Background, Color, Font, Rectangle, Size, Vector}; use bytemuck::{Pod, Zeroable}; use std::sync::Arc; @@ -39,7 +39,7 @@ pub enum Primitive { bounds: Rectangle, /// The background of the quad background: Background, - /// The border radius of the quad + /// The border radii of the quad border_radius: [f32; 4], /// The border width of the quad border_width: f32, @@ -81,15 +81,12 @@ pub enum Primitive { /// It can be used to render many kinds of geometry freely. GradientMesh { /// The vertices and indices of the mesh. - buffers: Mesh2D, + buffers: Mesh2D, /// The size of the drawable region of the mesh. /// /// Any geometry that falls out of this region will be clipped. size: Size, - - /// The [`Gradient`] to apply to the mesh. - gradient: Gradient, }, /// A [`tiny_skia`] path filled with some paint. #[cfg(feature = "tiny-skia")] @@ -242,25 +239,34 @@ pub struct Mesh2D { pub indices: Vec, } -/// A two-dimensional vertex. +/// A two-dimensional vertex with a color. #[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)] #[repr(C)] -pub struct Vertex2D { +pub struct ColoredVertex2D { /// The vertex position in 2D space. pub position: [f32; 2], + + /// The color of the vertex in __linear__ RGBA. + pub color: [f32; 4], } -/// A two-dimensional vertex with a color. -#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)] +/// A vertex which contains 2D position & packed gradient data. +#[derive(Copy, Clone, Debug, PartialEq)] #[repr(C)] -pub struct ColoredVertex2D { +pub struct GradientVertex2D { /// The vertex position in 2D space. pub position: [f32; 2], - /// The color of the vertex in __linear__ RGBA. - pub color: [f32; 4], + /// The packed vertex data of the gradient. + pub gradient: [f32; 44], } +#[allow(unsafe_code)] +unsafe impl Zeroable for GradientVertex2D {} + +#[allow(unsafe_code)] +unsafe impl Pod for GradientVertex2D {} + impl From<()> for Primitive { fn from(_: ()) -> Self { Self::Group { primitives: vec![] } diff --git a/graphics/src/triangle.rs b/graphics/src/triangle.rs deleted file mode 100644 index 09b61767..00000000 --- a/graphics/src/triangle.rs +++ /dev/null @@ -1 +0,0 @@ -//! Draw geometry using meshes of triangles. -- cgit From 4c1a082f0468a59099bbf8aa8991420a41234948 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 19 May 2023 03:32:21 +0200 Subject: Remove `Builder` abstractions for gradients --- graphics/src/geometry.rs | 2 +- graphics/src/geometry/fill.rs | 15 ++++- graphics/src/gradient.rs | 145 +++++++++++++++++------------------------- graphics/src/lib.rs | 2 +- 4 files changed, 71 insertions(+), 93 deletions(-) (limited to 'graphics') diff --git a/graphics/src/geometry.rs b/graphics/src/geometry.rs index 88997288..729c3d44 100644 --- a/graphics/src/geometry.rs +++ b/graphics/src/geometry.rs @@ -12,7 +12,7 @@ pub use stroke::{LineCap, LineDash, LineJoin, Stroke}; pub use style::Style; pub use text::Text; -pub use crate::core::gradient::{self, Gradient}; +pub use crate::gradient::{self, Gradient}; use crate::Primitive; diff --git a/graphics/src/geometry/fill.rs b/graphics/src/geometry/fill.rs index 6aa1f28b..b773c99b 100644 --- a/graphics/src/geometry/fill.rs +++ b/graphics/src/geometry/fill.rs @@ -1,8 +1,8 @@ //! Fill [crate::widget::canvas::Geometry] with a certain style. -use iced_core::Color; - pub use crate::geometry::Style; -use crate::Gradient; + +use crate::core::Color; +use crate::gradient::{self, Gradient}; /// The style used to fill geometry. #[derive(Debug, Clone)] @@ -50,6 +50,15 @@ impl From for Fill { } } +impl From for Fill { + fn from(gradient: gradient::Linear) -> Self { + Fill { + style: Style::Gradient(Gradient::Linear(gradient)), + ..Default::default() + } + } +} + /// The fill rule defines how to determine what is inside and what is outside of /// a shape. /// diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs index 21bcd2c6..3e88d9de 100644 --- a/graphics/src/gradient.rs +++ b/graphics/src/gradient.rs @@ -1,10 +1,11 @@ -//! A gradient that can be used as a [`Fill`] for a mesh. +//! A gradient that can be used as a [`Fill`] for some geometry. //! //! For a gradient that you can use as a background variant for a widget, see [`Gradient`]. //! //! [`Gradient`]: crate::core::Gradient; -use crate::core::Point; -pub use linear::Linear; +use crate::core::gradient::ColorStop; +use crate::core::{Color, Point}; +use std::cmp::Ordering; #[derive(Debug, Clone, PartialEq)] /// A fill which linearly interpolates colors along a direction. @@ -16,104 +17,72 @@ pub enum Gradient { Linear(Linear), } -impl Gradient { - /// Creates a new linear [`linear::Builder`]. - /// - /// The `start` and `end` [`Point`]s define the absolute position of the [`Gradient`]. - pub fn linear(start: Point, end: Point) -> linear::Builder { - linear::Builder::new(start, end) +impl From for Gradient { + fn from(gradient: Linear) -> Self { + Self::Linear(gradient) } } -pub mod linear { - //! Linear gradient builder & definition. - use crate::Gradient; - 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`]. +/// +/// [`Fill`]: crate::geometry::Fill; +/// [`Stroke`]: crate::geometry::Stroke; +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Linear { + /// The absolute starting position of the gradient. + pub start: Point, - /// A linear gradient that can be used in the style of [`Fill`] or [`Stroke`]. - /// - /// [`Fill`]: crate::geometry::Fill; - /// [`Stroke`]: crate::geometry::Stroke; - #[derive(Debug, Clone, Copy, PartialEq)] - pub struct Linear { - /// The absolute starting position of the gradient. - pub start: Point, + /// The absolute ending position of the gradient. + pub end: Point, - /// The absolute ending position of the gradient. - pub end: Point, + /// [`ColorStop`]s along the linear gradient direction. + pub stops: [Option; 8], +} - /// [`ColorStop`]s along the linear gradient direction. - pub color_stops: [Option; 8], +impl Linear { + /// Creates a new [`Builder`]. + pub fn new(start: Point, end: Point) -> Self { + Self { + start, + end, + stops: [None; 8], + } } - /// A [`Linear`] builder. - #[derive(Debug)] - pub struct Builder { - start: Point, - end: Point, - stops: [Option; 8], - } + /// Adds a new [`ColorStop`], defined by an offset and a color, to the gradient. + /// + /// Any `offset` that is not within `0.0..=1.0` will be silently ignored. + /// + /// 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) { + let (Ok(index) | Err(index)) = + self.stops.binary_search_by(|stop| match stop { + None => Ordering::Greater, + Some(stop) => stop.offset.partial_cmp(&offset).unwrap(), + }); - impl Builder { - /// Creates a new [`Builder`]. - pub fn new(start: Point, end: Point) -> Self { - Self { - start, - end, - stops: [None; 8], + if index < 8 { + self.stops[index] = Some(ColorStop { offset, color }); } - } + } else { + log::warn!("Gradient: ColorStop must be within 0.0..=1.0 range."); + }; - /// Adds a new [`ColorStop`], defined by an offset and a color, to the gradient. - /// - /// Any `offset` that is not within `0.0..=1.0` will be silently ignored. - /// - /// 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) { - let (Ok(index) | Err(index)) = - self.stops.binary_search_by(|stop| match stop { - None => Ordering::Greater, - Some(stop) => stop.offset.partial_cmp(&offset).unwrap(), - }); - - if index < 8 { - self.stops[index] = Some(ColorStop { offset, color }); - } - } else { - log::warn!( - "Gradient: ColorStop must be within 0.0..=1.0 range." - ); - }; - - self - } - - /// Adds multiple [`ColorStop`]s to the gradient. - /// - /// Any stop added after the 8th will be silently ignored. - pub fn add_stops( - mut self, - stops: impl IntoIterator, - ) -> Self { - for stop in stops.into_iter() { - self = self.add_stop(stop.offset, stop.color) - } + self + } - self + /// Adds multiple [`ColorStop`]s to the gradient. + /// + /// Any stop added after the 8th will be silently ignored. + pub fn add_stops( + mut self, + stops: impl IntoIterator, + ) -> Self { + for stop in stops.into_iter() { + self = self.add_stop(stop.offset, stop.color) } - /// Builds the linear [`Gradient`] of this [`Builder`]. - /// - /// Returns `BuilderError` if gradient in invalid. - pub fn build(self) -> Gradient { - Gradient::Linear(Linear { - start: self.start, - end: self.end, - color_stops: self.stops, - }) - } + self } } diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index ae338936..b44fd603 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -23,13 +23,13 @@ #![cfg_attr(docsrs, feature(doc_cfg))] mod antialiasing; mod error; -mod gradient; mod transformation; mod viewport; pub mod backend; pub mod compositor; pub mod damage; +pub mod gradient; pub mod primitive; pub mod renderer; -- cgit From 3d44de9547c770787edf6de3b683fe2b7e92ee09 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 19 May 2023 03:49:42 +0200 Subject: Fix imports of `geometry::style` in `iced_graphics` --- graphics/src/geometry/style.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'graphics') diff --git a/graphics/src/geometry/style.rs b/graphics/src/geometry/style.rs index ece6b32a..a0f4b08a 100644 --- a/graphics/src/geometry/style.rs +++ b/graphics/src/geometry/style.rs @@ -1,5 +1,5 @@ -use crate::Gradient; -use iced_core::Color; +use crate::core::Color; +use crate::geometry::Gradient; /// The coloring style of some drawing. #[derive(Debug, Clone, PartialEq)] -- cgit