summaryrefslogtreecommitdiffstats
path: root/wgpu/src/layer.rs
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 /wgpu/src/layer.rs
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 'wgpu/src/layer.rs')
-rw-r--r--wgpu/src/layer.rs94
1 files changed, 77 insertions, 17 deletions
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs
index 8af72b9d..b3ee4739 100644
--- a/wgpu/src/layer.rs
+++ b/wgpu/src/layer.rs
@@ -1,13 +1,13 @@
//! Organize rendering primitives into a flattened list of layers.
mod image;
-mod quad;
mod text;
pub mod mesh;
+pub mod quad;
pub use image::Image;
pub use mesh::Mesh;
-pub use quad::Quad;
+use quad::Quad;
pub use text::Text;
use crate::core;
@@ -22,7 +22,7 @@ pub struct Layer<'a> {
pub bounds: Rectangle,
/// The quads of the [`Layer`].
- pub quads: Vec<Quad>,
+ pub quads: Quads,
/// The triangle meshes of the [`Layer`].
pub meshes: Vec<Mesh<'a>>,
@@ -34,12 +34,29 @@ pub struct Layer<'a> {
pub images: Vec<Image>,
}
+/// The quads of the [`Layer`].
+#[derive(Default, Debug)]
+pub struct Quads {
+ /// The solid quads of the [`Layer`].
+ pub solids: Vec<quad::Solid>,
+
+ /// The gradient quads of the [`Layer`].
+ pub gradients: Vec<quad::Gradient>,
+}
+
+impl Quads {
+ /// Returns true if there are no quads of any type in [`Quads`].
+ pub fn is_empty(&self) -> bool {
+ self.solids.is_empty() && self.gradients.is_empty()
+ }
+}
+
impl<'a> Layer<'a> {
/// Creates a new [`Layer`] with the given clipping bounds.
pub fn new(bounds: Rectangle) -> Self {
Self {
bounds,
- quads: Vec::new(),
+ quads: Quads::default(),
meshes: Vec::new(),
text: Vec::new(),
images: Vec::new(),
@@ -145,20 +162,39 @@ impl<'a> Layer<'a> {
} => {
let layer = &mut layers[current_layer];
- // TODO: Move some of these computations to the GPU (?)
- layer.quads.push(Quad {
+ let quad = Quad {
position: [
bounds.x + translation.x,
bounds.y + translation.y,
],
size: [bounds.width, bounds.height],
- color: match background {
- Background::Color(color) => color.into_linear(),
- },
+ border_color: border_color.into_linear(),
border_radius: *border_radius,
border_width: *border_width,
- border_color: border_color.into_linear(),
- });
+ };
+
+ match background {
+ Background::Color(color) => {
+ layer.quads.solids.push(quad::Solid {
+ color: color.into_linear(),
+ quad,
+ });
+ }
+ Background::Gradient(gradient) => {
+ let quad = quad::Gradient {
+ gradient: pack_gradient(
+ gradient,
+ Rectangle::new(
+ quad.position.into(),
+ quad.size.into(),
+ ),
+ ),
+ quad,
+ };
+
+ layer.quads.gradients.push(quad);
+ }
+ };
}
Primitive::Image { handle, bounds } => {
let layer = &mut layers[current_layer];
@@ -198,11 +234,7 @@ impl<'a> Layer<'a> {
});
}
}
- Primitive::GradientMesh {
- buffers,
- size,
- gradient,
- } => {
+ Primitive::GradientMesh { buffers, size } => {
let layer = &mut layers[current_layer];
let bounds = Rectangle::new(
@@ -216,7 +248,6 @@ impl<'a> Layer<'a> {
origin: Point::new(translation.x, translation.y),
buffers,
clip_bounds,
- gradient,
});
}
}
@@ -279,3 +310,32 @@ impl<'a> Layer<'a> {
}
}
}
+
+/// Packs the [`Gradient`] for use in shader code.
+fn pack_gradient(gradient: &core::Gradient, bounds: Rectangle) -> [f32; 44] {
+ match gradient {
+ core::Gradient::Linear(linear) => {
+ let mut pack: [f32; 44] = [0.0; 44];
+
+ 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.map_or(2.0, |s| s.offset);
+ }
+
+ let (start, end) = linear.angle.to_distance(&bounds);
+
+ pack[40] = start.x;
+ pack[41] = start.y;
+ pack[42] = end.x;
+ pack[43] = end.y;
+
+ pack
+ }
+ }
+}