summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
Diffstat (limited to 'graphics')
-rw-r--r--graphics/Cargo.toml5
-rw-r--r--graphics/src/backend.rs10
-rw-r--r--graphics/src/compositor.rs15
-rw-r--r--graphics/src/damage.rs66
-rw-r--r--graphics/src/geometry.rs17
-rw-r--r--graphics/src/gradient.rs85
-rw-r--r--graphics/src/lib.rs8
-rw-r--r--graphics/src/mesh.rs76
-rw-r--r--graphics/src/primitive.rs176
-rw-r--r--graphics/src/renderer.rs81
10 files changed, 274 insertions, 265 deletions
diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml
index 0e22227d..7a9e6aee 100644
--- a/graphics/Cargo.toml
+++ b/graphics/Cargo.toml
@@ -18,6 +18,7 @@ web-colors = []
[dependencies]
glam = "0.24"
+half = "2.2.1"
log = "0.4"
raw-window-handle = "0.5"
thiserror = "1.0"
@@ -31,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 ae89da06..77bb650b 100644
--- a/graphics/src/backend.rs
+++ b/graphics/src/backend.rs
@@ -10,12 +10,8 @@ use std::borrow::Cow;
///
/// [`Renderer`]: crate::Renderer
pub trait Backend {
- /// Trims the measurements cache.
- ///
- /// This method is currently necessary to properly trim the text cache in
- /// `iced_wgpu` and `iced_glow` because of limitations in the text rendering
- /// pipeline. It will be removed in the future.
- fn trim_measurements(&mut self) {}
+ /// The custom kind of primitives this [`Backend`] supports.
+ type Primitive;
}
/// A graphics backend that supports text rendering.
@@ -50,7 +46,7 @@ pub trait Text {
font: Font,
bounds: Size,
shaping: text::Shaping,
- ) -> (f32, f32);
+ ) -> Size;
/// Tests whether the provided point is within the boundaries of [`Text`]
/// laid out with the given parameters, returning information about
diff --git a/graphics/src/compositor.rs b/graphics/src/compositor.rs
index d55e801a..f7b86045 100644
--- a/graphics/src/compositor.rs
+++ b/graphics/src/compositor.rs
@@ -59,6 +59,19 @@ pub trait Compositor: Sized {
background_color: Color,
overlay: &[T],
) -> Result<(), SurfaceError>;
+
+ /// Screenshots the current [`Renderer`] primitives to an offscreen texture, and returns the bytes of
+ /// the texture ordered as `RGBA` in the sRGB color space.
+ ///
+ /// [`Renderer`]: Self::Renderer;
+ fn screenshot<T: AsRef<str>>(
+ &mut self,
+ renderer: &mut Self::Renderer,
+ surface: &mut Self::Surface,
+ viewport: &Viewport,
+ background_color: Color,
+ overlay: &[T],
+ ) -> Vec<u8>;
}
/// Result of an unsuccessful call to [`Compositor::present`].
@@ -82,7 +95,7 @@ pub enum SurfaceError {
OutOfMemory,
}
-/// Contains informations about the graphics (e.g. graphics adapter, graphics backend).
+/// Contains information about the graphics (e.g. graphics adapter, graphics backend).
#[derive(Debug)]
pub struct Information {
/// Contains the graphics adapter.
diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs
index c6b0f759..2f29956e 100644
--- a/graphics/src/damage.rs
+++ b/graphics/src/damage.rs
@@ -1,11 +1,66 @@
//! 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> {
+/// A type that has some damage bounds.
+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::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 +131,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 +151,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..7cd3dd3a 100644
--- a/graphics/src/geometry.rs
+++ b/graphics/src/geometry.rs
@@ -14,20 +14,11 @@ 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 {
+ /// The kind of geometry this renderer can draw.
+ 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/gradient.rs b/graphics/src/gradient.rs
index d26b5665..4db565d8 100644
--- a/graphics/src/gradient.rs
+++ b/graphics/src/gradient.rs
@@ -7,6 +7,8 @@ use crate::color;
use crate::core::gradient::ColorStop;
use crate::core::{self, Color, Point, Rectangle};
+use bytemuck::{Pod, Zeroable};
+use half::f16;
use std::cmp::Ordering;
#[derive(Debug, Clone, PartialEq)]
@@ -99,61 +101,96 @@ impl Linear {
/// Packs the [`Gradient`] for use in shader code.
pub fn pack(&self) -> Packed {
- let mut data: [f32; 44] = [0.0; 44];
+ let mut colors = [[0u32; 2]; 8];
+ let mut offsets = [f16::from(0u8); 8];
for (index, stop) in self.stops.iter().enumerate() {
let [r, g, b, a] =
color::pack(stop.map_or(Color::default(), |s| s.color))
.components();
- data[index * 4] = r;
- data[(index * 4) + 1] = g;
- data[(index * 4) + 2] = b;
- data[(index * 4) + 3] = a;
+ colors[index] = [
+ pack_f16s([f16::from_f32(r), f16::from_f32(g)]),
+ pack_f16s([f16::from_f32(b), f16::from_f32(a)]),
+ ];
- data[32 + index] = stop.map_or(2.0, |s| s.offset);
+ offsets[index] =
+ stop.map_or(f16::from_f32(2.0), |s| f16::from_f32(s.offset));
}
- data[40] = self.start.x;
- data[41] = self.start.y;
- data[42] = self.end.x;
- data[43] = self.end.y;
+ let offsets = [
+ pack_f16s([offsets[0], offsets[1]]),
+ pack_f16s([offsets[2], offsets[3]]),
+ pack_f16s([offsets[4], offsets[5]]),
+ pack_f16s([offsets[6], offsets[7]]),
+ ];
- Packed(data)
+ let direction = [self.start.x, self.start.y, self.end.x, self.end.y];
+
+ Packed {
+ colors,
+ offsets,
+ direction,
+ }
}
}
/// Packed [`Gradient`] data for use in shader code.
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, Zeroable, Pod)]
#[repr(C)]
-pub struct Packed([f32; 44]);
+pub struct Packed {
+ // 8 colors, each channel = 16 bit float, 2 colors packed into 1 u32
+ colors: [[u32; 2]; 8],
+ // 8 offsets, 8x 16 bit floats packed into 4 u32s
+ offsets: [u32; 4],
+ direction: [f32; 4],
+}
/// Creates a new [`Packed`] gradient for use in shader code.
pub fn pack(gradient: &core::Gradient, bounds: Rectangle) -> Packed {
match gradient {
core::Gradient::Linear(linear) => {
- let mut data: [f32; 44] = [0.0; 44];
+ let mut colors = [[0u32; 2]; 8];
+ let mut offsets = [f16::from(0u8); 8];
for (index, stop) in linear.stops.iter().enumerate() {
let [r, g, b, a] =
color::pack(stop.map_or(Color::default(), |s| s.color))
.components();
- data[index * 4] = r;
- data[(index * 4) + 1] = g;
- data[(index * 4) + 2] = b;
- data[(index * 4) + 3] = a;
- data[32 + index] = stop.map_or(2.0, |s| s.offset);
+ colors[index] = [
+ pack_f16s([f16::from_f32(r), f16::from_f32(g)]),
+ pack_f16s([f16::from_f32(b), f16::from_f32(a)]),
+ ];
+
+ offsets[index] = stop
+ .map_or(f16::from_f32(2.0), |s| f16::from_f32(s.offset));
}
+ let offsets = [
+ pack_f16s([offsets[0], offsets[1]]),
+ pack_f16s([offsets[2], offsets[3]]),
+ pack_f16s([offsets[4], offsets[5]]),
+ pack_f16s([offsets[6], offsets[7]]),
+ ];
+
let (start, end) = linear.angle.to_distance(&bounds);
- data[40] = start.x;
- data[41] = start.y;
- data[42] = end.x;
- data[43] = end.y;
+ let direction = [start.x, start.y, end.x, end.y];
- Packed(data)
+ Packed {
+ colors,
+ offsets,
+ direction,
+ }
}
}
}
+
+/// Packs two f16s into one u32.
+fn pack_f16s(f: [f16; 2]) -> u32 {
+ let one = (f[0].to_bits() as u32) << 16;
+ let two = f[1].to_bits() as u32;
+
+ one | two
+}
diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs
index f6bc87fb..af374a2f 100644
--- a/graphics/src/lib.rs
+++ b/graphics/src/lib.rs
@@ -23,6 +23,7 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
mod antialiasing;
mod error;
+mod primitive;
mod transformation;
mod viewport;
@@ -31,7 +32,7 @@ pub mod color;
pub mod compositor;
pub mod damage;
pub mod gradient;
-pub mod primitive;
+pub mod mesh;
pub mod renderer;
#[cfg(feature = "geometry")]
@@ -43,14 +44,13 @@ 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 mesh::Mesh;
pub use primitive::Primitive;
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/mesh.rs b/graphics/src/mesh.rs
new file mode 100644
index 00000000..cfb5a60f
--- /dev/null
+++ b/graphics/src/mesh.rs
@@ -0,0 +1,76 @@
+//! Draw triangles!
+use crate::color;
+use crate::core::{Rectangle, Size};
+use crate::gradient;
+use crate::Damage;
+
+use bytemuck::{Pod, Zeroable};
+
+/// A low-level primitive to render a mesh of triangles.
+#[derive(Debug, Clone, PartialEq)]
+pub enum Mesh {
+ /// A mesh with a solid color.
+ Solid {
+ /// The vertices and indices of the mesh.
+ buffers: Indexed<SolidVertex2D>,
+
+ /// The size of the drawable region of the mesh.
+ ///
+ /// Any geometry that falls out of this region will be clipped.
+ size: Size,
+ },
+ /// A mesh with a gradient.
+ Gradient {
+ /// The vertices and indices of the mesh.
+ buffers: Indexed<GradientVertex2D>,
+
+ /// The size of the drawable region of the mesh.
+ ///
+ /// Any geometry that falls out of this region will be clipped.
+ size: Size,
+ },
+}
+
+impl Damage for Mesh {
+ fn bounds(&self) -> Rectangle {
+ match self {
+ Self::Solid { size, .. } | Self::Gradient { size, .. } => {
+ Rectangle::with_size(*size)
+ }
+ }
+ }
+}
+
+/// A set of [`Vertex2D`] and indices representing a list of triangles.
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Indexed<T> {
+ /// The vertices of the mesh
+ pub vertices: Vec<T>,
+
+ /// The list of vertex indices that defines the triangles of the mesh.
+ ///
+ /// Therefore, this list should always have a length that is a multiple of 3.
+ pub indices: Vec<u32>,
+}
+
+/// A two-dimensional vertex with a color.
+#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
+#[repr(C)]
+pub struct SolidVertex2D {
+ /// The vertex position in 2D space.
+ pub position: [f32; 2],
+
+ /// The color of the vertex in __linear__ RGBA.
+ pub color: color::Packed,
+}
+
+/// A vertex which contains 2D position & packed gradient data.
+#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
+#[repr(C)]
+pub struct GradientVertex2D {
+ /// The vertex position in 2D space.
+ pub position: [f32; 2],
+
+ /// The packed vertex data of the gradient.
+ pub gradient: gradient::Packed,
+}
diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs
index 187c6c6c..7592a410 100644
--- a/graphics/src/primitive.rs
+++ b/graphics/src/primitive.rs
@@ -1,19 +1,15 @@
//! Draw using different graphical primitives.
-use crate::color;
use crate::core::alignment;
use crate::core::image;
use crate::core::svg;
use crate::core::text;
-use crate::core::{Background, Color, Font, Rectangle, Size, Vector};
-use crate::gradient;
+use crate::core::{Background, Color, Font, Rectangle, Vector};
-use bytemuck::{Pod, Zeroable};
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
@@ -66,65 +62,17 @@ pub enum Primitive {
/// The bounds of the viewport
bounds: Rectangle,
},
- /// A low-level primitive to render a mesh of triangles with a solid color.
- ///
- /// It can be used to render many kinds of geometry freely.
- SolidMesh {
- /// The vertices and indices of the mesh.
- buffers: Mesh2D<ColoredVertex2D>,
-
- /// The size of the drawable region of the mesh.
- ///
- /// Any geometry that falls out of this region will be clipped.
- size: Size,
- },
- /// A low-level primitive to render a mesh of triangles with a gradient.
- ///
- /// It can be used to render many kinds of geometry freely.
- GradientMesh {
- /// The vertices and indices of the mesh.
- buffers: Mesh2D<GradientVertex2D>,
-
- /// The size of the drawable region of the mesh.
- ///
- /// 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 +80,7 @@ pub enum Primitive {
translation: Vector,
/// The primitive to translate
- content: Box<Primitive>,
+ content: Box<Primitive<T>>,
},
/// A cached primitive.
///
@@ -140,11 +88,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,112 +115,4 @@ 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.
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Mesh2D<T> {
- /// The vertices of the mesh
- pub vertices: Vec<T>,
-
- /// The list of vertex indices that defines the triangles of the mesh.
- ///
- /// Therefore, this list should always have a length that is a multiple of 3.
- pub indices: Vec<u32>,
-}
-
-/// A two-dimensional vertex with a color.
-#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
-#[repr(C)]
-pub struct ColoredVertex2D {
- /// The vertex position in 2D space.
- pub position: [f32; 2],
-
- /// The color of the vertex in __linear__ RGBA.
- pub color: color::Packed,
-}
-
-/// A vertex which contains 2D position & packed gradient data.
-#[derive(Copy, Clone, Debug, PartialEq)]
-#[repr(C)]
-pub struct GradientVertex2D {
- /// The vertex position in 2D space.
- pub position: [f32; 2],
-
- /// The packed vertex data of the gradient.
- pub gradient: gradient::Packed,
-}
-
-#[allow(unsafe_code)]
-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 de905503..d80dea34 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -3,13 +3,10 @@ use crate::backend::{self, Backend};
use crate::Primitive;
use iced_core::image;
-use iced_core::layout;
use iced_core::renderer;
use iced_core::svg;
use iced_core::text::{self, Text};
-use iced_core::{
- Background, Color, Element, Font, Point, Rectangle, Size, Vector,
-};
+use iced_core::{Background, Color, Font, Point, Rectangle, Size, Vector};
use std::borrow::Cow;
use std::marker::PhantomData;
@@ -18,7 +15,7 @@ use std::marker::PhantomData;
#[derive(Debug)]
pub struct Renderer<B: Backend, Theme> {
backend: B,
- primitives: Vec<Primitive>,
+ primitives: Vec<Primitive<B::Primitive>>,
theme: PhantomData<Theme>,
}
@@ -38,7 +35,7 @@ impl<B: Backend, 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,38 +43,54 @@ impl<B: Backend, 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)
}
-}
-impl<B, T> iced_core::Renderer for Renderer<B, T>
-where
- B: Backend,
-{
- type Theme = T;
+ /// Starts recording a new layer.
+ pub fn start_layer(&mut self) -> Vec<Primitive<B::Primitive>> {
+ std::mem::take(&mut self.primitives)
+ }
- fn layout<Message>(
+ /// Ends the recording of a layer.
+ pub fn end_layer(
&mut self,
- element: &Element<'_, Message, Self>,
- limits: &layout::Limits,
- ) -> layout::Node {
- let layout = element.as_widget().layout(self, limits);
+ primitives: Vec<Primitive<B::Primitive>>,
+ bounds: Rectangle,
+ ) {
+ let layer = std::mem::replace(&mut self.primitives, primitives);
- self.backend.trim_measurements();
+ self.primitives.push(Primitive::group(layer).clip(bounds));
+ }
- layout
+ /// Starts recording a translation.
+ pub fn start_translation(&mut self) -> Vec<Primitive<B::Primitive>> {
+ std::mem::take(&mut self.primitives)
}
+ /// Ends the recording of a translation.
+ 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: Backend, T> iced_core::Renderer for Renderer<B, T> {
+ type Theme = 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(
@@ -85,14 +98,11 @@ where
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(
@@ -140,7 +150,7 @@ where
font: Font,
bounds: Size,
shaping: text::Shaping,
- ) -> (f32, f32) {
+ ) -> Size {
self.backend().measure(
content,
size,
@@ -229,14 +239,3 @@ where
})
}
}
-
-#[cfg(feature = "geometry")]
-impl<B, T> crate::geometry::Renderer for Renderer<B, T>
-where
- B: Backend,
-{
- fn draw(&mut self, layers: Vec<crate::Geometry>) {
- self.primitives
- .extend(layers.into_iter().map(crate::Geometry::into));
- }
-}