Skip to content

Commit

Permalink
Merge pull request #2351 from iced-rs/custom-renderer-injection
Browse files Browse the repository at this point in the history
Type-Driven Renderer Fallback
  • Loading branch information
hecrj authored Mar 25, 2024
2 parents 3013463 + 6a4f5ac commit a2a8381
Show file tree
Hide file tree
Showing 56 changed files with 1,886 additions and 1,447 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ all-features = true
maintenance = { status = "actively-developed" }

[features]
default = ["wgpu", "fira-sans", "auto-detect-theme"]
default = ["wgpu", "tiny-skia", "fira-sans", "auto-detect-theme"]
# Enable the `wgpu` GPU-accelerated renderer backend
wgpu = ["iced_renderer/wgpu", "iced_widget/wgpu"]
# Enable the `tiny-skia` software renderer backend
tiny-skia = ["iced_renderer/tiny-skia"]
# Enables the `Image` widget
image = ["iced_widget/image", "dep:image"]
# Enables the `Svg` widget
Expand Down
4 changes: 2 additions & 2 deletions core/src/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
///
/// ```no_run
/// # mod iced {
/// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, iced_core::renderer::Null>;
/// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
/// #
/// # pub mod widget {
/// # pub fn row<'a, Message>(iter: impl IntoIterator<Item = super::Element<'a, Message>>) -> super::Element<'a, Message> {
Expand All @@ -109,7 +109,7 @@ impl<'a, Message, Theme, Renderer> Element<'a, Message, Theme, Renderer> {
/// # pub enum Message {}
/// # pub struct Counter;
/// #
/// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, iced_core::renderer::Null>;
/// # pub type Element<'a, Message> = iced_core::Element<'a, Message, iced_core::Theme, ()>;
/// #
/// # impl Counter {
/// # pub fn view(&self) -> Element<Message> {
Expand Down
4 changes: 2 additions & 2 deletions core/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,11 @@ pub trait Renderer: crate::Renderer {
type Handle: Clone + Hash;

/// Returns the dimensions of an image for the given [`Handle`].
fn dimensions(&self, handle: &Self::Handle) -> Size<u32>;
fn measure_image(&self, handle: &Self::Handle) -> Size<u32>;

/// Draws an image with the given [`Handle`] and inside the provided
/// `bounds`.
fn draw(
fn draw_image(
&mut self,
handle: Self::Handle,
filter_method: FilterMethod,
Expand Down
33 changes: 27 additions & 6 deletions core/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,47 @@
#[cfg(debug_assertions)]
mod null;

#[cfg(debug_assertions)]
pub use null::Null;

use crate::{
Background, Border, Color, Rectangle, Shadow, Size, Transformation, Vector,
};

/// A component that can be used by widgets to draw themselves on a screen.
pub trait Renderer: Sized {
pub trait Renderer {
/// Starts recording a new layer.
fn start_layer(&mut self);

/// Ends recording a new layer.
///
/// The new layer will clip its contents to the provided `bounds`.
fn end_layer(&mut self, bounds: Rectangle);

/// Draws the primitives recorded in the given closure in a new layer.
///
/// The layer will clip its contents to the provided `bounds`.
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self));
fn with_layer(&mut self, bounds: Rectangle, f: impl FnOnce(&mut Self)) {
self.start_layer();
f(self);
self.end_layer(bounds);
}

/// Starts recording with a new [`Transformation`].
fn start_transformation(&mut self);

/// Ends recording a new layer.
///
/// The new layer will clip its contents to the provided `bounds`.
fn end_transformation(&mut self, transformation: Transformation);

/// Applies a [`Transformation`] to the primitives recorded in the given closure.
fn with_transformation(
&mut self,
transformation: Transformation,
f: impl FnOnce(&mut Self),
);
) {
self.start_transformation();
f(self);
self.end_transformation(transformation);
}

/// Applies a translation to the primitives recorded in the given closure.
fn with_translation(
Expand Down
58 changes: 38 additions & 20 deletions core/src/renderer/null.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,22 @@
use crate::alignment;
use crate::image;
use crate::renderer::{self, Renderer};
use crate::svg;
use crate::text::{self, Text};
use crate::{
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
};

use std::borrow::Cow;

/// A renderer that does nothing.
///
/// It can be useful if you are writing tests!
#[derive(Debug, Clone, Copy, Default)]
pub struct Null;
impl Renderer for () {
fn start_layer(&mut self) {}

impl Null {
/// Creates a new [`Null`] renderer.
pub fn new() -> Null {
Null
}
}
fn end_layer(&mut self, _bounds: Rectangle) {}

impl Renderer for Null {
fn with_layer(&mut self, _bounds: Rectangle, _f: impl FnOnce(&mut Self)) {}
fn start_transformation(&mut self) {}

fn with_transformation(
&mut self,
_transformation: Transformation,
_f: impl FnOnce(&mut Self),
) {
}
fn end_transformation(&mut self, _transformation: Transformation) {}

fn clear(&mut self) {}

Expand All @@ -40,7 +28,7 @@ impl Renderer for Null {
}
}

impl text::Renderer for Null {
impl text::Renderer for () {
type Font = Font;
type Paragraph = ();
type Editor = ();
Expand Down Expand Up @@ -174,3 +162,33 @@ impl text::Editor for () {
) {
}
}

impl image::Renderer for () {
type Handle = ();

fn measure_image(&self, _handle: &Self::Handle) -> Size<u32> {
Size::default()
}

fn draw_image(
&mut self,
_handle: Self::Handle,
_filter_method: image::FilterMethod,
_bounds: Rectangle,
) {
}
}

impl svg::Renderer for () {
fn measure_svg(&self, _handle: &svg::Handle) -> Size<u32> {
Size::default()
}

fn draw_svg(
&mut self,
_handle: svg::Handle,
_color: Option<Color>,
_bounds: Rectangle,
) {
}
}
2 changes: 1 addition & 1 deletion core/src/size.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::Vector;

/// An amount of space in 2 dimensions.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Size<T = f32> {
/// The width.
pub width: T,
Expand Down
9 changes: 7 additions & 2 deletions core/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,13 @@ impl std::fmt::Debug for Data {
/// [renderer]: crate::renderer
pub trait Renderer: crate::Renderer {
/// Returns the default dimensions of an SVG for the given [`Handle`].
fn dimensions(&self, handle: &Handle) -> Size<u32>;
fn measure_svg(&self, handle: &Handle) -> Size<u32>;

/// Draws an SVG with the given [`Handle`], an optional [`Color`] filter, and inside the provided `bounds`.
fn draw(&mut self, handle: Handle, color: Option<Color>, bounds: Rectangle);
fn draw_svg(
&mut self,
handle: Handle,
color: Option<Color>,
bounds: Rectangle,
);
}
13 changes: 4 additions & 9 deletions examples/bezier_tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,23 +143,18 @@ mod bezier {
bounds: Rectangle,
cursor: mouse::Cursor,
) -> Vec<Geometry> {
let content = self.state.cache.draw(
renderer,
bounds.size(),
|frame: &mut Frame| {
let content =
self.state.cache.draw(renderer, bounds.size(), |frame| {
Curve::draw_all(self.curves, frame);

frame.stroke(
&Path::rectangle(Point::ORIGIN, frame.size()),
Stroke::default().with_width(2.0),
);
},
);
});

if let Some(pending) = state {
let pending_curve = pending.draw(renderer, bounds, cursor);

vec![content, pending_curve]
vec![content, pending.draw(renderer, bounds, cursor)]
} else {
vec![content]
}
Expand Down
6 changes: 3 additions & 3 deletions examples/game_of_life/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -602,9 +602,7 @@ mod grid {
frame.into_geometry()
};

if self.scaling < 0.2 || !self.show_lines {
vec![life, overlay]
} else {
if self.scaling >= 0.2 && self.show_lines {
let grid =
self.grid_cache.draw(renderer, bounds.size(), |frame| {
frame.translate(center);
Expand Down Expand Up @@ -641,6 +639,8 @@ mod grid {
});

vec![life, grid, overlay]
} else {
vec![life, overlay]
}
}

Expand Down
4 changes: 3 additions & 1 deletion examples/geometry/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ mod rainbow {
cursor: mouse::Cursor,
_viewport: &Rectangle,
) {
use iced::advanced::graphics::mesh::{self, Mesh, SolidVertex2D};
use iced::advanced::graphics::mesh::{
self, Mesh, Renderer as _, SolidVertex2D,
};
use iced::advanced::Renderer as _;

let bounds = layout.bounds();
Expand Down
2 changes: 1 addition & 1 deletion examples/loading_spinners/src/circular.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ where
|renderer| {
use iced::advanced::graphics::geometry::Renderer as _;

renderer.draw(vec![geometry]);
renderer.draw_geometry(geometry);
},
);
}
Expand Down
4 changes: 2 additions & 2 deletions examples/sierpinski_triangle/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use iced::mouse;
use iced::widget::canvas::event::{self, Event};
use iced::widget::canvas::{self, Canvas};
use iced::widget::canvas::{self, Canvas, Geometry};
use iced::widget::{column, row, slider, text};
use iced::{Color, Length, Point, Rectangle, Renderer, Size, Theme};

Expand Down Expand Up @@ -111,7 +111,7 @@ impl canvas::Program<Message> for SierpinskiGraph {
_theme: &Theme,
bounds: Rectangle,
_cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> {
) -> Vec<Geometry> {
let geom = self.cache.draw(renderer, bounds.size(), |frame| {
frame.stroke(
&canvas::Path::rectangle(Point::ORIGIN, frame.size()),
Expand Down
4 changes: 2 additions & 2 deletions examples/solar_system/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use iced::mouse;
use iced::widget::canvas;
use iced::widget::canvas::gradient;
use iced::widget::canvas::stroke::{self, Stroke};
use iced::widget::canvas::Path;
use iced::widget::canvas::{Geometry, Path};
use iced::window;
use iced::{
Color, Element, Length, Point, Rectangle, Renderer, Size, Subscription,
Expand Down Expand Up @@ -130,7 +130,7 @@ impl<Message> canvas::Program<Message> for State {
_theme: &Theme,
bounds: Rectangle,
_cursor: mouse::Cursor,
) -> Vec<canvas::Geometry> {
) -> Vec<Geometry> {
use std::f32::consts::PI;

let background =
Expand Down
8 changes: 6 additions & 2 deletions graphics/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
42 changes: 42 additions & 0 deletions graphics/src/cached.rs
Original file line number Diff line number Diff line change
@@ -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 {}
}
Loading

0 comments on commit a2a8381

Please sign in to comment.