diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/src/backend.rs | 8 | ||||
-rw-r--r-- | graphics/src/cached.rs | 42 | ||||
-rw-r--r-- | graphics/src/compositor.rs | 94 | ||||
-rw-r--r-- | graphics/src/error.rs | 27 | ||||
-rw-r--r-- | graphics/src/geometry.rs | 40 | ||||
-rw-r--r-- | graphics/src/geometry/cache.rs | 108 | ||||
-rw-r--r-- | graphics/src/geometry/frame.rs | 251 | ||||
-rw-r--r-- | graphics/src/lib.rs | 6 | ||||
-rw-r--r-- | graphics/src/mesh.rs | 6 | ||||
-rw-r--r-- | graphics/src/renderer.rs | 111 | ||||
-rw-r--r-- | graphics/src/settings.rs | 29 |
11 files changed, 659 insertions, 63 deletions
diff --git a/graphics/src/backend.rs b/graphics/src/backend.rs index 10eb337f..7abc42c5 100644 --- a/graphics/src/backend.rs +++ b/graphics/src/backend.rs @@ -2,15 +2,19 @@ use crate::core::image; use crate::core::svg; use crate::core::Size; +use crate::{Compositor, Mesh, Renderer}; use std::borrow::Cow; /// The graphics backend of a [`Renderer`]. /// /// [`Renderer`]: crate::Renderer -pub trait Backend { +pub trait Backend: Sized { /// The custom kind of primitives this [`Backend`] supports. - type Primitive; + type Primitive: TryFrom<Mesh, Error = &'static str>; + + /// The default compositor of this [`Backend`]. + type Compositor: Compositor<Renderer = Renderer<Self>>; } /// A graphics backend that supports text rendering. diff --git a/graphics/src/cached.rs b/graphics/src/cached.rs new file mode 100644 index 00000000..b52f9d9d --- /dev/null +++ b/graphics/src/cached.rs @@ -0,0 +1,42 @@ +use crate::Primitive; + +use std::sync::Arc; + +/// A piece of data that can be cached. +pub trait Cached: Sized { + /// The type of cache produced. + type Cache; + + /// Loads the [`Cache`] into a proper instance. + /// + /// [`Cache`]: Self::Cache + fn load(cache: &Self::Cache) -> Self; + + /// Caches this value, producing its corresponding [`Cache`]. + /// + /// [`Cache`]: Self::Cache + fn cache(self) -> Self::Cache; +} + +impl<T> Cached for Primitive<T> { + type Cache = Arc<Self>; + + fn load(cache: &Arc<Self>) -> Self { + Self::Cache { + content: cache.clone(), + } + } + + fn cache(self) -> Arc<Self> { + Arc::new(self) + } +} + +#[cfg(debug_assertions)] +impl Cached for () { + type Cache = (); + + fn load(_cache: &Self::Cache) -> Self {} + + fn cache(self) -> Self::Cache {} +} diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs index 91951a8e..86472a58 100644 --- a/graphics/src/compositor.rs +++ b/graphics/src/compositor.rs @@ -1,9 +1,8 @@ //! A compositor is responsible for initializing a renderer and managing window //! surfaces. -use crate::{Error, Viewport}; - use crate::core::Color; use crate::futures::{MaybeSend, MaybeSync}; +use crate::{Error, Settings, Viewport}; use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::future::Future; @@ -11,19 +10,28 @@ use thiserror::Error; /// A graphics compositor that can draw to windows. pub trait Compositor: Sized { - /// The settings of the backend. - type Settings: Default; - /// The iced renderer of the backend. - type Renderer: iced_core::Renderer; + type Renderer; /// The surface of the backend. type Surface; /// Creates a new [`Compositor`]. fn new<W: Window + Clone>( - settings: Self::Settings, + settings: Settings, compatible_window: W, + ) -> impl Future<Output = Result<Self, Error>> { + Self::with_backend(settings, compatible_window, None) + } + + /// Creates a new [`Compositor`] with a backend preference. + /// + /// If the backend does not match the preference, it will return + /// [`Error::GraphicsAdapterNotFound`]. + fn with_backend<W: Window + Clone>( + _settings: Settings, + _compatible_window: W, + _backend: Option<&str>, ) -> impl Future<Output = Result<Self, Error>>; /// Creates a [`Self::Renderer`] for the [`Compositor`]. @@ -93,6 +101,12 @@ impl<T> Window for T where { } +/// Defines the default compositor of a renderer. +pub trait Default { + /// The compositor of the renderer. + type Compositor: Compositor<Renderer = Self>; +} + /// Result of an unsuccessful call to [`Compositor::present`]. #[derive(Clone, PartialEq, Eq, Debug, Error)] pub enum SurfaceError { @@ -122,3 +136,69 @@ pub struct Information { /// Contains the graphics backend. pub backend: String, } + +#[cfg(debug_assertions)] +impl Compositor for () { + type Renderer = (); + type Surface = (); + + async fn with_backend<W: Window + Clone>( + _settings: Settings, + _compatible_window: W, + _preffered_backend: Option<&str>, + ) -> Result<Self, Error> { + Ok(()) + } + + fn create_renderer(&self) -> Self::Renderer {} + + fn create_surface<W: Window + Clone>( + &mut self, + _window: W, + _width: u32, + _height: u32, + ) -> Self::Surface { + } + + fn configure_surface( + &mut self, + _surface: &mut Self::Surface, + _width: u32, + _height: u32, + ) { + } + + fn fetch_information(&self) -> Information { + Information { + adapter: String::from("Null Renderer"), + backend: String::from("Null"), + } + } + + fn present<T: AsRef<str>>( + &mut self, + _renderer: &mut Self::Renderer, + _surface: &mut Self::Surface, + _viewport: &Viewport, + _background_color: Color, + _overlay: &[T], + ) -> Result<(), SurfaceError> { + Ok(()) + } + + fn screenshot<T: AsRef<str>>( + &mut self, + _renderer: &mut Self::Renderer, + _surface: &mut Self::Surface, + _viewport: &Viewport, + _background_color: Color, + _overlay: &[T], + ) -> Vec<u8> { + vec![] + } +} + +#[cfg(debug_assertions)] +impl Default for () { + type Compositor = (); +} diff --git a/graphics/src/error.rs b/graphics/src/error.rs index c6ea98a3..6ea1d3a4 100644 --- a/graphics/src/error.rs +++ b/graphics/src/error.rs @@ -1,5 +1,7 @@ +//! See what can go wrong when creating graphical backends. + /// An error that occurred while creating an application's graphical context. -#[derive(Debug, thiserror::Error)] +#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum Error { /// The requested backend version is not supported. #[error("the requested backend version is not supported")] @@ -11,9 +13,30 @@ pub enum Error { /// A suitable graphics adapter or device could not be found. #[error("a suitable graphics adapter or device could not be found")] - GraphicsAdapterNotFound, + GraphicsAdapterNotFound { + /// The name of the backend where the error happened + backend: &'static str, + /// The reason why this backend could not be used + reason: Reason, + }, /// An error occurred in the context's internal backend #[error("an error occurred in the context's internal backend")] BackendError(String), + + /// Multiple errors occurred + #[error("multiple errors occurred: {0:?}")] + List(Vec<Self>), +} + +/// The reason why a graphics adapter could not be found +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum Reason { + /// The backend did not match the preference + DidNotMatch { + /// The preferred backend + preferred_backend: String, + }, + /// The request to create the backend failed + RequestFailed(String), } diff --git a/graphics/src/geometry.rs b/graphics/src/geometry.rs index d7d6a0aa..d251efb8 100644 --- a/graphics/src/geometry.rs +++ b/graphics/src/geometry.rs @@ -1,12 +1,16 @@ //! Build and draw geometry. pub mod fill; +pub mod frame; pub mod path; pub mod stroke; +mod cache; mod style; mod text; +pub use cache::Cache; pub use fill::Fill; +pub use frame::Frame; pub use path::Path; pub use stroke::{LineCap, LineDash, LineJoin, Stroke}; pub use style::Style; @@ -14,11 +18,39 @@ pub use text::Text; pub use crate::gradient::{self, Gradient}; +use crate::core::{self, Size}; +use crate::Cached; + /// A renderer capable of drawing some [`Self::Geometry`]. -pub trait Renderer: crate::core::Renderer { +pub trait Renderer: core::Renderer { /// The kind of geometry this renderer can draw. - type Geometry; + type Geometry: Cached; + + /// The kind of [`Frame`] this renderer supports. + type Frame: frame::Backend<Geometry = Self::Geometry>; + + /// Creates a new [`Self::Frame`]. + fn new_frame(&self, size: Size) -> Self::Frame; + + /// Draws the given [`Self::Geometry`]. + fn draw_geometry(&mut self, geometry: Self::Geometry); +} + +/// The graphics backend of a geometry renderer. +pub trait Backend { + /// The kind of [`Frame`] this backend supports. + type Frame: frame::Backend; + + /// Creates a new [`Self::Frame`]. + fn new_frame(&self, size: Size) -> Self::Frame; +} + +#[cfg(debug_assertions)] +impl Renderer for () { + type Geometry = (); + type Frame = (); + + fn new_frame(&self, _size: Size) -> Self::Frame {} - /// Draws the given layers of [`Self::Geometry`]. - fn draw(&mut self, layers: Vec<Self::Geometry>); + fn draw_geometry(&mut self, _geometry: Self::Geometry) {} } diff --git a/graphics/src/geometry/cache.rs b/graphics/src/geometry/cache.rs new file mode 100644 index 00000000..37d433c2 --- /dev/null +++ b/graphics/src/geometry/cache.rs @@ -0,0 +1,108 @@ +use crate::core::Size; +use crate::geometry::{self, Frame}; +use crate::Cached; + +use std::cell::RefCell; + +/// A simple cache that stores generated geometry to avoid recomputation. +/// +/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer +/// change or it is explicitly cleared. +pub struct Cache<Renderer> +where + Renderer: geometry::Renderer, +{ + state: RefCell<State<Renderer::Geometry>>, +} + +impl<Renderer> Cache<Renderer> +where + Renderer: geometry::Renderer, +{ + /// Creates a new empty [`Cache`]. + pub fn new() -> Self { + Cache { + state: RefCell::new(State::Empty), + } + } + + /// Clears the [`Cache`], forcing a redraw the next time it is used. + pub fn clear(&self) { + *self.state.borrow_mut() = State::Empty; + } + + /// Draws geometry using the provided closure and stores it in the + /// [`Cache`]. + /// + /// The closure will only be called when + /// - the bounds have changed since the previous draw call. + /// - the [`Cache`] is empty or has been explicitly cleared. + /// + /// Otherwise, the previously stored geometry will be returned. The + /// [`Cache`] is not cleared in this case. In other words, it will keep + /// returning the stored geometry if needed. + pub fn draw( + &self, + renderer: &Renderer, + bounds: Size, + draw_fn: impl FnOnce(&mut Frame<Renderer>), + ) -> Renderer::Geometry { + use std::ops::Deref; + + if let State::Filled { + bounds: cached_bounds, + geometry, + } = self.state.borrow().deref() + { + if *cached_bounds == bounds { + return Cached::load(geometry); + } + } + + let mut frame = Frame::new(renderer, bounds); + draw_fn(&mut frame); + + let geometry = frame.into_geometry().cache(); + let result = Cached::load(&geometry); + + *self.state.borrow_mut() = State::Filled { bounds, geometry }; + + result + } +} + +impl<Renderer> std::fmt::Debug for Cache<Renderer> +where + Renderer: geometry::Renderer, +{ + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let state = self.state.borrow(); + + match *state { + State::Empty => write!(f, "Cache::Empty"), + State::Filled { bounds, .. } => { + write!(f, "Cache::Filled {{ bounds: {bounds:?} }}") + } + } + } +} + +impl<Renderer> Default for Cache<Renderer> +where + Renderer: geometry::Renderer, +{ + fn default() -> Self { + Self::new() + } +} + +enum State<Geometry> +where + Geometry: Cached, +{ + Empty, + Filled { + bounds: Size, + geometry: Geometry::Cache, + }, +} diff --git a/graphics/src/geometry/frame.rs b/graphics/src/geometry/frame.rs new file mode 100644 index 00000000..ad35e8ec --- /dev/null +++ b/graphics/src/geometry/frame.rs @@ -0,0 +1,251 @@ +//! Draw and generate geometry. +use crate::core::{Point, Radians, Rectangle, Size, Vector}; +use crate::geometry::{self, Fill, Path, Stroke, Text}; + +/// The region of a surface that can be used to draw geometry. +#[allow(missing_debug_implementations)] +pub struct Frame<Renderer> +where + Renderer: geometry::Renderer, +{ + raw: Renderer::Frame, +} + +impl<Renderer> Frame<Renderer> +where + Renderer: geometry::Renderer, +{ + /// Creates a new [`Frame`] with the given dimensions. + pub fn new(renderer: &Renderer, size: Size) -> Self { + Self { + raw: renderer.new_frame(size), + } + } + + /// Returns the width of the [`Frame`]. + pub fn width(&self) -> f32 { + self.raw.width() + } + + /// Returns the height of the [`Frame`]. + pub fn height(&self) -> f32 { + self.raw.height() + } + + /// Returns the dimensions of the [`Frame`]. + pub fn size(&self) -> Size { + self.raw.size() + } + + /// Returns the coordinate of the center of the [`Frame`]. + pub fn center(&self) -> Point { + self.raw.center() + } + + /// Draws the given [`Path`] on the [`Frame`] by filling it with the + /// provided style. + pub fn fill(&mut self, path: &Path, fill: impl Into<Fill>) { + self.raw.fill(path, fill); + } + + /// Draws an axis-aligned rectangle given its top-left corner coordinate and + /// its `Size` on the [`Frame`] by filling it with the provided style. + pub fn fill_rectangle( + &mut self, + top_left: Point, + size: Size, + fill: impl Into<Fill>, + ) { + self.raw.fill_rectangle(top_left, size, fill); + } + + /// Draws the stroke of the given [`Path`] on the [`Frame`] with the + /// provided style. + pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>) { + self.raw.stroke(path, stroke); + } + + /// Draws the characters of the given [`Text`] on the [`Frame`], filling + /// them with the given color. + /// + /// __Warning:__ All text will be rendered on top of all the layers of + /// a `Canvas`. Therefore, it is currently only meant to be used for + /// overlays, which is the most common use case. + pub fn fill_text(&mut self, text: impl Into<Text>) { + self.raw.fill_text(text); + } + + /// Stores the current transform of the [`Frame`] and executes the given + /// drawing operations, restoring the transform afterwards. + /// + /// This method is useful to compose transforms and perform drawing + /// operations in different coordinate systems. + #[inline] + pub fn with_save<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { + self.push_transform(); + + let result = f(self); + + self.pop_transform(); + + result + } + + /// Pushes the current transform in the transform stack. + pub fn push_transform(&mut self) { + self.raw.push_transform(); + } + + /// Pops a transform from the transform stack and sets it as the current transform. + pub fn pop_transform(&mut self) { + self.raw.pop_transform(); + } + + /// Executes the given drawing operations within a [`Rectangle`] region, + /// clipping any geometry that overflows its bounds. Any transformations + /// performed are local to the provided closure. + /// + /// This method is useful to perform drawing operations that need to be + /// clipped. + #[inline] + pub fn with_clip<R>( + &mut self, + region: Rectangle, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + let mut frame = self.draft(region.size()); + + let result = f(&mut frame); + + let origin = Point::new(region.x, region.y); + + self.paste(frame, origin); + + result + } + + /// Creates a new [`Frame`] with the given [`Size`]. + /// + /// Draw its contents back to this [`Frame`] with [`paste`]. + /// + /// [`paste`]: Self::paste + pub fn draft(&mut self, size: Size) -> Self { + Self { + raw: self.raw.draft(size), + } + } + + /// Draws the contents of the given [`Frame`] with origin at the given [`Point`]. + pub fn paste(&mut self, frame: Self, at: Point) { + self.raw.paste(frame.raw, at); + } + + /// Applies a translation to the current transform of the [`Frame`]. + pub fn translate(&mut self, translation: Vector) { + self.raw.translate(translation); + } + + /// Applies a rotation in radians to the current transform of the [`Frame`]. + pub fn rotate(&mut self, angle: impl Into<Radians>) { + self.raw.rotate(angle); + } + + /// Applies a uniform scaling to the current transform of the [`Frame`]. + pub fn scale(&mut self, scale: impl Into<f32>) { + self.raw.scale(scale); + } + + /// Applies a non-uniform scaling to the current transform of the [`Frame`]. + pub fn scale_nonuniform(&mut self, scale: impl Into<Vector>) { + self.raw.scale_nonuniform(scale); + } + + /// Turns the [`Frame`] into its underlying geometry. + pub fn into_geometry(self) -> Renderer::Geometry { + self.raw.into_geometry() + } +} + +/// The internal implementation of a [`Frame`]. +/// +/// Analogous to [`Frame`]. See [`Frame`] for the documentation +/// of each method. +#[allow(missing_docs)] +pub trait Backend: Sized { + type Geometry; + + fn width(&self) -> f32; + fn height(&self) -> f32; + fn size(&self) -> Size; + fn center(&self) -> Point; + + fn push_transform(&mut self); + fn pop_transform(&mut self); + + fn translate(&mut self, translation: Vector); + fn rotate(&mut self, angle: impl Into<Radians>); + fn scale(&mut self, scale: impl Into<f32>); + fn scale_nonuniform(&mut self, scale: impl Into<Vector>); + + fn draft(&mut self, size: Size) -> Self; + fn paste(&mut self, frame: Self, at: Point); + + fn stroke<'a>(&mut self, path: &Path, stroke: impl Into<Stroke<'a>>); + + fn fill(&mut self, path: &Path, fill: impl Into<Fill>); + fn fill_text(&mut self, text: impl Into<Text>); + fn fill_rectangle( + &mut self, + top_left: Point, + size: Size, + fill: impl Into<Fill>, + ); + + fn into_geometry(self) -> Self::Geometry; +} + +#[cfg(debug_assertions)] +impl Backend for () { + type Geometry = (); + + fn width(&self) -> f32 { + 0.0 + } + + fn height(&self) -> f32 { + 0.0 + } + + fn size(&self) -> Size { + Size::ZERO + } + + fn center(&self) -> Point { + Point::ORIGIN + } + + fn push_transform(&mut self) {} + fn pop_transform(&mut self) {} + + fn translate(&mut self, _translation: Vector) {} + fn rotate(&mut self, _angle: impl Into<Radians>) {} + fn scale(&mut self, _scale: impl Into<f32>) {} + fn scale_nonuniform(&mut self, _scale: impl Into<Vector>) {} + + fn draft(&mut self, _size: Size) -> Self {} + fn paste(&mut self, _frame: Self, _at: Point) {} + + fn stroke<'a>(&mut self, _path: &Path, _stroke: impl Into<Stroke<'a>>) {} + + fn fill(&mut self, _path: &Path, _fill: impl Into<Fill>) {} + fn fill_text(&mut self, _text: impl Into<Text>) {} + fn fill_rectangle( + &mut self, + _top_left: Point, + _size: Size, + _fill: impl Into<Fill>, + ) { + } + + fn into_geometry(self) -> Self::Geometry {} +} diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index aa9d00e8..d7f2f439 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -17,14 +17,16 @@ )] #![cfg_attr(docsrs, feature(doc_auto_cfg))] mod antialiasing; -mod error; +mod cached; mod primitive; +mod settings; mod viewport; pub mod backend; pub mod color; pub mod compositor; pub mod damage; +pub mod error; pub mod gradient; pub mod mesh; pub mod renderer; @@ -38,6 +40,7 @@ pub mod image; pub use antialiasing::Antialiasing; pub use backend::Backend; +pub use cached::Cached; pub use compositor::Compositor; pub use damage::Damage; pub use error::Error; @@ -45,6 +48,7 @@ pub use gradient::Gradient; pub use mesh::Mesh; pub use primitive::Primitive; pub use renderer::Renderer; +pub use settings::Settings; pub use viewport::Viewport; pub use iced_core as core; diff --git a/graphics/src/mesh.rs b/graphics/src/mesh.rs index 041986cf..20692b07 100644 --- a/graphics/src/mesh.rs +++ b/graphics/src/mesh.rs @@ -74,3 +74,9 @@ pub struct GradientVertex2D { /// The packed vertex data of the gradient. pub gradient: gradient::Packed, } + +/// A renderer capable of drawing a [`Mesh`]. +pub trait Renderer { + /// Draws the given [`Mesh`]. + fn draw_mesh(&mut self, mesh: Mesh); +} diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs index 143f348b..f517ff3e 100644 --- a/graphics/src/renderer.rs +++ b/graphics/src/renderer.rs @@ -1,5 +1,6 @@ //! Create a renderer from a [`Backend`]. use crate::backend::{self, Backend}; +use crate::compositor; use crate::core; use crate::core::image; use crate::core::renderer; @@ -8,8 +9,9 @@ use crate::core::text::Text; use crate::core::{ Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation, }; +use crate::mesh; use crate::text; -use crate::Primitive; +use crate::{Mesh, Primitive}; use std::borrow::Cow; @@ -20,6 +22,7 @@ pub struct Renderer<B: Backend> { default_font: Font, default_text_size: Pixels, primitives: Vec<Primitive<B::Primitive>>, + stack: Vec<Vec<Primitive<B::Primitive>>>, } impl<B: Backend> Renderer<B> { @@ -34,6 +37,7 @@ impl<B: Backend> Renderer<B> { default_font, default_text_size, primitives: Vec::new(), + stack: Vec::new(), } } @@ -55,61 +59,35 @@ impl<B: Backend> Renderer<B> { ) -> O { f(&mut self.backend, &self.primitives) } +} - /// Starts recording a new layer. - pub fn start_layer(&mut self) -> Vec<Primitive<B::Primitive>> { - std::mem::take(&mut self.primitives) +impl<B: Backend> iced_core::Renderer for Renderer<B> { + fn start_layer(&mut self) { + self.stack.push(std::mem::take(&mut self.primitives)); } - /// Ends the recording of a layer. - pub fn end_layer( - &mut self, - primitives: Vec<Primitive<B::Primitive>>, - bounds: Rectangle, - ) { - let layer = std::mem::replace(&mut self.primitives, primitives); + fn end_layer(&mut self, bounds: Rectangle) { + let layer = std::mem::replace( + &mut self.primitives, + self.stack.pop().expect("a layer should be recording"), + ); self.primitives.push(Primitive::group(layer).clip(bounds)); } - /// Starts recording a translation. - pub fn start_transformation(&mut self) -> Vec<Primitive<B::Primitive>> { - std::mem::take(&mut self.primitives) + fn start_transformation(&mut self) { + self.stack.push(std::mem::take(&mut self.primitives)); } - /// Ends the recording of a translation. - pub fn end_transformation( - &mut self, - primitives: Vec<Primitive<B::Primitive>>, - transformation: Transformation, - ) { - let layer = std::mem::replace(&mut self.primitives, primitives); + fn end_transformation(&mut self, transformation: Transformation) { + let layer = std::mem::replace( + &mut self.primitives, + self.stack.pop().expect("a layer should be recording"), + ); self.primitives .push(Primitive::group(layer).transform(transformation)); } -} - -impl<B: Backend> iced_core::Renderer for Renderer<B> { - fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) { - let current = self.start_layer(); - - f(self); - - self.end_layer(current, bounds); - } - - fn with_transformation( - &mut self, - transformation: Transformation, - f: impl FnOnce(&mut Self), - ) { - let current = self.start_transformation(); - - f(self); - - self.end_transformation(current, transformation); - } fn fill_quad( &mut self, @@ -211,11 +189,11 @@ where { type Handle = image::Handle; - fn dimensions(&self, handle: &image::Handle) -> Size<u32> { + fn measure_image(&self, handle: &image::Handle) -> Size<u32> { self.backend().dimensions(handle) } - fn draw( + fn draw_image( &mut self, handle: image::Handle, filter_method: image::FilterMethod, @@ -233,11 +211,11 @@ impl<B> svg::Renderer for Renderer<B> where B: Backend + backend::Svg, { - fn dimensions(&self, handle: &svg::Handle) -> Size<u32> { + fn measure_svg(&self, handle: &svg::Handle) -> Size<u32> { self.backend().viewport_dimensions(handle) } - fn draw( + fn draw_svg( &mut self, handle: svg::Handle, color: Option<Color>, @@ -250,3 +228,42 @@ where }); } } + +impl<B: Backend> mesh::Renderer for Renderer<B> { + fn draw_mesh(&mut self, mesh: Mesh) { + match B::Primitive::try_from(mesh) { + Ok(primitive) => { + self.draw_primitive(Primitive::Custom(primitive)); + } + Err(error) => { + log::warn!("mesh primitive could not be drawn: {error:?}"); + } + } + } +} + +#[cfg(feature = "geometry")] +impl<B> crate::geometry::Renderer for Renderer<B> +where + B: Backend + crate::geometry::Backend, + B::Frame: + crate::geometry::frame::Backend<Geometry = Primitive<B::Primitive>>, +{ + type Frame = B::Frame; + type Geometry = Primitive<B::Primitive>; + + fn new_frame(&self, size: Size) -> Self::Frame { + self.backend.new_frame(size) + } + + fn draw_geometry(&mut self, geometry: Self::Geometry) { + self.draw_primitive(geometry); + } +} + +impl<B> compositor::Default for Renderer<B> +where + B: Backend, +{ + type Compositor = B::Compositor; +} diff --git a/graphics/src/settings.rs b/graphics/src/settings.rs new file mode 100644 index 00000000..68673536 --- /dev/null +++ b/graphics/src/settings.rs @@ -0,0 +1,29 @@ +use crate::core::{Font, Pixels}; +use crate::Antialiasing; + +/// The settings of a Backend. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Settings { + /// The default [`Font`] to use. + pub default_font: Font, + + /// The default size of text. + /// + /// By default, it will be set to `16.0`. + pub default_text_size: Pixels, + + /// The antialiasing strategy that will be used for triangle primitives. + /// + /// By default, it is `None`. + pub antialiasing: Option<Antialiasing>, +} + +impl Default for Settings { + fn default() -> Settings { + Settings { + default_font: Font::default(), + default_text_size: Pixels(16.0), + antialiasing: None, + } + } +} |