summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
authorLibravatar Bingus <shankern@protonmail.com>2023-05-11 09:12:06 -0700
committerLibravatar Bingus <shankern@protonmail.com>2023-05-11 11:13:44 -0700
commit6551a0b2ab6c831dd1d3646ecf55180339275e22 (patch)
treede1e4a85b3176f94fd006fed190ef035d3202e49 /graphics
parent669f7cc74b2e7918e86a8197916f503f2d3d9b93 (diff)
downloadiced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.gz
iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.bz2
iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.zip
Added support for gradients as background variants + other optimizations.
Diffstat (limited to '')
-rw-r--r--graphics/src/geometry/fill.rs3
-rw-r--r--graphics/src/geometry/style.rs3
-rw-r--r--graphics/src/gradient.rs119
-rw-r--r--graphics/src/lib.rs2
-rw-r--r--graphics/src/primitive.rs32
-rw-r--r--graphics/src/triangle.rs1
6 files changed, 144 insertions, 16 deletions
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<ColorStop>; 8],
+ }
+
+ /// A [`Linear`] builder.
+ #[derive(Debug)]
+ pub struct Builder {
+ start: Point,
+ end: Point,
+ stops: [Option<ColorStop>; 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<Item = ColorStop>,
+ ) -> 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<Vertex2D>,
+ buffers: Mesh2D<GradientVertex2D>,
/// 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<T> {
pub indices: Vec<u32>,
}
-/// 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.