diff options
-rw-r--r-- | graphics/src/layer/mesh.rs | 8 | ||||
-rw-r--r-- | graphics/src/widget/canvas/fill.rs | 6 | ||||
-rw-r--r-- | graphics/src/widget/canvas/frame.rs | 74 | ||||
-rw-r--r-- | wgpu/src/triangle/solid.rs | 7 |
4 files changed, 53 insertions, 42 deletions
diff --git a/graphics/src/layer/mesh.rs b/graphics/src/layer/mesh.rs index 0946317e..a2232a1f 100644 --- a/graphics/src/layer/mesh.rs +++ b/graphics/src/layer/mesh.rs @@ -1,7 +1,7 @@ //! A collection of triangle primitives. -use crate::{Color, Point, Rectangle, triangle}; use crate::gradient::Gradient; +use crate::{triangle, Color, Point, Rectangle}; /// A mesh of triangles. #[derive(Debug, Clone, Copy)] @@ -19,16 +19,16 @@ pub struct Mesh<'a> { pub style: &'a Style, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq)] /// Supported shaders for primitives. pub enum Style { /// Fill a primitive with a solid color. Solid(Color), /// Fill a primitive with an interpolated color. - Gradient(Gradient) + Gradient(Gradient), } -impl <'a> Into<Style> for Gradient { +impl<'a> Into<Style> for Gradient { fn into(self) -> Style { match self { Gradient::Linear(linear) => { diff --git a/graphics/src/widget/canvas/fill.rs b/graphics/src/widget/canvas/fill.rs index 34cc5e50..9582bf27 100644 --- a/graphics/src/widget/canvas/fill.rs +++ b/graphics/src/widget/canvas/fill.rs @@ -2,8 +2,8 @@ use crate::gradient::Gradient; use crate::layer::mesh; -use iced_native::Color; use crate::widget::canvas::frame::Transform; +use iced_native::Color; /// The style used to fill geometry. #[derive(Debug, Clone)] @@ -64,9 +64,7 @@ impl<'a> Style<'a> { /// Converts a fill's [Style] to a [mesh::Style] for use in the renderer's shader. pub(crate) fn as_mesh_style(&self, transform: &Transform) -> mesh::Style { match self { - Style::Solid(color) => { - mesh::Style::Solid(*color) - }, + Style::Solid(color) => mesh::Style::Solid(*color), Style::Gradient(gradient) => mesh::Style::Gradient( transform.transform_gradient((*gradient).clone()), ), diff --git a/graphics/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs index 3ba72179..677d7bc5 100644 --- a/graphics/src/widget/canvas/frame.rs +++ b/graphics/src/widget/canvas/frame.rs @@ -18,13 +18,41 @@ use lyon::tessellation; #[allow(missing_debug_implementations)] pub struct Frame { size: Size, - buffers: Vec<(tessellation::VertexBuffers<Vertex2D, u32>, mesh::Style)>, + buffers: BufferStack, primitives: Vec<Primitive>, transforms: Transforms, fill_tessellator: tessellation::FillTessellator, stroke_tessellator: tessellation::StrokeTessellator, } +struct BufferStack { + stack: Vec<(tessellation::VertexBuffers<Vertex2D, u32>, mesh::Style)>, +} + +impl BufferStack { + fn new() -> Self { + Self { stack: Vec::new() } + } + + fn get( + &mut self, + mesh_style: mesh::Style, + ) -> tessellation::BuffersBuilder<'_, Vertex2D, u32, Vertex2DBuilder> { + match self.stack.last_mut() { + Some((_, current_style)) if current_style == &mesh_style => {} + _ => { + self.stack + .push((tessellation::VertexBuffers::new(), mesh_style)); + } + }; + + tessellation::BuffersBuilder::new( + &mut self.stack.last_mut().unwrap().0, + Vertex2DBuilder, + ) + } +} + #[derive(Debug)] struct Transforms { previous: Vec<Transform>, @@ -67,7 +95,7 @@ impl Frame { pub fn new(size: Size) -> Frame { Frame { size, - buffers: Vec::new(), + buffers: BufferStack::new(), primitives: Vec::new(), transforms: Transforms { previous: Vec::new(), @@ -110,10 +138,9 @@ impl Frame { pub fn fill<'a>(&mut self, path: &Path, fill: impl Into<Fill<'a>>) { let Fill { style, rule } = fill.into(); - let mut buf = tessellation::VertexBuffers::new(); - - let mut buffers = - tessellation::BuffersBuilder::new(&mut buf, Vertex2DBuilder); + let mut buffer = self + .buffers + .get(style.as_mesh_style(&self.transforms.current)); let options = tessellation::FillOptions::default().with_fill_rule(rule.into()); @@ -122,7 +149,7 @@ impl Frame { self.fill_tessellator.tessellate_path( path.raw(), &options, - &mut buffers, + &mut buffer, ) } else { let path = path.transformed(&self.transforms.current.raw); @@ -130,13 +157,10 @@ impl Frame { self.fill_tessellator.tessellate_path( path.raw(), &options, - &mut buffers, + &mut buffer, ) } .expect("Tessellate path."); - - self.buffers - .push((buf, style.as_mesh_style(&self.transforms.current))); } /// Draws an axis-aligned rectangle given its top-left corner coordinate and @@ -149,10 +173,9 @@ impl Frame { ) { let Fill { style, rule } = fill.into(); - let mut buf = tessellation::VertexBuffers::new(); - - let mut buffers = - tessellation::BuffersBuilder::new(&mut buf, Vertex2DBuilder); + let mut buffer = self + .buffers + .get(style.as_mesh_style(&self.transforms.current)); let top_left = self.transforms.current.raw.transform_point( @@ -171,12 +194,9 @@ impl Frame { .tessellate_rectangle( &lyon::math::Box2D::new(top_left, top_left + size), &options, - &mut buffers, + &mut buffer, ) .expect("Fill rectangle"); - - self.buffers - .push((buf, style.as_mesh_style(&self.transforms.current))); } /// Draws the stroke of the given [`Path`] on the [`Frame`] with the @@ -184,10 +204,9 @@ impl Frame { pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) { let stroke = stroke.into(); - let mut buf = tessellation::VertexBuffers::new(); - - let mut buffers = - tessellation::BuffersBuilder::new(&mut buf, Vertex2DBuilder); + let mut buffer = self + .buffers + .get(stroke.style.as_mesh_style(&self.transforms.current)); let mut options = tessellation::StrokeOptions::default(); options.line_width = stroke.width; @@ -205,7 +224,7 @@ impl Frame { self.stroke_tessellator.tessellate_path( path.raw(), &options, - &mut buffers, + &mut buffer, ) } else { let path = path.transformed(&self.transforms.current.raw); @@ -213,13 +232,10 @@ impl Frame { self.stroke_tessellator.tessellate_path( path.raw(), &options, - &mut buffers, + &mut buffer, ) } .expect("Stroke path"); - - self.buffers - .push((buf, stroke.style.as_mesh_style(&self.transforms.current))) } /// Draws the characters of the given [`Text`] on the [`Frame`], filling @@ -361,7 +377,7 @@ impl Frame { } fn into_primitives(mut self) -> Vec<Primitive> { - for (buffer, style) in self.buffers { + for (buffer, style) in self.buffers.stack { if !buffer.indices.is_empty() { self.primitives.push(Primitive::Mesh2D { buffers: triangle::Mesh2D { diff --git a/wgpu/src/triangle/solid.rs b/wgpu/src/triangle/solid.rs index 4000b059..0373ebee 100644 --- a/wgpu/src/triangle/solid.rs +++ b/wgpu/src/triangle/solid.rs @@ -54,11 +54,8 @@ impl Pipeline { }], }); - let bind_group = Pipeline::bind_group( - device, - &buffer.raw(), - &bind_group_layout, - ); + let bind_group = + Pipeline::bind_group(device, &buffer.raw(), &bind_group_layout); let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { |