diff options
author | 2023-05-11 09:12:06 -0700 | |
---|---|---|
committer | 2023-05-11 11:13:44 -0700 | |
commit | 6551a0b2ab6c831dd1d3646ecf55180339275e22 (patch) | |
tree | de1e4a85b3176f94fd006fed190ef035d3202e49 /wgpu/src/geometry.rs | |
parent | 669f7cc74b2e7918e86a8197916f503f2d3d9b93 (diff) | |
download | iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.gz iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.tar.bz2 iced-6551a0b2ab6c831dd1d3646ecf55180339275e22.zip |
Added support for gradients as background variants + other optimizations.
Diffstat (limited to 'wgpu/src/geometry.rs')
-rw-r--r-- | wgpu/src/geometry.rs | 111 |
1 files changed, 81 insertions, 30 deletions
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 7e17a7ad..e26d9278 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -1,10 +1,11 @@ //! Build and draw geometry. -use crate::core::{Gradient, Point, Rectangle, Size, Vector}; +use crate::core::{Point, Rectangle, Size, Vector}; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::{ LineCap, LineDash, LineJoin, Path, Stroke, Style, Text, }; use crate::graphics::primitive::{self, Primitive}; +use crate::graphics::Gradient; use lyon::geom::euclid; use lyon::tessellation; @@ -23,10 +24,7 @@ pub struct Frame { enum Buffer { Solid(tessellation::VertexBuffers<primitive::ColoredVertex2D, u32>), - Gradient( - tessellation::VertexBuffers<primitive::Vertex2D, u32>, - Gradient, - ), + Gradient(tessellation::VertexBuffers<primitive::GradientVertex2D, u32>), } struct BufferStack { @@ -48,12 +46,11 @@ impl BufferStack { )); } }, - Style::Gradient(gradient) => match self.stack.last() { - Some(Buffer::Gradient(_, last)) if gradient == last => {} + Style::Gradient(_) => match self.stack.last() { + Some(Buffer::Gradient(_)) => {} _ => { self.stack.push(Buffer::Gradient( tessellation::VertexBuffers::new(), - gradient.clone(), )); } }, @@ -73,9 +70,14 @@ impl BufferStack { TriangleVertex2DBuilder(color.into_linear()), )) } - (Style::Gradient(_), Buffer::Gradient(buffer, _)) => Box::new( - tessellation::BuffersBuilder::new(buffer, Vertex2DBuilder), - ), + (Style::Gradient(gradient), Buffer::Gradient(buffer)) => { + Box::new(tessellation::BuffersBuilder::new( + buffer, + GradientVertex2DBuilder { + gradient: gradient.clone(), + }, + )) + } _ => unreachable!(), } } @@ -91,9 +93,14 @@ impl BufferStack { TriangleVertex2DBuilder(color.into_linear()), )) } - (Style::Gradient(_), Buffer::Gradient(buffer, _)) => Box::new( - tessellation::BuffersBuilder::new(buffer, Vertex2DBuilder), - ), + (Style::Gradient(gradient), Buffer::Gradient(buffer)) => { + Box::new(tessellation::BuffersBuilder::new( + buffer, + GradientVertex2DBuilder { + gradient: gradient.clone(), + }, + )) + } _ => unreachable!(), } } @@ -131,11 +138,13 @@ impl Transform { } fn transform_gradient(&self, mut gradient: Gradient) -> Gradient { - let (start, end) = match &mut gradient { - Gradient::Linear(linear) => (&mut linear.start, &mut linear.end), - }; - self.transform_point(start); - self.transform_point(end); + match &mut gradient { + Gradient::Linear(linear) => { + self.transform_point(&mut linear.start); + self.transform_point(&mut linear.end); + } + } + gradient } } @@ -462,7 +471,7 @@ impl Frame { }) } } - Buffer::Gradient(buffer, gradient) => { + Buffer::Gradient(buffer) => { if !buffer.indices.is_empty() { self.primitives.push(Primitive::GradientMesh { buffers: primitive::Mesh2D { @@ -470,7 +479,6 @@ impl Frame { indices: buffer.indices, }, size: self.size, - gradient, }) } } @@ -481,34 +489,38 @@ impl Frame { } } -struct Vertex2DBuilder; +struct GradientVertex2DBuilder { + gradient: Gradient, +} -impl tessellation::FillVertexConstructor<primitive::Vertex2D> - for Vertex2DBuilder +impl tessellation::FillVertexConstructor<primitive::GradientVertex2D> + for GradientVertex2DBuilder { fn new_vertex( &mut self, vertex: tessellation::FillVertex<'_>, - ) -> primitive::Vertex2D { + ) -> primitive::GradientVertex2D { let position = vertex.position(); - primitive::Vertex2D { + primitive::GradientVertex2D { position: [position.x, position.y], + gradient: pack_gradient(&self.gradient), } } } -impl tessellation::StrokeVertexConstructor<primitive::Vertex2D> - for Vertex2DBuilder +impl tessellation::StrokeVertexConstructor<primitive::GradientVertex2D> + for GradientVertex2DBuilder { fn new_vertex( &mut self, vertex: tessellation::StrokeVertex<'_, '_>, - ) -> primitive::Vertex2D { + ) -> primitive::GradientVertex2D { let position = vertex.position(); - primitive::Vertex2D { + primitive::GradientVertex2D { position: [position.x, position.y], + gradient: pack_gradient(&self.gradient), } } } @@ -611,3 +623,42 @@ pub(super) fn dashed(path: &Path, line_dash: LineDash<'_>) -> Path { ); }) } + +/// Packs the [`Gradient`] for use in shader code. +fn pack_gradient(gradient: &Gradient) -> [f32; 44] { + match gradient { + Gradient::Linear(linear) => { + 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() { + 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.map_or(2.0, |s| s.offset); + } + + pack[32] = offsets[0]; + pack[33] = offsets[1]; + pack[34] = offsets[2]; + pack[35] = offsets[3]; + pack[36] = offsets[4]; + pack[37] = offsets[5]; + pack[38] = offsets[6]; + pack[39] = offsets[7]; + + pack[40] = linear.start.x; + pack[41] = linear.start.y; + pack[42] = linear.end.x; + pack[43] = linear.end.y; + + pack + } + } +} |