summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-06-22 00:38:36 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2023-06-29 07:18:20 +0200
commit0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2 (patch)
tree7f3d09dca8ea9fae96457d3f9266e014d1d25d80
parent8d65e40a1174ecb8225ce9973575bced36e7aeb5 (diff)
downloadiced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.tar.gz
iced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.tar.bz2
iced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.zip
Introduce custom backend-specific primitives
-rw-r--r--examples/geometry/Cargo.toml1
-rw-r--r--examples/geometry/src/main.rs7
-rw-r--r--examples/loading_spinners/src/circular.rs4
-rw-r--r--graphics/Cargo.toml4
-rw-r--r--graphics/src/backend.rs7
-rw-r--r--graphics/src/damage.rs68
-rw-r--r--graphics/src/geometry.rs16
-rw-r--r--graphics/src/lib.rs9
-rw-r--r--graphics/src/primitive.rs107
-rw-r--r--graphics/src/renderer.rs70
-rw-r--r--renderer/src/compositor.rs80
-rw-r--r--renderer/src/geometry.rs24
-rw-r--r--renderer/src/geometry/cache.rs52
-rw-r--r--renderer/src/lib.rs248
-rw-r--r--tiny_skia/Cargo.toml1
-rw-r--r--tiny_skia/src/backend.rs36
-rw-r--r--tiny_skia/src/geometry.rs47
-rw-r--r--tiny_skia/src/lib.rs2
-rw-r--r--tiny_skia/src/primitive.rs48
-rw-r--r--tiny_skia/src/window/compositor.rs4
-rw-r--r--wgpu/src/backend.rs7
-rw-r--r--wgpu/src/geometry.rs6
-rw-r--r--wgpu/src/layer.rs11
-rw-r--r--wgpu/src/lib.rs6
-rw-r--r--wgpu/src/primitive.rs3
-rw-r--r--wgpu/src/window/compositor.rs4
-rw-r--r--widget/src/canvas/program.rs6
-rw-r--r--widget/src/qr_code.rs3
28 files changed, 618 insertions, 263 deletions
diff --git a/examples/geometry/Cargo.toml b/examples/geometry/Cargo.toml
index 79fe52d5..6068d651 100644
--- a/examples/geometry/Cargo.toml
+++ b/examples/geometry/Cargo.toml
@@ -7,4 +7,3 @@ publish = false
[dependencies]
iced = { path = "../..", features = ["advanced"] }
-iced_graphics = { path = "../../graphics" }
diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs
index 29f78ea1..e146c6bd 100644
--- a/examples/geometry/src/main.rs
+++ b/examples/geometry/src/main.rs
@@ -1,9 +1,8 @@
//! This example showcases a simple native custom widget that renders using
//! arbitrary low-level geometry.
mod rainbow {
- use iced_graphics::primitive::{ColoredVertex2D, Primitive};
-
use iced::advanced::graphics::color;
+ use iced::advanced::graphics::primitive::{ColoredVertex2D, Primitive};
use iced::advanced::layout::{self, Layout};
use iced::advanced::renderer;
use iced::advanced::widget::{self, Widget};
@@ -46,8 +45,8 @@ mod rainbow {
cursor: mouse::Cursor,
_viewport: &Rectangle,
) {
+ use iced::advanced::graphics::primitive::Mesh2D;
use iced::advanced::Renderer as _;
- use iced_graphics::primitive::Mesh2D;
let bounds = layout.bounds();
@@ -135,7 +134,7 @@ mod rainbow {
renderer.with_translation(
Vector::new(bounds.x, bounds.y),
|renderer| {
- renderer.draw_primitive(mesh);
+ renderer.draw_with_wgpu(mesh);
},
);
}
diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs
index 4cef081e..3a35e029 100644
--- a/examples/loading_spinners/src/circular.rs
+++ b/examples/loading_spinners/src/circular.rs
@@ -358,7 +358,9 @@ where
renderer.with_translation(
Vector::new(bounds.x, bounds.y),
|renderer| {
- renderer.draw_primitive(geometry.0);
+ use iced::advanced::graphics::geometry::Renderer as _;
+
+ renderer.draw(vec![geometry]);
},
);
}
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
index 02621695..7a9e6aee 100644
--- a/graphics/Cargo.toml
+++ b/graphics/Cargo.toml
@@ -32,10 +32,6 @@ features = ["derive"]
version = "0.9"
path = "../core"
-[dependencies.tiny-skia]
-version = "0.9"
-optional = true
-
[dependencies.image]
version = "0.24"
optional = true
diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs
index 70ccc664..3ff24335 100644
--- a/graphics/src/backend.rs
+++ b/graphics/src/backend.rs
@@ -6,6 +6,13 @@ use iced_core::{Font, Point, Size};
use std::borrow::Cow;
+/// The graphics backend of a [`Renderer`].
+///
+/// [`Renderer`]: crate::Renderer
+pub trait Backend {
+ type Primitive;
+}
+
/// A graphics backend that supports text rendering.
pub trait Text {
/// The icon font of the backend.
diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs
index c6b0f759..1add6707 100644
--- a/graphics/src/damage.rs
+++ b/graphics/src/damage.rs
@@ -1,11 +1,68 @@
//! Track and compute the damage of graphical primitives.
+use crate::core::alignment;
use crate::core::{Rectangle, Size};
use crate::Primitive;
use std::sync::Arc;
-/// Computes the damage regions between the two given primitives.
-pub fn regions(a: &Primitive, b: &Primitive) -> Vec<Rectangle> {
+pub trait Damage: PartialEq {
+ /// Returns the bounds of the [`Damage`].
+ fn bounds(&self) -> Rectangle;
+}
+
+impl<T: Damage> Damage for Primitive<T> {
+ fn bounds(&self) -> Rectangle {
+ match self {
+ Self::Text {
+ bounds,
+ horizontal_alignment,
+ vertical_alignment,
+ ..
+ } => {
+ let mut bounds = *bounds;
+
+ bounds.x = match horizontal_alignment {
+ alignment::Horizontal::Left => bounds.x,
+ alignment::Horizontal::Center => {
+ bounds.x - bounds.width / 2.0
+ }
+ alignment::Horizontal::Right => bounds.x - bounds.width,
+ };
+
+ bounds.y = match vertical_alignment {
+ alignment::Vertical::Top => bounds.y,
+ alignment::Vertical::Center => {
+ bounds.y - bounds.height / 2.0
+ }
+ alignment::Vertical::Bottom => bounds.y - bounds.height,
+ };
+
+ bounds.expand(1.5)
+ }
+ Self::Quad { bounds, .. }
+ | Self::Image { bounds, .. }
+ | Self::Svg { bounds, .. } => bounds.expand(1.0),
+ Self::Clip { bounds, .. } => bounds.expand(1.0),
+ Self::SolidMesh { size, .. } | Self::GradientMesh { size, .. } => {
+ Rectangle::with_size(*size)
+ }
+ Self::Group { primitives } => primitives
+ .iter()
+ .map(Self::bounds)
+ .fold(Rectangle::with_size(Size::ZERO), |a, b| {
+ Rectangle::union(&a, &b)
+ }),
+ Self::Translate {
+ translation,
+ content,
+ } => content.bounds() + *translation,
+ Self::Cache { content } => content.bounds(),
+ Self::Custom(custom) => custom.bounds(),
+ }
+ }
+}
+
+fn regions<T: Damage>(a: &Primitive<T>, b: &Primitive<T>) -> Vec<Rectangle> {
match (a, b) {
(
Primitive::Group {
@@ -76,7 +133,10 @@ pub fn regions(a: &Primitive, b: &Primitive) -> Vec<Rectangle> {
}
/// Computes the damage regions between the two given lists of primitives.
-pub fn list(previous: &[Primitive], current: &[Primitive]) -> Vec<Rectangle> {
+pub fn list<T: Damage>(
+ previous: &[Primitive<T>],
+ current: &[Primitive<T>],
+) -> Vec<Rectangle> {
let damage = previous
.iter()
.zip(current)
@@ -93,7 +153,7 @@ pub fn list(previous: &[Primitive], current: &[Primitive]) -> Vec<Rectangle> {
// Extend damage by the added/removed primitives
damage
- .chain(bigger[smaller.len()..].iter().map(Primitive::bounds))
+ .chain(bigger[smaller.len()..].iter().map(Damage::bounds))
.collect()
}
}
diff --git a/graphics/src/geometry.rs b/graphics/src/geometry.rs
index 729c3d44..5e547bae 100644
--- a/graphics/src/geometry.rs
+++ b/graphics/src/geometry.rs
@@ -14,20 +14,10 @@ pub use text::Text;
pub use crate::gradient::{self, Gradient};
-use crate::Primitive;
-
-/// A bunch of shapes that can be drawn.
-#[derive(Debug, Clone)]
-pub struct Geometry(pub Primitive);
-
-impl From<Geometry> for Primitive {
- fn from(geometry: Geometry) -> Self {
- geometry.0
- }
-}
-
/// A renderer capable of drawing some [`Geometry`].
pub trait Renderer: crate::core::Renderer {
+ type Geometry;
+
/// Draws the given layers of [`Geometry`].
- fn draw(&mut self, layers: Vec<Geometry>);
+ fn draw(&mut self, layers: Vec<Self::Geometry>);
}
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index 226b245b..055a9216 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -8,8 +8,8 @@
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
#![deny(
- missing_debug_implementations,
- missing_docs,
+ //missing_debug_implementations,
+ //missing_docs,
unsafe_code,
unused_results,
clippy::extra_unused_lifetimes,
@@ -41,7 +41,9 @@ pub mod geometry;
pub mod image;
pub use antialiasing::Antialiasing;
+pub use backend::Backend;
pub use compositor::Compositor;
+pub use damage::Damage;
pub use error::Error;
pub use gradient::Gradient;
pub use primitive::Primitive;
@@ -49,7 +51,4 @@ pub use renderer::Renderer;
pub use transformation::Transformation;
pub use viewport::Viewport;
-#[cfg(feature = "geometry")]
-pub use geometry::Geometry;
-
pub use iced_core as core;
diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs
index 187c6c6c..f8b005ad 100644
--- a/graphics/src/primitive.rs
+++ b/graphics/src/primitive.rs
@@ -12,8 +12,7 @@ use std::sync::Arc;
/// A rendering primitive.
#[derive(Debug, Clone, PartialEq)]
-#[non_exhaustive]
-pub enum Primitive {
+pub enum Primitive<T> {
/// A text primitive
Text {
/// The contents of the text
@@ -90,41 +89,17 @@ pub enum Primitive {
/// Any geometry that falls out of this region will be clipped.
size: Size,
},
- /// A [`tiny_skia`] path filled with some paint.
- #[cfg(feature = "tiny-skia")]
- Fill {
- /// The path to fill.
- path: tiny_skia::Path,
- /// The paint to use.
- paint: tiny_skia::Paint<'static>,
- /// The fill rule to follow.
- rule: tiny_skia::FillRule,
- /// The transform to apply to the path.
- transform: tiny_skia::Transform,
- },
- /// A [`tiny_skia`] path stroked with some paint.
- #[cfg(feature = "tiny-skia")]
- Stroke {
- /// The path to stroke.
- path: tiny_skia::Path,
- /// The paint to use.
- paint: tiny_skia::Paint<'static>,
- /// The stroke settings.
- stroke: tiny_skia::Stroke,
- /// The transform to apply to the path.
- transform: tiny_skia::Transform,
- },
/// A group of primitives
Group {
/// The primitives of the group
- primitives: Vec<Primitive>,
+ primitives: Vec<Primitive<T>>,
},
/// A clip primitive
Clip {
/// The bounds of the clip
bounds: Rectangle,
/// The content of the clip
- content: Box<Primitive>,
+ content: Box<Primitive<T>>,
},
/// A primitive that applies a translation
Translate {
@@ -132,7 +107,7 @@ pub enum Primitive {
translation: Vector,
/// The primitive to translate
- content: Box<Primitive>,
+ content: Box<Primitive<T>>,
},
/// A cached primitive.
///
@@ -140,11 +115,13 @@ pub enum Primitive {
/// generation is expensive.
Cache {
/// The cached primitive
- content: Arc<Primitive>,
+ content: Arc<Primitive<T>>,
},
+ /// A backend-specific primitive.
+ Custom(T),
}
-impl Primitive {
+impl<T> Primitive<T> {
/// Creates a [`Primitive::Group`].
pub fn group(primitives: Vec<Self>) -> Self {
Self::Group { primitives }
@@ -165,68 +142,6 @@ impl Primitive {
content: Box::new(self),
}
}
-
- /// Returns the bounds of the [`Primitive`].
- pub fn bounds(&self) -> Rectangle {
- match self {
- Self::Text {
- bounds,
- horizontal_alignment,
- vertical_alignment,
- ..
- } => {
- let mut bounds = *bounds;
-
- bounds.x = match horizontal_alignment {
- alignment::Horizontal::Left => bounds.x,
- alignment::Horizontal::Center => {
- bounds.x - bounds.width / 2.0
- }
- alignment::Horizontal::Right => bounds.x - bounds.width,
- };
-
- bounds.y = match vertical_alignment {
- alignment::Vertical::Top => bounds.y,
- alignment::Vertical::Center => {
- bounds.y - bounds.height / 2.0
- }
- alignment::Vertical::Bottom => bounds.y - bounds.height,
- };
-
- bounds.expand(1.5)
- }
- Self::Quad { bounds, .. }
- | Self::Image { bounds, .. }
- | Self::Svg { bounds, .. } => bounds.expand(1.0),
- Self::Clip { bounds, .. } => bounds.expand(1.0),
- Self::SolidMesh { size, .. } | Self::GradientMesh { size, .. } => {
- Rectangle::with_size(*size)
- }
- #[cfg(feature = "tiny-skia")]
- Self::Fill { path, .. } | Self::Stroke { path, .. } => {
- let bounds = path.bounds();
-
- Rectangle {
- x: bounds.x(),
- y: bounds.y(),
- width: bounds.width(),
- height: bounds.height(),
- }
- .expand(1.0)
- }
- Self::Group { primitives } => primitives
- .iter()
- .map(Self::bounds)
- .fold(Rectangle::with_size(Size::ZERO), |a, b| {
- Rectangle::union(&a, &b)
- }),
- Self::Translate {
- translation,
- content,
- } => content.bounds() + *translation,
- Self::Cache { content } => content.bounds(),
- }
- }
}
/// A set of [`Vertex2D`] and indices representing a list of triangles.
@@ -268,9 +183,3 @@ unsafe impl Zeroable for GradientVertex2D {}
#[allow(unsafe_code)]
unsafe impl Pod for GradientVertex2D {}
-
-impl From<()> for Primitive {
- fn from(_: ()) -> Self {
- Self::Group { primitives: vec![] }
- }
-}
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs
index 7e70a766..9acfc2b7 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -1,5 +1,5 @@
//! Create a renderer from a [`Backend`].
-use crate::backend;
+use crate::backend::{self, Backend};
use crate::Primitive;
use iced_core::image;
@@ -16,13 +16,13 @@ use std::marker::PhantomData;
/// A backend-agnostic renderer that supports all the built-in widgets.
#[derive(Debug)]
-pub struct Renderer<B, Theme> {
+pub struct Renderer<B: Backend, Theme> {
backend: B,
- primitives: Vec<Primitive>,
+ primitives: Vec<Primitive<B::Primitive>>,
theme: PhantomData<Theme>,
}
-impl<B, T> Renderer<B, T> {
+impl<B: Backend, T> Renderer<B, T> {
/// Creates a new [`Renderer`] from the given [`Backend`].
pub fn new(backend: B) -> Self {
Self {
@@ -38,7 +38,7 @@ impl<B, T> Renderer<B, T> {
}
/// Enqueues the given [`Primitive`] in the [`Renderer`] for drawing.
- pub fn draw_primitive(&mut self, primitive: Primitive) {
+ pub fn draw_primitive(&mut self, primitive: Primitive<B::Primitive>) {
self.primitives.push(primitive);
}
@@ -46,13 +46,42 @@ impl<B, T> Renderer<B, T> {
/// of the [`Renderer`].
pub fn with_primitives<O>(
&mut self,
- f: impl FnOnce(&mut B, &[Primitive]) -> O,
+ f: impl FnOnce(&mut B, &[Primitive<B::Primitive>]) -> O,
) -> O {
f(&mut self.backend, &self.primitives)
}
+
+ pub fn start_layer(&mut self) -> Vec<Primitive<B::Primitive>> {
+ std::mem::take(&mut self.primitives)
+ }
+
+ pub fn end_layer(
+ &mut self,
+ primitives: Vec<Primitive<B::Primitive>>,
+ bounds: Rectangle,
+ ) {
+ let layer = std::mem::replace(&mut self.primitives, primitives);
+
+ self.primitives.push(Primitive::group(layer).clip(bounds));
+ }
+
+ pub fn start_translation(&mut self) -> Vec<Primitive<B::Primitive>> {
+ std::mem::take(&mut self.primitives)
+ }
+
+ pub fn end_translation(
+ &mut self,
+ primitives: Vec<Primitive<B::Primitive>>,
+ translation: Vector,
+ ) {
+ let layer = std::mem::replace(&mut self.primitives, primitives);
+
+ self.primitives
+ .push(Primitive::group(layer).translate(translation));
+ }
}
-impl<B, T> iced_core::Renderer for Renderer<B, T> {
+impl<B: Backend, T> iced_core::Renderer for Renderer<B, T> {
type Theme = T;
fn layout<Message>(
@@ -64,13 +93,11 @@ impl<B, T> iced_core::Renderer for Renderer<B, T> {
}
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
- let current = std::mem::take(&mut self.primitives);
+ let current = self.start_layer();
f(self);
- let layer = std::mem::replace(&mut self.primitives, current);
-
- self.primitives.push(Primitive::group(layer).clip(bounds));
+ self.end_layer(current, bounds);
}
fn with_translation(
@@ -78,14 +105,11 @@ impl<B, T> iced_core::Renderer for Renderer<B, T> {
translation: Vector,
f: impl FnOnce(&mut Self),
) {
- let current = std::mem::take(&mut self.primitives);
+ let current = self.start_translation();
f(self);
- let layer = std::mem::replace(&mut self.primitives, current);
-
- self.primitives
- .push(Primitive::group(layer).translate(translation));
+ self.end_translation(current, translation);
}
fn fill_quad(
@@ -109,7 +133,7 @@ impl<B, T> iced_core::Renderer for Renderer<B, T> {
impl<B, T> text::Renderer for Renderer<B, T>
where
- B: backend::Text,
+ B: Backend + backend::Text,
{
type Font = Font;
@@ -188,7 +212,7 @@ where
impl<B, T> image::Renderer for Renderer<B, T>
where
- B: backend::Image,
+ B: Backend + backend::Image,
{
type Handle = image::Handle;
@@ -203,7 +227,7 @@ where
impl<B, T> svg::Renderer for Renderer<B, T>
where
- B: backend::Svg,
+ B: Backend + backend::Svg,
{
fn dimensions(&self, handle: &svg::Handle) -> Size<u32> {
self.backend().viewport_dimensions(handle)
@@ -222,11 +246,3 @@ where
})
}
}
-
-#[cfg(feature = "geometry")]
-impl<B, T> crate::geometry::Renderer for Renderer<B, T> {
- fn draw(&mut self, layers: Vec<crate::Geometry>) {
- self.primitives
- .extend(layers.into_iter().map(crate::Geometry::into));
- }
-}
diff --git a/renderer/src/compositor.rs b/renderer/src/compositor.rs
index 57317b28..8b17a4b0 100644
--- a/renderer/src/compositor.rs
+++ b/renderer/src/compositor.rs
@@ -100,26 +100,28 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
background_color: Color,
overlay: &[T],
) -> Result<(), SurfaceError> {
- renderer.with_primitives(|backend, primitives| {
- match (self, backend, surface) {
- (
- Self::TinySkia(_compositor),
- crate::Backend::TinySkia(backend),
- Surface::TinySkia(surface),
- ) => iced_tiny_skia::window::compositor::present(
+ match (self, renderer, surface) {
+ (
+ Self::TinySkia(_compositor),
+ crate::Renderer::TinySkia(renderer),
+ Surface::TinySkia(surface),
+ ) => renderer.with_primitives(|backend, primitives| {
+ iced_tiny_skia::window::compositor::present(
backend,
surface,
primitives,
viewport,
background_color,
overlay,
- ),
- #[cfg(feature = "wgpu")]
- (
- Self::Wgpu(compositor),
- crate::Backend::Wgpu(backend),
- Surface::Wgpu(surface),
- ) => iced_wgpu::window::compositor::present(
+ )
+ }),
+ #[cfg(feature = "wgpu")]
+ (
+ Self::Wgpu(compositor),
+ crate::Renderer::Wgpu(renderer),
+ Surface::Wgpu(surface),
+ ) => renderer.with_primitives(|backend, primitives| {
+ iced_wgpu::window::compositor::present(
compositor,
backend,
surface,
@@ -127,14 +129,14 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
viewport,
background_color,
overlay,
- ),
- #[allow(unreachable_patterns)]
- _ => panic!(
- "The provided renderer or surface are not compatible \
+ )
+ }),
+ #[allow(unreachable_patterns)]
+ _ => panic!(
+ "The provided renderer or surface are not compatible \
with the compositor."
- ),
- }
- })
+ ),
+ }
}
fn screenshot<T: AsRef<str>>(
@@ -145,12 +147,27 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
background_color: Color,
overlay: &[T],
) -> Vec<u8> {
- renderer.with_primitives(|backend, primitives| match (self, backend, surface) {
- (Self::TinySkia(_compositor), crate::Backend::TinySkia(backend), Surface::TinySkia(surface)) => {
- iced_tiny_skia::window::compositor::screenshot(surface, backend, primitives, viewport, background_color, overlay)
- },
+ match (self, renderer, surface) {
+ (
+ Self::TinySkia(_compositor),
+ Renderer::TinySkia(renderer),
+ Surface::TinySkia(surface),
+ ) => renderer.with_primitives(|backend, primitives| {
+ iced_tiny_skia::window::compositor::screenshot(
+ surface,
+ backend,
+ primitives,
+ viewport,
+ background_color,
+ overlay,
+ )
+ }),
#[cfg(feature = "wgpu")]
- (Self::Wgpu(compositor), crate::Backend::Wgpu(backend), Surface::Wgpu(_)) => {
+ (
+ Self::Wgpu(compositor),
+ Renderer::Wgpu(renderer),
+ Surface::Wgpu(_),
+ ) => renderer.with_primitives(|backend, primitives| {
iced_wgpu::window::compositor::screenshot(
compositor,
backend,
@@ -159,12 +176,13 @@ impl<Theme> crate::graphics::Compositor for Compositor<Theme> {
background_color,
overlay,
)
- },
+ }),
#[allow(unreachable_patterns)]
_ => panic!(
- "The provided renderer or backend are not compatible with the compositor."
+ "The provided renderer or backend are not compatible \
+ with the compositor."
),
- })
+ }
}
}
@@ -215,7 +233,7 @@ impl Candidate {
Ok((
Compositor::TinySkia(compositor),
- Renderer::new(crate::Backend::TinySkia(backend)),
+ Renderer::TinySkia(iced_tiny_skia::Renderer::new(backend)),
))
}
#[cfg(feature = "wgpu")]
@@ -232,7 +250,7 @@ impl Candidate {
Ok((
Compositor::Wgpu(compositor),
- Renderer::new(crate::Backend::Wgpu(backend)),
+ Renderer::Wgpu(iced_wgpu::Renderer::new(backend)),
))
}
#[cfg(not(feature = "wgpu"))]
diff --git a/renderer/src/geometry.rs b/renderer/src/geometry.rs
index 26e2fed0..04b5d9e6 100644
--- a/renderer/src/geometry.rs
+++ b/renderer/src/geometry.rs
@@ -3,8 +3,8 @@ mod cache;
pub use cache::Cache;
use crate::core::{Point, Rectangle, Size, Vector};
-use crate::graphics::geometry::{Fill, Geometry, Path, Stroke, Text};
-use crate::Backend;
+use crate::graphics::geometry::{Fill, Path, Stroke, Text};
+use crate::Renderer;
pub enum Frame {
TinySkia(iced_tiny_skia::geometry::Frame),
@@ -12,6 +12,12 @@ pub enum Frame {
Wgpu(iced_wgpu::geometry::Frame),
}
+pub enum Geometry {
+ TinySkia(iced_tiny_skia::Primitive),
+ #[cfg(feature = "wgpu")]
+ Wgpu(iced_wgpu::Primitive),
+}
+
macro_rules! delegate {
($frame:expr, $name:ident, $body:expr) => {
match $frame {
@@ -23,13 +29,13 @@ macro_rules! delegate {
}
impl Frame {
- pub fn new<Theme>(renderer: &crate::Renderer<Theme>, size: Size) -> Self {
- match renderer.backend() {
- Backend::TinySkia(_) => {
+ pub fn new<Theme>(renderer: &Renderer<Theme>, size: Size) -> Self {
+ match renderer {
+ Renderer::TinySkia(_) => {
Frame::TinySkia(iced_tiny_skia::geometry::Frame::new(size))
}
#[cfg(feature = "wgpu")]
- Backend::Wgpu(_) => {
+ Renderer::Wgpu(_) => {
Frame::Wgpu(iced_wgpu::geometry::Frame::new(size))
}
}
@@ -169,6 +175,10 @@ impl Frame {
}
pub fn into_geometry(self) -> Geometry {
- Geometry(delegate!(self, frame, frame.into_primitive()))
+ match self {
+ Self::TinySkia(frame) => Geometry::TinySkia(frame.into_primitive()),
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(frame) => Geometry::Wgpu(frame.into_primitive()),
+ }
}
}
diff --git a/renderer/src/geometry/cache.rs b/renderer/src/geometry/cache.rs
index 2a3534d0..d82e7f69 100644
--- a/renderer/src/geometry/cache.rs
+++ b/renderer/src/geometry/cache.rs
@@ -1,6 +1,5 @@
use crate::core::Size;
use crate::geometry::{Frame, Geometry};
-use crate::graphics::Primitive;
use crate::Renderer;
use std::cell::RefCell;
@@ -21,10 +20,17 @@ enum State {
Empty,
Filled {
bounds: Size,
- primitive: Arc<Primitive>,
+ primitive: Internal,
},
}
+#[derive(Debug, Clone)]
+enum Internal {
+ TinySkia(Arc<iced_tiny_skia::Primitive>),
+ #[cfg(feature = "wgpu")]
+ Wgpu(Arc<iced_wgpu::Primitive>),
+}
+
impl Cache {
/// Creates a new empty [`Cache`].
pub fn new() -> Self {
@@ -62,9 +68,21 @@ impl Cache {
} = self.state.borrow().deref()
{
if *cached_bounds == bounds {
- return Geometry(Primitive::Cache {
- content: primitive.clone(),
- });
+ match primitive {
+ Internal::TinySkia(primitive) => {
+ return Geometry::TinySkia(
+ iced_tiny_skia::Primitive::Cache {
+ content: primitive.clone(),
+ },
+ );
+ }
+ #[cfg(feature = "wgpu")]
+ Internal::Wgpu(primitive) => {
+ return Geometry::Wgpu(iced_wgpu::Primitive::Cache {
+ content: primitive.clone(),
+ });
+ }
+ }
}
}
@@ -74,7 +92,15 @@ impl Cache {
let primitive = {
let geometry = frame.into_geometry();
- Arc::new(geometry.0)
+ match geometry {
+ Geometry::TinySkia(primitive) => {
+ Internal::TinySkia(Arc::new(primitive))
+ }
+ #[cfg(feature = "wgpu")]
+ Geometry::Wgpu(primitive) => {
+ Internal::Wgpu(Arc::new(primitive))
+ }
+ }
};
*self.state.borrow_mut() = State::Filled {
@@ -82,6 +108,18 @@ impl Cache {
primitive: primitive.clone(),
};
- Geometry(Primitive::Cache { content: primitive })
+ match primitive {
+ Internal::TinySkia(primitive) => {
+ Geometry::TinySkia(iced_tiny_skia::Primitive::Cache {
+ content: primitive,
+ })
+ }
+ #[cfg(feature = "wgpu")]
+ Internal::Wgpu(primitive) => {
+ Geometry::Wgpu(iced_wgpu::Primitive::Cache {
+ content: primitive,
+ })
+ }
+ }
}
}
diff --git a/renderer/src/lib.rs b/renderer/src/lib.rs
index 22ec7bd1..89b8f4c6 100644
--- a/renderer/src/lib.rs
+++ b/renderer/src/lib.rs
@@ -3,17 +3,259 @@ pub mod compositor;
#[cfg(feature = "geometry")]
pub mod geometry;
-mod backend;
mod settings;
pub use iced_graphics as graphics;
pub use iced_graphics::core;
-pub use backend::Backend;
pub use compositor::Compositor;
pub use settings::Settings;
+#[cfg(feature = "geometry")]
+pub use geometry::Geometry;
+
+use crate::core::renderer;
+use crate::core::text::{self, Text};
+use crate::core::{Background, Font, Point, Rectangle, Size, Vector};
+
+use std::borrow::Cow;
+
/// The default graphics renderer for [`iced`].
///
/// [`iced`]: https://github.com/iced-rs/iced
-pub type Renderer<Theme> = iced_graphics::Renderer<Backend, Theme>;
+pub enum Renderer<Theme> {
+ TinySkia(iced_tiny_skia::Renderer<Theme>),
+ #[cfg(feature = "wgpu")]
+ Wgpu(iced_wgpu::Renderer<Theme>),
+}
+
+macro_rules! delegate {
+ ($renderer:expr, $name:ident, $body:expr) => {
+ match $renderer {
+ Self::TinySkia($name) => $body,
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu($name) => $body,
+ }
+ };
+}
+
+impl<T> Renderer<T> {
+ #[cfg(feature = "wgpu")]
+ pub fn draw_with_wgpu(&mut self, primitive: iced_wgpu::Primitive) {
+ if let Self::Wgpu(renderer) = self {
+ renderer.draw_primitive(primitive);
+ }
+ }
+}
+
+impl<T> core::Renderer for Renderer<T> {
+ type Theme = T;
+
+ fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
+ match self {
+ Self::TinySkia(renderer) => {
+ let primitives = renderer.start_layer();
+
+ f(self);
+
+ match self {
+ Self::TinySkia(renderer) => {
+ renderer.end_layer(primitives, bounds);
+ }
+ #[cfg(feature = "wgpu")]
+ _ => unreachable!(),
+ }
+ }
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(renderer) => {
+ let primitives = renderer.start_layer();
+
+ f(self);
+
+ match self {
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(renderer) => {
+ renderer.end_layer(primitives, bounds);
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+
+ fn with_translation(
+ &mut self,
+ translation: Vector,
+ f: impl FnOnce(&mut Self),
+ ) {
+ match self {
+ Self::TinySkia(renderer) => {
+ let primitives = renderer.start_translation();
+
+ f(self);
+
+ match self {
+ Self::TinySkia(renderer) => {
+ renderer.end_translation(primitives, translation);
+ }
+ #[cfg(feature = "wgpu")]
+ _ => unreachable!(),
+ }
+ }
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(renderer) => {
+ let primitives = renderer.start_translation();
+
+ f(self);
+
+ match self {
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(renderer) => {
+ renderer.end_translation(primitives, translation);
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+
+ fn fill_quad(
+ &mut self,
+ quad: renderer::Quad,
+ background: impl Into<Background>,
+ ) {
+ delegate!(self, renderer, renderer.fill_quad(quad, background));
+ }
+
+ fn clear(&mut self) {
+ delegate!(self, renderer, renderer.clear());
+ }
+}
+
+impl<T> text::Renderer for Renderer<T> {
+ type Font = Font;
+
+ const ICON_FONT: Font = iced_tiny_skia::Renderer::<T>::ICON_FONT;
+ const CHECKMARK_ICON: char = iced_tiny_skia::Renderer::<T>::CHECKMARK_ICON;
+ const ARROW_DOWN_ICON: char =
+ iced_tiny_skia::Renderer::<T>::ARROW_DOWN_ICON;
+
+ fn default_font(&self) -> Self::Font {
+ delegate!(self, renderer, renderer.default_font())
+ }
+
+ fn default_size(&self) -> f32 {
+ delegate!(self, renderer, renderer.default_size())
+ }
+
+ fn measure(
+ &self,
+ content: &str,
+ size: f32,
+ line_height: text::LineHeight,
+ font: Font,
+ bounds: Size,
+ shaping: text::Shaping,
+ ) -> Size {
+ delegate!(
+ self,
+ renderer,
+ renderer.measure(content, size, line_height, font, bounds, shaping)
+ )
+ }
+
+ fn hit_test(
+ &self,
+ content: &str,
+ size: f32,
+ line_height: text::LineHeight,
+ font: Font,
+ bounds: Size,
+ shaping: text::Shaping,
+ point: Point,
+ nearest_only: bool,
+ ) -> Option<text::Hit> {
+ delegate!(
+ self,
+ renderer,
+ renderer.hit_test(
+ content,
+ size,
+ line_height,
+ font,
+ bounds,
+ shaping,
+ point,
+ nearest_only
+ )
+ )
+ }
+
+ fn load_font(&mut self, bytes: Cow<'static, [u8]>) {
+ delegate!(self, renderer, renderer.load_font(bytes));
+ }
+
+ fn fill_text(&mut self, text: Text<'_, Self::Font>) {
+ delegate!(self, renderer, renderer.fill_text(text));
+ }
+}
+
+#[cfg(feature = "image")]
+impl<T> crate::core::image::Renderer for Renderer<T> {
+ type Handle = crate::core::image::Handle;
+
+ fn dimensions(&self, handle: &crate::core::image::Handle) -> Size<u32> {
+ delegate!(self, renderer, renderer.dimensions(handle))
+ }
+
+ fn draw(&mut self, handle: crate::core::image::Handle, bounds: Rectangle) {
+ delegate!(self, renderer, renderer.draw(handle, bounds));
+ }
+}
+
+#[cfg(feature = "svg")]
+impl<T> crate::core::svg::Renderer for Renderer<T> {
+ fn dimensions(&self, handle: &crate::core::svg::Handle) -> Size<u32> {
+ delegate!(self, renderer, renderer.dimensions(handle))
+ }
+
+ fn draw(
+ &mut self,
+ handle: crate::core::svg::Handle,
+ color: Option<crate::core::Color>,
+ bounds: Rectangle,
+ ) {
+ delegate!(self, renderer, renderer.draw(handle, color, bounds))
+ }
+}
+
+#[cfg(feature = "geometry")]
+impl<T> crate::graphics::geometry::Renderer for Renderer<T> {
+ type Geometry = crate::Geometry;
+
+ fn draw(&mut self, layers: Vec<Self::Geometry>) {
+ match self {
+ Self::TinySkia(renderer) => {
+ for layer in layers {
+ match layer {
+ crate::Geometry::TinySkia(primitive) => {
+ renderer.draw_primitive(primitive);
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+ #[cfg(feature = "wgpu")]
+ Self::Wgpu(renderer) => {
+ for layer in layers {
+ match layer {
+ crate::Geometry::Wgpu(primitive) => {
+ renderer.draw_primitive(primitive);
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tiny_skia/Cargo.toml b/tiny_skia/Cargo.toml
index ef993fb9..431f324b 100644
--- a/tiny_skia/Cargo.toml
+++ b/tiny_skia/Cargo.toml
@@ -20,7 +20,6 @@ log = "0.4"
[dependencies.iced_graphics]
version = "0.8"
path = "../graphics"
-features = ["tiny-skia"]
[dependencies.cosmic-text]
git = "https://github.com/hecrj/cosmic-text.git"
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index c8999561..0d06ef70 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -2,7 +2,8 @@ use crate::core::text;
use crate::core::Gradient;
use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector};
use crate::graphics::backend;
-use crate::graphics::{Primitive, Viewport};
+use crate::graphics::{Damage, Viewport};
+use crate::primitive::{self, Primitive};
use crate::Settings;
use std::borrow::Cow;
@@ -419,6 +420,13 @@ impl Backend {
self.raster_pipeline
.draw(handle, *bounds, pixels, transform, clip_mask);
}
+ #[cfg(not(feature = "image"))]
+ Primitive::Image { .. } => {
+ log::warn!(
+ "Unsupported primitive in `iced_tiny_skia`: {:?}",
+ primitive
+ );
+ }
#[cfg(feature = "svg")]
Primitive::Svg {
handle,
@@ -442,12 +450,19 @@ impl Backend {
clip_mask,
);
}
- Primitive::Fill {
+ #[cfg(not(feature = "svg"))]
+ Primitive::Svg { .. } => {
+ log::warn!(
+ "Unsupported primitive in `iced_tiny_skia`: {:?}",
+ primitive
+ );
+ }
+ Primitive::Custom(primitive::Custom::Fill {
path,
paint,
rule,
transform,
- } => {
+ }) => {
let bounds = path.bounds();
let physical_bounds = (Rectangle {
@@ -475,12 +490,12 @@ impl Backend {
clip_mask,
);
}
- Primitive::Stroke {
+ Primitive::Custom(primitive::Custom::Stroke {
path,
paint,
stroke,
transform,
- } => {
+ }) => {
let bounds = path.bounds();
let physical_bounds = (Rectangle {
@@ -588,13 +603,6 @@ impl Backend {
primitive
);
}
- _ => {
- // Not supported!
- log::warn!(
- "Unsupported primitive in `iced_tiny_skia`: {:?}",
- primitive
- );
- }
}
}
}
@@ -766,6 +774,10 @@ fn adjust_clip_mask(clip_mask: &mut tiny_skia::Mask, bounds: Rectangle) {
);
}
+impl iced_graphics::Backend for Backend {
+ type Primitive = primitive::Custom;
+}
+
impl backend::Text for Backend {
const ICON_FONT: Font = Font::with_name("Iced-Icons");
const CHECKMARK_ICON: char = '\u{f00c}';
diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs
index ee347c73..9bd47556 100644
--- a/tiny_skia/src/geometry.rs
+++ b/tiny_skia/src/geometry.rs
@@ -3,7 +3,7 @@ use crate::graphics::geometry::fill::{self, Fill};
use crate::graphics::geometry::stroke::{self, Stroke};
use crate::graphics::geometry::{Path, Style, Text};
use crate::graphics::Gradient;
-use crate::graphics::Primitive;
+use crate::primitive::{self, Primitive};
pub struct Frame {
size: Size,
@@ -42,12 +42,13 @@ impl Frame {
let Some(path) = convert_path(path) else { return };
let fill = fill.into();
- self.primitives.push(Primitive::Fill {
- path,
- paint: into_paint(fill.style),
- rule: into_fill_rule(fill.rule),
- transform: self.transform,
- });
+ self.primitives
+ .push(Primitive::Custom(primitive::Custom::Fill {
+ path,
+ paint: into_paint(fill.style),
+ rule: into_fill_rule(fill.rule),
+ transform: self.transform,
+ }));
}
pub fn fill_rectangle(
@@ -59,15 +60,16 @@ impl Frame {
let Some(path) = convert_path(&Path::rectangle(top_left, size)) else { return };
let fill = fill.into();
- self.primitives.push(Primitive::Fill {
- path,
- paint: tiny_skia::Paint {
- anti_alias: false,
- ..into_paint(fill.style)
- },
- rule: into_fill_rule(fill.rule),
- transform: self.transform,
- });
+ self.primitives
+ .push(Primitive::Custom(primitive::Custom::Fill {
+ path,
+ paint: tiny_skia::Paint {
+ anti_alias: false,
+ ..into_paint(fill.style)
+ },
+ rule: into_fill_rule(fill.rule),
+ transform: self.transform,
+ }));
}
pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) {
@@ -76,12 +78,13 @@ impl Frame {
let stroke = stroke.into();
let skia_stroke = into_stroke(&stroke);
- self.primitives.push(Primitive::Stroke {
- path,
- paint: into_paint(stroke.style),
- stroke: skia_stroke,
- transform: self.transform,
- });
+ self.primitives
+ .push(Primitive::Custom(primitive::Custom::Stroke {
+ path,
+ paint: into_paint(stroke.style),
+ stroke: skia_stroke,
+ transform: self.transform,
+ }));
}
pub fn fill_text(&mut self, text: impl Into<Text>) {
diff --git a/tiny_skia/src/lib.rs b/tiny_skia/src/lib.rs
index 83baef1c..15de6ce2 100644
--- a/tiny_skia/src/lib.rs
+++ b/tiny_skia/src/lib.rs
@@ -1,6 +1,7 @@
pub mod window;
mod backend;
+mod primitive;
mod settings;
mod text;
@@ -17,6 +18,7 @@ pub use iced_graphics as graphics;
pub use iced_graphics::core;
pub use backend::Backend;
+pub use primitive::Primitive;
pub use settings::Settings;
/// A [`tiny-skia`] graphics renderer for [`iced`].
diff --git a/tiny_skia/src/primitive.rs b/tiny_skia/src/primitive.rs
new file mode 100644
index 00000000..0ed24969
--- /dev/null
+++ b/tiny_skia/src/primitive.rs
@@ -0,0 +1,48 @@
+use crate::core::Rectangle;
+use crate::graphics::Damage;
+
+pub type Primitive = crate::graphics::Primitive<Custom>;
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Custom {
+ /// A path filled with some paint.
+ Fill {
+ /// The path to fill.
+ path: tiny_skia::Path,
+ /// The paint to use.
+ paint: tiny_skia::Paint<'static>,
+ /// The fill rule to follow.
+ rule: tiny_skia::FillRule,
+ /// The transform to apply to the path.
+ transform: tiny_skia::Transform,
+ },
+ /// A path stroked with some paint.
+ Stroke {
+ /// The path to stroke.
+ path: tiny_skia::Path,
+ /// The paint to use.
+ paint: tiny_skia::Paint<'static>,
+ /// The stroke settings.
+ stroke: tiny_skia::Stroke,
+ /// The transform to apply to the path.
+ transform: tiny_skia::Transform,
+ },
+}
+
+impl Damage for Custom {
+ fn bounds(&self) -> Rectangle {
+ match self {
+ Self::Fill { path, .. } | Self::Stroke { path, .. } => {
+ let bounds = path.bounds();
+
+ Rectangle {
+ x: bounds.x(),
+ y: bounds.y(),
+ width: bounds.width(),
+ height: bounds.height(),
+ }
+ .expand(1.0)
+ }
+ }
+ }
+}
diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs
index f3be3f16..775cf9e5 100644
--- a/tiny_skia/src/window/compositor.rs
+++ b/tiny_skia/src/window/compositor.rs
@@ -1,8 +1,8 @@
use crate::core::{Color, Rectangle, Size};
use crate::graphics::compositor::{self, Information};
use crate::graphics::damage;
-use crate::graphics::{Error, Primitive, Viewport};
-use crate::{Backend, Renderer, Settings};
+use crate::graphics::{Error, Viewport};
+use crate::{Backend, Primitive, Renderer, Settings};
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use std::marker::PhantomData;
diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs
index f8829e47..596d43c5 100644
--- a/wgpu/src/backend.rs
+++ b/wgpu/src/backend.rs
@@ -2,7 +2,8 @@ use crate::core;
use crate::core::{Color, Font, Point, Size};
use crate::graphics::backend;
use crate::graphics::color;
-use crate::graphics::{Primitive, Transformation, Viewport};
+use crate::graphics::{Transformation, Viewport};
+use crate::primitive::{self, Primitive};
use crate::quad;
use crate::text;
use crate::triangle;
@@ -334,6 +335,10 @@ impl Backend {
}
}
+impl crate::graphics::Backend for Backend {
+ type Primitive = primitive::Custom;
+}
+
impl backend::Text for Backend {
const ICON_FONT: Font = Font::with_name("Iced-Icons");
const CHECKMARK_ICON: char = '\u{f00c}';
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs
index f81b5b2f..d43f1065 100644
--- a/wgpu/src/geometry.rs
+++ b/wgpu/src/geometry.rs
@@ -5,10 +5,10 @@ use crate::graphics::geometry::fill::{self, Fill};
use crate::graphics::geometry::{
LineCap, LineDash, LineJoin, Path, Stroke, Style, Text,
};
-use crate::graphics::primitive::{self, Primitive};
-use crate::graphics::Gradient;
+use crate::graphics::gradient::{self, Gradient};
+use crate::graphics::primitive;
+use crate::Primitive;
-use iced_graphics::gradient;
use lyon::geom::euclid;
use lyon::tessellation;
use std::borrow::Cow;
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs
index 71570e3d..ef850cd9 100644
--- a/wgpu/src/layer.rs
+++ b/wgpu/src/layer.rs
@@ -12,8 +12,9 @@ use crate::core;
use crate::core::alignment;
use crate::core::{Color, Font, Point, Rectangle, Size, Vector};
use crate::graphics::color;
-use crate::graphics::{Primitive, Viewport};
+use crate::graphics::Viewport;
use crate::quad::{self, Quad};
+use crate::Primitive;
/// A group of primitives that should be clipped together.
#[derive(Debug)]
@@ -262,13 +263,7 @@ impl<'a> Layer<'a> {
current_layer,
);
}
- _ => {
- // Not supported!
- log::warn!(
- "Unsupported primitive in `iced_wgpu`: {:?}",
- primitive
- );
- }
+ Primitive::Custom(()) => {}
}
}
}
diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs
index 86a962a5..79dfdd24 100644
--- a/wgpu/src/lib.rs
+++ b/wgpu/src/lib.rs
@@ -24,8 +24,8 @@
html_logo_url = "https://raw.githubusercontent.com/iced-rs/iced/9ab6923e943f784985e9ef9ca28b10278297225d/docs/logo.svg"
)]
#![deny(
- missing_debug_implementations,
- missing_docs,
+ //missing_debug_implementations,
+ //missing_docs,
unsafe_code,
unused_results,
clippy::extra_unused_lifetimes,
@@ -47,6 +47,7 @@ pub mod geometry;
mod backend;
mod buffer;
mod color;
+mod primitive;
mod quad;
mod text;
mod triangle;
@@ -60,6 +61,7 @@ pub use wgpu;
pub use backend::Backend;
pub use layer::Layer;
+pub use primitive::Primitive;
pub use settings::Settings;
#[cfg(any(feature = "image", feature = "svg"))]
diff --git a/wgpu/src/primitive.rs b/wgpu/src/primitive.rs
new file mode 100644
index 00000000..2e31cd53
--- /dev/null
+++ b/wgpu/src/primitive.rs
@@ -0,0 +1,3 @@
+pub type Primitive = crate::graphics::Primitive<Custom>;
+
+pub type Custom = ();
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 1cfd7b67..cd5b20cc 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -3,8 +3,8 @@ use crate::core::{Color, Size};
use crate::graphics;
use crate::graphics::color;
use crate::graphics::compositor;
-use crate::graphics::{Error, Primitive, Viewport};
-use crate::{Backend, Renderer, Settings};
+use crate::graphics::{Error, Viewport};
+use crate::{Backend, Primitive, Renderer, Settings};
use futures::stream::{self, StreamExt};
diff --git a/widget/src/canvas/program.rs b/widget/src/canvas/program.rs
index 929ee285..b3f6175e 100644
--- a/widget/src/canvas/program.rs
+++ b/widget/src/canvas/program.rs
@@ -1,7 +1,7 @@
use crate::canvas::event::{self, Event};
use crate::canvas::mouse;
use crate::core::Rectangle;
-use crate::graphics::geometry::{self, Geometry};
+use crate::graphics::geometry;
/// The state and logic of a [`Canvas`].
///
@@ -51,7 +51,7 @@ where
theme: &Renderer::Theme,
bounds: Rectangle,
cursor: mouse::Cursor,
- ) -> Vec<Geometry>;
+ ) -> Vec<Renderer::Geometry>;
/// Returns the current mouse interaction of the [`Program`].
///
@@ -93,7 +93,7 @@ where
theme: &Renderer::Theme,
bounds: Rectangle,
cursor: mouse::Cursor,
- ) -> Vec<Geometry> {
+ ) -> Vec<Renderer::Geometry> {
T::draw(self, state, renderer, theme, bounds, cursor)
}
diff --git a/widget/src/qr_code.rs b/widget/src/qr_code.rs
index 06be93c0..51a541fd 100644
--- a/widget/src/qr_code.rs
+++ b/widget/src/qr_code.rs
@@ -7,6 +7,7 @@ use crate::core::widget::Tree;
use crate::core::{
Color, Element, Layout, Length, Point, Rectangle, Size, Vector, Widget,
};
+use crate::graphics::geometry::Renderer as _;
use crate::Renderer;
use thiserror::Error;
@@ -121,7 +122,7 @@ impl<'a, Message, Theme> Widget<Message, Renderer<Theme>> for QRCode<'a> {
let translation = Vector::new(bounds.x, bounds.y);
renderer.with_translation(translation, |renderer| {
- renderer.draw_primitive(geometry.0);
+ renderer.draw(vec![geometry]);
});
}
}