diff options
Diffstat (limited to 'graphics/src/widget')
-rw-r--r-- | graphics/src/widget/canvas.rs | 2 | ||||
-rw-r--r-- | graphics/src/widget/canvas/fill.rs | 2 | ||||
-rw-r--r-- | graphics/src/widget/canvas/frame.rs | 196 | ||||
-rw-r--r-- | graphics/src/widget/canvas/stroke.rs | 2 | ||||
-rw-r--r-- | graphics/src/widget/canvas/style.rs | 11 |
5 files changed, 165 insertions, 48 deletions
diff --git a/graphics/src/widget/canvas.rs b/graphics/src/widget/canvas.rs index a14940d9..b070d0a6 100644 --- a/graphics/src/widget/canvas.rs +++ b/graphics/src/widget/canvas.rs @@ -13,6 +13,7 @@ mod cursor; mod frame; mod geometry; mod program; +mod style; mod text; pub use crate::gradient::{self, Gradient}; @@ -25,6 +26,7 @@ pub use geometry::Geometry; pub use path::Path; pub use program::Program; pub use stroke::{LineCap, LineDash, LineJoin, Stroke}; +pub use style::Style; pub use text::Text; use crate::{Backend, Primitive, Renderer}; diff --git a/graphics/src/widget/canvas/fill.rs b/graphics/src/widget/canvas/fill.rs index e2fc1cfe..e954ebb5 100644 --- a/graphics/src/widget/canvas/fill.rs +++ b/graphics/src/widget/canvas/fill.rs @@ -1,7 +1,7 @@ //! Fill [crate::widget::canvas::Geometry] with a certain style. use crate::{Color, Gradient}; -pub use crate::triangle::Style; +pub use crate::widget::canvas::Style; /// The style used to fill geometry. #[derive(Debug, Clone)] diff --git a/graphics/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs index a7b88502..d68548ae 100644 --- a/graphics/src/widget/canvas/frame.rs +++ b/graphics/src/widget/canvas/frame.rs @@ -1,7 +1,6 @@ use crate::gradient::Gradient; use crate::triangle; -use crate::triangle::Vertex2D; -use crate::widget::canvas::{path, Fill, Geometry, Path, Stroke, Text}; +use crate::widget::canvas::{path, Fill, Geometry, Path, Stroke, Style, Text}; use crate::Primitive; use iced_native::{Point, Rectangle, Size, Vector}; @@ -23,8 +22,16 @@ pub struct Frame { stroke_tessellator: tessellation::StrokeTessellator, } +enum Buffer { + Solid(tessellation::VertexBuffers<triangle::ColoredVertex2D, u32>), + Gradient( + tessellation::VertexBuffers<triangle::Vertex2D, u32>, + Gradient, + ), +} + struct BufferStack { - stack: Vec<(tessellation::VertexBuffers<Vertex2D, u32>, triangle::Style)>, + stack: Vec<Buffer>, } impl BufferStack { @@ -32,22 +39,64 @@ impl BufferStack { Self { stack: Vec::new() } } - fn get( - &mut self, - mesh_style: triangle::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)); + fn get_mut(&mut self, style: &Style) -> &mut Buffer { + match style { + Style::Solid(_) => match self.stack.last() { + Some(Buffer::Solid(_)) => {} + _ => { + self.stack.push(Buffer::Solid( + tessellation::VertexBuffers::new(), + )); + } + }, + Style::Gradient(gradient) => match self.stack.last() { + Some(Buffer::Gradient(_, last)) if gradient == last => {} + _ => { + self.stack.push(Buffer::Gradient( + tessellation::VertexBuffers::new(), + gradient.clone(), + )); + } + }, + } + + self.stack.last_mut().unwrap() + } + + fn get_fill<'a>( + &'a mut self, + style: &Style, + ) -> Box<dyn tessellation::FillGeometryBuilder + 'a> { + match (style, self.get_mut(style)) { + (Style::Solid(color), Buffer::Solid(buffer)) => { + Box::new(tessellation::BuffersBuilder::new( + buffer, + TriangleVertex2DBuilder(color.into_linear()), + )) } - }; + (Style::Gradient(_), Buffer::Gradient(buffer, _)) => Box::new( + tessellation::BuffersBuilder::new(buffer, Vertex2DBuilder), + ), + _ => unreachable!(), + } + } - tessellation::BuffersBuilder::new( - &mut self.stack.last_mut().unwrap().0, - Vertex2DBuilder, - ) + fn get_stroke<'a>( + &'a mut self, + style: &Style, + ) -> Box<dyn tessellation::StrokeGeometryBuilder + 'a> { + match (style, self.get_mut(style)) { + (Style::Solid(color), Buffer::Solid(buffer)) => { + Box::new(tessellation::BuffersBuilder::new( + buffer, + TriangleVertex2DBuilder(color.into_linear()), + )) + } + (Style::Gradient(_), Buffer::Gradient(buffer, _)) => Box::new( + tessellation::BuffersBuilder::new(buffer, Vertex2DBuilder), + ), + _ => unreachable!(), + } } } @@ -73,12 +122,11 @@ impl Transform { point.y = transformed.y; } - fn transform_style(&self, style: triangle::Style) -> triangle::Style { + fn transform_style(&self, style: Style) -> Style { match style { - triangle::Style::Solid(color) => triangle::Style::Solid(color), - #[cfg(not(target_arch = "wasm32"))] - triangle::Style::Gradient(gradient) => { - triangle::Style::Gradient(self.transform_gradient(gradient)) + Style::Solid(color) => Style::Solid(color), + Style::Gradient(gradient) => { + Style::Gradient(self.transform_gradient(gradient)) } } } @@ -146,7 +194,7 @@ impl Frame { let mut buffer = self .buffers - .get(self.transforms.current.transform_style(style)); + .get_fill(&self.transforms.current.transform_style(style)); let options = tessellation::FillOptions::default().with_fill_rule(rule.into()); @@ -155,7 +203,7 @@ impl Frame { self.fill_tessellator.tessellate_path( path.raw(), &options, - &mut buffer, + buffer.as_mut(), ) } else { let path = path.transformed(&self.transforms.current.raw); @@ -163,7 +211,7 @@ impl Frame { self.fill_tessellator.tessellate_path( path.raw(), &options, - &mut buffer, + buffer.as_mut(), ) } .expect("Tessellate path."); @@ -181,7 +229,7 @@ impl Frame { let mut buffer = self .buffers - .get(self.transforms.current.transform_style(style)); + .get_fill(&self.transforms.current.transform_style(style)); let top_left = self.transforms.current.raw.transform_point( @@ -200,7 +248,7 @@ impl Frame { .tessellate_rectangle( &lyon::math::Box2D::new(top_left, top_left + size), &options, - &mut buffer, + buffer.as_mut(), ) .expect("Fill rectangle"); } @@ -212,7 +260,7 @@ impl Frame { let mut buffer = self .buffers - .get(self.transforms.current.transform_style(stroke.style)); + .get_stroke(&self.transforms.current.transform_style(stroke.style)); let mut options = tessellation::StrokeOptions::default(); options.line_width = stroke.width; @@ -230,7 +278,7 @@ impl Frame { self.stroke_tessellator.tessellate_path( path.raw(), &options, - &mut buffer, + buffer.as_mut(), ) } else { let path = path.transformed(&self.transforms.current.raw); @@ -238,7 +286,7 @@ impl Frame { self.stroke_tessellator.tessellate_path( path.raw(), &options, - &mut buffer, + buffer.as_mut(), ) } .expect("Stroke path"); @@ -383,16 +431,31 @@ impl Frame { } fn into_primitives(mut self) -> Vec<Primitive> { - for (buffer, style) in self.buffers.stack { - if !buffer.indices.is_empty() { - self.primitives.push(Primitive::Mesh2D { - buffers: triangle::Mesh2D { - vertices: buffer.vertices, - indices: buffer.indices, - }, - size: self.size, - style, - }) + for buffer in self.buffers.stack { + match buffer { + Buffer::Solid(buffer) => { + if !buffer.indices.is_empty() { + self.primitives.push(Primitive::SolidMesh { + buffers: triangle::Mesh2D { + vertices: buffer.vertices, + indices: buffer.indices, + }, + size: self.size, + }) + } + } + Buffer::Gradient(buffer, gradient) => { + if !buffer.indices.is_empty() { + self.primitives.push(Primitive::GradientMesh { + buffers: triangle::Mesh2D { + vertices: buffer.vertices, + indices: buffer.indices, + }, + size: self.size, + gradient, + }) + } + } } } @@ -402,25 +465,66 @@ impl Frame { struct Vertex2DBuilder; -impl tessellation::FillVertexConstructor<Vertex2D> for Vertex2DBuilder { - fn new_vertex(&mut self, vertex: tessellation::FillVertex<'_>) -> Vertex2D { +impl tessellation::FillVertexConstructor<triangle::Vertex2D> + for Vertex2DBuilder +{ + fn new_vertex( + &mut self, + vertex: tessellation::FillVertex<'_>, + ) -> triangle::Vertex2D { + let position = vertex.position(); + + triangle::Vertex2D { + position: [position.x, position.y], + } + } +} + +impl tessellation::StrokeVertexConstructor<triangle::Vertex2D> + for Vertex2DBuilder +{ + fn new_vertex( + &mut self, + vertex: tessellation::StrokeVertex<'_, '_>, + ) -> triangle::Vertex2D { + let position = vertex.position(); + + triangle::Vertex2D { + position: [position.x, position.y], + } + } +} + +struct TriangleVertex2DBuilder([f32; 4]); + +impl tessellation::FillVertexConstructor<triangle::ColoredVertex2D> + for TriangleVertex2DBuilder +{ + fn new_vertex( + &mut self, + vertex: tessellation::FillVertex<'_>, + ) -> triangle::ColoredVertex2D { let position = vertex.position(); - Vertex2D { + triangle::ColoredVertex2D { position: [position.x, position.y], + color: self.0, } } } -impl tessellation::StrokeVertexConstructor<Vertex2D> for Vertex2DBuilder { +impl tessellation::StrokeVertexConstructor<triangle::ColoredVertex2D> + for TriangleVertex2DBuilder +{ fn new_vertex( &mut self, vertex: tessellation::StrokeVertex<'_, '_>, - ) -> Vertex2D { + ) -> triangle::ColoredVertex2D { let position = vertex.position(); - Vertex2D { + triangle::ColoredVertex2D { position: [position.x, position.y], + color: self.0, } } } diff --git a/graphics/src/widget/canvas/stroke.rs b/graphics/src/widget/canvas/stroke.rs index a882531a..4c19251d 100644 --- a/graphics/src/widget/canvas/stroke.rs +++ b/graphics/src/widget/canvas/stroke.rs @@ -1,5 +1,5 @@ //! Create lines from a [crate::widget::canvas::Path] and assigns them various attributes/styles. -pub use crate::triangle::Style; +pub use crate::widget::canvas::Style; use iced_native::Color; diff --git a/graphics/src/widget/canvas/style.rs b/graphics/src/widget/canvas/style.rs new file mode 100644 index 00000000..794109bd --- /dev/null +++ b/graphics/src/widget/canvas/style.rs @@ -0,0 +1,11 @@ +use crate::{Color, Gradient}; + +/// The coloring style of some drawing. +#[derive(Debug, Clone, PartialEq)] +pub enum Style { + /// A solid [`Color`]. + Solid(Color), + + /// A [`Gradient`] color. + Gradient(Gradient), +} |