Draft (very) basic incremental rendering for iced_tiny_skia

This commit is contained in:
Héctor Ramón Jiménez 2023-03-22 00:36:57 +01:00
parent 6fae8bf6cb
commit 0f7abffc0e
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
10 changed files with 286 additions and 92 deletions

View file

@ -7,7 +7,7 @@ use bytemuck::{Pod, Zeroable};
use std::sync::Arc;
/// A rendering primitive.
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum Primitive {
/// A text primitive
@ -147,10 +147,153 @@ impl Primitive {
content: Box::new(self),
}
}
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.0)
}
Self::Quad { bounds, .. }
| Self::Image { bounds, .. }
| Self::Svg { bounds, .. }
| 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(),
}
}
pub fn damage(&self, other: &Self) -> Vec<Rectangle> {
match (self, other) {
(
Primitive::Group {
primitives: primitives_a,
},
Primitive::Group {
primitives: primitives_b,
},
) => return Self::damage_list(primitives_a, primitives_b),
(
Primitive::Clip {
bounds: bounds_a,
content: content_a,
},
Primitive::Clip {
bounds: bounds_b,
content: content_b,
},
) => {
if bounds_a == bounds_b {
return content_a.damage(content_b);
} else {
return vec![*bounds_a, *bounds_b];
}
}
(
Primitive::Translate {
translation: translation_a,
content: content_a,
},
Primitive::Translate {
translation: translation_b,
content: content_b,
},
) => {
if translation_a == translation_b {
return content_a.damage(content_b);
}
}
(
Primitive::Cache { content: content_a },
Primitive::Cache { content: content_b },
) => {
if Arc::ptr_eq(content_a, content_b) {
return vec![];
}
}
_ if self == other => return vec![],
_ => {}
}
let bounds_a = self.bounds();
let bounds_b = other.bounds();
if bounds_a == bounds_b {
vec![bounds_a]
} else {
vec![bounds_a, bounds_b]
}
}
pub fn damage_list(previous: &[Self], current: &[Self]) -> Vec<Rectangle> {
let damage =
previous.iter().zip(current).flat_map(|(a, b)| a.damage(b));
if previous.len() == current.len() {
damage.collect()
} else {
let (smaller, bigger) = if previous.len() < current.len() {
(previous, current)
} else {
(current, previous)
};
// Extend damage by the added/removed primitives
damage
.chain(bigger[smaller.len()..].iter().map(Primitive::bounds))
.collect()
}
}
}
/// A set of [`Vertex2D`] and indices representing a list of triangles.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Mesh2D<T> {
/// The vertices of the mesh
pub vertices: Vec<T>,
@ -162,7 +305,7 @@ pub struct Mesh2D<T> {
}
/// A two-dimensional vertex.
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
#[repr(C)]
pub struct Vertex2D {
/// The vertex position in 2D space.
@ -170,7 +313,7 @@ pub struct Vertex2D {
}
/// A two-dimensional vertex with a color.
#[derive(Copy, Clone, Debug, Zeroable, Pod)]
#[derive(Copy, Clone, Debug, PartialEq, Zeroable, Pod)]
#[repr(C)]
pub struct ColoredVertex2D {
/// The vertex position in 2D space.

View file

@ -32,7 +32,7 @@ impl<B: Backend, T> Renderer<B, T> {
}
}
/// Returns the [`Backend`] of the [`Renderer`].
/// Returns a reference to the [`Backend`] of the [`Renderer`].
pub fn backend(&self) -> &B {
&self.backend
}