diff options
author | 2022-11-03 04:33:54 +0100 | |
---|---|---|
committer | 2022-11-03 04:33:54 +0100 | |
commit | 20a0577034b40a6bbabee9bbbfc085f3fd5016c0 (patch) | |
tree | ff23320c3955226685cd4da64a2a4c7830cdb932 /graphics | |
parent | d53e2624255680448282fb6f767c7eb732a74a9f (diff) | |
download | iced-20a0577034b40a6bbabee9bbbfc085f3fd5016c0.tar.gz iced-20a0577034b40a6bbabee9bbbfc085f3fd5016c0.tar.bz2 iced-20a0577034b40a6bbabee9bbbfc085f3fd5016c0.zip |
Reuse last buffer in `Frame` if `mesh_style` matches
Diffstat (limited to 'graphics')
-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 |
3 files changed, 51 insertions, 37 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 { |