Group all solid triangles independently of color
This commit is contained in:
parent
5b0dfcd0b0
commit
33c3c0c0aa
23 changed files with 1343 additions and 1084 deletions
|
|
@ -166,10 +166,27 @@ impl<'a> Layer<'a> {
|
|||
border_color: border_color.into_linear(),
|
||||
});
|
||||
}
|
||||
Primitive::Mesh2D {
|
||||
Primitive::SolidMesh { buffers, size } => {
|
||||
let layer = &mut layers[current_layer];
|
||||
|
||||
let bounds = Rectangle::new(
|
||||
Point::new(translation.x, translation.y),
|
||||
*size,
|
||||
);
|
||||
|
||||
// Only draw visible content
|
||||
if let Some(clip_bounds) = layer.bounds.intersection(&bounds) {
|
||||
layer.meshes.push(Mesh::Solid {
|
||||
origin: Point::new(translation.x, translation.y),
|
||||
buffers,
|
||||
clip_bounds,
|
||||
});
|
||||
}
|
||||
}
|
||||
Primitive::GradientMesh {
|
||||
buffers,
|
||||
size,
|
||||
style,
|
||||
gradient,
|
||||
} => {
|
||||
let layer = &mut layers[current_layer];
|
||||
|
||||
|
|
@ -180,11 +197,11 @@ impl<'a> Layer<'a> {
|
|||
|
||||
// Only draw visible content
|
||||
if let Some(clip_bounds) = layer.bounds.intersection(&bounds) {
|
||||
layer.meshes.push(Mesh {
|
||||
layer.meshes.push(Mesh::Gradient {
|
||||
origin: Point::new(translation.x, translation.y),
|
||||
buffers,
|
||||
clip_bounds,
|
||||
style,
|
||||
gradient,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,93 @@
|
|||
//! A collection of triangle primitives.
|
||||
use crate::triangle;
|
||||
use crate::{Point, Rectangle};
|
||||
use crate::{Gradient, Point, Rectangle};
|
||||
|
||||
/// A mesh of triangles.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Mesh<'a> {
|
||||
/// The origin of the vertices of the [`Mesh`].
|
||||
pub origin: Point,
|
||||
pub enum Mesh<'a> {
|
||||
/// A mesh of triangles with a solid color.
|
||||
Solid {
|
||||
/// The origin of the vertices of the [`Mesh`].
|
||||
origin: Point,
|
||||
|
||||
/// The vertex and index buffers of the [`Mesh`].
|
||||
pub buffers: &'a triangle::Mesh2D,
|
||||
/// The vertex and index buffers of the [`Mesh`].
|
||||
buffers: &'a triangle::Mesh2D<triangle::ColoredVertex2D>,
|
||||
|
||||
/// The clipping bounds of the [`Mesh`].
|
||||
pub clip_bounds: Rectangle<f32>,
|
||||
/// The clipping bounds of the [`Mesh`].
|
||||
clip_bounds: Rectangle<f32>,
|
||||
},
|
||||
/// A mesh of triangles with a gradient color.
|
||||
Gradient {
|
||||
/// The origin of the vertices of the [`Mesh`].
|
||||
origin: Point,
|
||||
|
||||
/// The shader of the [`Mesh`].
|
||||
pub style: &'a triangle::Style,
|
||||
/// The vertex and index buffers of the [`Mesh`].
|
||||
buffers: &'a triangle::Mesh2D<triangle::Vertex2D>,
|
||||
|
||||
/// The clipping bounds of the [`Mesh`].
|
||||
clip_bounds: Rectangle<f32>,
|
||||
|
||||
/// The gradient to apply to the [`Mesh`].
|
||||
gradient: &'a Gradient,
|
||||
},
|
||||
}
|
||||
|
||||
impl Mesh<'_> {
|
||||
/// Returns the origin of the [`Mesh`].
|
||||
pub fn origin(&self) -> Point {
|
||||
match self {
|
||||
Self::Solid { origin, .. } | Self::Gradient { origin, .. } => {
|
||||
*origin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the indices of the [`Mesh`].
|
||||
pub fn indices(&self) -> &[u32] {
|
||||
match self {
|
||||
Self::Solid { buffers, .. } => &buffers.indices,
|
||||
Self::Gradient { buffers, .. } => &buffers.indices,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the clip bounds of the [`Mesh`].
|
||||
pub fn clip_bounds(&self) -> Rectangle<f32> {
|
||||
match self {
|
||||
Self::Solid { clip_bounds, .. }
|
||||
| Self::Gradient { clip_bounds, .. } => *clip_bounds,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The result of counting the attributes of a set of meshes.
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct AttributeCount {
|
||||
/// The total amount of solid vertices.
|
||||
pub solid_vertices: usize,
|
||||
|
||||
/// The total amount of gradient vertices.
|
||||
pub gradient_vertices: usize,
|
||||
|
||||
/// The total amount of indices.
|
||||
pub indices: usize,
|
||||
}
|
||||
|
||||
/// Returns the number of total vertices & total indices of all [`Mesh`]es.
|
||||
pub fn attribute_count_of<'a>(meshes: &'a [Mesh<'a>]) -> (usize, usize) {
|
||||
pub fn attribute_count_of<'a>(meshes: &'a [Mesh<'a>]) -> AttributeCount {
|
||||
meshes
|
||||
.iter()
|
||||
.map(|Mesh { buffers, .. }| {
|
||||
(buffers.vertices.len(), buffers.indices.len())
|
||||
})
|
||||
.fold((0, 0), |(total_v, total_i), (v, i)| {
|
||||
(total_v + v, total_i + i)
|
||||
.fold(AttributeCount::default(), |mut count, mesh| {
|
||||
match mesh {
|
||||
Mesh::Solid { buffers, .. } => {
|
||||
count.solid_vertices += buffers.vertices.len();
|
||||
count.indices += buffers.indices.len();
|
||||
}
|
||||
Mesh::Gradient { buffers, .. } => {
|
||||
count.gradient_vertices += buffers.vertices.len();
|
||||
count.indices += buffers.indices.len();
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use iced_native::svg;
|
|||
use iced_native::{Background, Color, Font, Rectangle, Size, Vector};
|
||||
|
||||
use crate::alignment;
|
||||
use crate::gradient::Gradient;
|
||||
use crate::triangle;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
|
@ -77,20 +78,32 @@ pub enum Primitive {
|
|||
/// The primitive to translate
|
||||
content: Box<Primitive>,
|
||||
},
|
||||
/// A low-level primitive to render a mesh of triangles.
|
||||
/// A low-level primitive to render a mesh of triangles with a solid color.
|
||||
///
|
||||
/// It can be used to render many kinds of geometry freely.
|
||||
Mesh2D {
|
||||
/// The vertex and index buffers of the mesh
|
||||
buffers: triangle::Mesh2D,
|
||||
SolidMesh {
|
||||
/// The vertices and indices of the mesh.
|
||||
buffers: triangle::Mesh2D<triangle::ColoredVertex2D>,
|
||||
|
||||
/// The size of the drawable region of the mesh.
|
||||
///
|
||||
/// Any geometry that falls out of this region will be clipped.
|
||||
size: Size,
|
||||
},
|
||||
/// A low-level primitive to render a mesh of triangles with a gradient.
|
||||
///
|
||||
/// It can be used to render many kinds of geometry freely.
|
||||
GradientMesh {
|
||||
/// The vertices and indices of the mesh.
|
||||
buffers: triangle::Mesh2D<triangle::Vertex2D>,
|
||||
|
||||
/// The size of the drawable region of the mesh.
|
||||
///
|
||||
/// Any geometry that falls out of this region will be clipped.
|
||||
size: Size,
|
||||
|
||||
/// The shader of the mesh
|
||||
style: triangle::Style,
|
||||
/// The [`Gradient`] to apply to the mesh.
|
||||
gradient: Gradient,
|
||||
},
|
||||
/// A cached primitive.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
//! Draw geometry using meshes of triangles.
|
||||
use crate::Color;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use crate::Gradient;
|
||||
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
|
||||
/// A set of [`Vertex2D`] and indices representing a list of triangles.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Mesh2D {
|
||||
pub struct Mesh2D<T> {
|
||||
/// The vertices of the mesh
|
||||
pub vertices: Vec<Vertex2D>,
|
||||
pub vertices: Vec<T>,
|
||||
|
||||
/// The list of vertex indices that defines the triangles of the mesh.
|
||||
///
|
||||
/// Therefore, this list should always have a length that is a multiple of 3.
|
||||
|
|
@ -24,25 +21,13 @@ pub struct Vertex2D {
|
|||
pub position: [f32; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
/// Supported shaders for triangle primitives.
|
||||
pub enum Style {
|
||||
/// Fill a primitive with a solid color.
|
||||
Solid(Color),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
/// Fill a primitive with an interpolated color.
|
||||
Gradient(Gradient),
|
||||
}
|
||||
/// A two-dimensional vertex with a color.
|
||||
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
|
||||
#[repr(C)]
|
||||
pub struct ColoredVertex2D {
|
||||
/// The vertex position in 2D space.
|
||||
pub position: [f32; 2],
|
||||
|
||||
impl From<Color> for Style {
|
||||
fn from(color: Color) -> Self {
|
||||
Self::Solid(color)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl From<Gradient> for Style {
|
||||
fn from(gradient: Gradient) -> Self {
|
||||
Self::Gradient(gradient)
|
||||
}
|
||||
/// The color of the vertex in __linear__ RGBA.
|
||||
pub color: [f32; 4],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
tessellation::BuffersBuilder::new(
|
||||
&mut self.stack.last_mut().unwrap().0,
|
||||
Vertex2DBuilder,
|
||||
)
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
Vertex2D {
|
||||
triangle::Vertex2D {
|
||||
position: [position.x, position.y],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl tessellation::StrokeVertexConstructor<Vertex2D> for Vertex2DBuilder {
|
||||
impl tessellation::StrokeVertexConstructor<triangle::Vertex2D>
|
||||
for Vertex2DBuilder
|
||||
{
|
||||
fn new_vertex(
|
||||
&mut self,
|
||||
vertex: tessellation::StrokeVertex<'_, '_>,
|
||||
) -> Vertex2D {
|
||||
) -> triangle::Vertex2D {
|
||||
let position = vertex.position();
|
||||
|
||||
Vertex2D {
|
||||
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();
|
||||
|
||||
triangle::ColoredVertex2D {
|
||||
position: [position.x, position.y],
|
||||
color: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl tessellation::StrokeVertexConstructor<triangle::ColoredVertex2D>
|
||||
for TriangleVertex2DBuilder
|
||||
{
|
||||
fn new_vertex(
|
||||
&mut self,
|
||||
vertex: tessellation::StrokeVertex<'_, '_>,
|
||||
) -> triangle::ColoredVertex2D {
|
||||
let position = vertex.position();
|
||||
|
||||
triangle::ColoredVertex2D {
|
||||
position: [position.x, position.y],
|
||||
color: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
11
graphics/src/widget/canvas/style.rs
Normal file
11
graphics/src/widget/canvas/style.rs
Normal file
|
|
@ -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),
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue