diff options
author | 2023-06-22 00:38:36 +0200 | |
---|---|---|
committer | 2023-06-29 07:18:20 +0200 | |
commit | 0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2 (patch) | |
tree | 7f3d09dca8ea9fae96457d3f9266e014d1d25d80 /renderer | |
parent | 8d65e40a1174ecb8225ce9973575bced36e7aeb5 (diff) | |
download | iced-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.rs | 80 | ||||
-rw-r--r-- | renderer/src/geometry.rs | 24 | ||||
-rw-r--r-- | renderer/src/geometry/cache.rs | 52 | ||||
-rw-r--r-- | renderer/src/lib.rs | 248 |
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!(), + } + } + } + } + } +} |