summaryrefslogtreecommitdiffstats
path: root/renderer
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 /renderer
parent8d65e40a1174ecb8225ce9973575bced36e7aeb5 (diff)
downloadiced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.tar.gz
iced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.tar.bz2
iced-0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2.zip
Introduce custom backend-specific primitives
Diffstat (limited to 'renderer')
-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
4 files changed, 356 insertions, 48 deletions
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!(),
+ }
+ }
+ }
+ }
+ }
+}