summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--graphics/src/layer/mesh.rs8
-rw-r--r--graphics/src/widget/canvas/fill.rs6
-rw-r--r--graphics/src/widget/canvas/frame.rs74
-rw-r--r--wgpu/src/triangle/solid.rs7
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 {