From 5fd5d1cdf8e5354788dc40729c4565ef377d3bba Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector0193@gmail.com>
Date: Wed, 1 Mar 2023 21:34:26 +0100
Subject: Implement `Canvas` support for `iced_tiny_skia`

---
 graphics/src/primitive.rs | 128 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 94 insertions(+), 34 deletions(-)

(limited to 'graphics/src/primitive.rs')

diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs
index 5a163a2f..e4826591 100644
--- a/graphics/src/primitive.rs
+++ b/graphics/src/primitive.rs
@@ -1,23 +1,15 @@
+use crate::alignment;
+
 use iced_native::image;
 use iced_native::svg;
-use iced_native::{Background, Color, Font, Rectangle, Size, Vector};
-
-use crate::alignment;
-use crate::gradient::Gradient;
-use crate::triangle;
+use iced_native::{Background, Color, Font, Gradient, Rectangle, Size, Vector};
 
+use bytemuck::{Pod, Zeroable};
 use std::sync::Arc;
 
 /// A rendering primitive.
 #[derive(Debug, Clone)]
 pub enum Primitive {
-    /// An empty primitive
-    None,
-    /// A group of primitives
-    Group {
-        /// The primitives of the group
-        primitives: Vec<Primitive>,
-    },
     /// A text primitive
     Text {
         /// The contents of the text
@@ -66,27 +58,12 @@ pub enum Primitive {
         /// The bounds of the viewport
         bounds: Rectangle,
     },
-    /// A clip primitive
-    Clip {
-        /// The bounds of the clip
-        bounds: Rectangle,
-        /// The content of the clip
-        content: Box<Primitive>,
-    },
-    /// A primitive that applies a translation
-    Translate {
-        /// The translation vector
-        translation: Vector,
-
-        /// The primitive to translate
-        content: Box<Primitive>,
-    },
     /// 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.
     SolidMesh {
         /// The vertices and indices of the mesh.
-        buffers: triangle::Mesh2D<triangle::ColoredVertex2D>,
+        buffers: Mesh2D<ColoredVertex2D>,
 
         /// The size of the drawable region of the mesh.
         ///
@@ -98,7 +75,7 @@ pub enum Primitive {
     /// It can be used to render many kinds of geometry freely.
     GradientMesh {
         /// The vertices and indices of the mesh.
-        buffers: triangle::Mesh2D<triangle::Vertex2D>,
+        buffers: Mesh2D<Vertex2D>,
 
         /// The size of the drawable region of the mesh.
         ///
@@ -108,18 +85,101 @@ pub enum Primitive {
         /// The [`Gradient`] to apply to the mesh.
         gradient: Gradient,
     },
+    Fill {
+        path: tiny_skia::Path,
+        paint: tiny_skia::Paint<'static>,
+        rule: tiny_skia::FillRule,
+        transform: tiny_skia::Transform,
+    },
+    Stroke {
+        path: tiny_skia::Path,
+        paint: tiny_skia::Paint<'static>,
+        stroke: tiny_skia::Stroke,
+        transform: tiny_skia::Transform,
+    },
+    /// A group of primitives
+    Group {
+        /// The primitives of the group
+        primitives: Vec<Primitive>,
+    },
+    /// A clip primitive
+    Clip {
+        /// The bounds of the clip
+        bounds: Rectangle,
+        /// The content of the clip
+        content: Box<Primitive>,
+    },
+    /// A primitive that applies a translation
+    Translate {
+        /// The translation vector
+        translation: Vector,
+
+        /// The primitive to translate
+        content: Box<Primitive>,
+    },
     /// A cached primitive.
     ///
     /// This can be useful if you are implementing a widget where primitive
     /// generation is expensive.
-    Cached {
+    Cache {
         /// The cached primitive
-        cache: Arc<Primitive>,
+        content: Arc<Primitive>,
     },
 }
 
-impl Default for Primitive {
-    fn default() -> Primitive {
-        Primitive::None
+impl Primitive {
+    pub fn group(primitives: Vec<Self>) -> Self {
+        Self::Group { primitives }
+    }
+
+    pub fn clip(self, bounds: Rectangle) -> Self {
+        Self::Clip {
+            bounds,
+            content: Box::new(self),
+        }
+    }
+
+    pub fn translate(self, translation: Vector) -> Self {
+        Self::Translate {
+            translation,
+            content: Box::new(self),
+        }
+    }
+}
+
+/// A set of [`Vertex2D`] and indices representing a list of triangles.
+#[derive(Clone, Debug)]
+pub struct Mesh2D<T> {
+    /// The vertices of the mesh
+    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.
+    pub indices: Vec<u32>,
+}
+
+/// A two-dimensional vertex.
+#[derive(Copy, Clone, Debug, Zeroable, Pod)]
+#[repr(C)]
+pub struct Vertex2D {
+    /// The vertex position in 2D space.
+    pub position: [f32; 2],
+}
+
+/// 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],
+
+    /// The color of the vertex in __linear__ RGBA.
+    pub color: [f32; 4],
+}
+
+impl From<()> for Primitive {
+    fn from(_: ()) -> Self {
+        Self::Group { primitives: vec![] }
     }
 }
-- 
cgit