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

@ -17,6 +17,9 @@ pub struct Backend {
#[cfg(feature = "svg")]
vector_pipeline: crate::vector::Pipeline,
last_primitives: Vec<Primitive>,
last_background_color: Color,
}
impl Backend {
@ -31,6 +34,9 @@ impl Backend {
#[cfg(feature = "svg")]
vector_pipeline: crate::vector::Pipeline::new(),
last_primitives: Vec::new(),
last_background_color: Color::BLACK,
}
}
@ -43,10 +49,48 @@ impl Backend {
background_color: Color,
overlay: &[T],
) {
pixels.fill(into_color(background_color));
let damage = if self.last_background_color == background_color {
Primitive::damage_list(&self.last_primitives, primitives)
} else {
vec![Rectangle::with_size(viewport.logical_size())]
};
if damage.is_empty() {
return;
}
self.last_primitives = primitives.to_vec();
self.last_background_color = background_color;
let scale_factor = viewport.scale_factor() as f32;
dbg!(&damage);
for region in &damage {
let region = *region * scale_factor;
pixels.fill_path(
&tiny_skia::PathBuilder::from_rect(
tiny_skia::Rect::from_xywh(
region.x,
region.y,
region.width.min(viewport.physical_width() as f32),
region.height.min(viewport.physical_height() as f32),
)
.expect("Create damage rectangle"),
),
&tiny_skia::Paint {
shader: tiny_skia::Shader::SolidColor(into_color(
background_color,
)),
..Default::default()
},
tiny_skia::FillRule::default(),
tiny_skia::Transform::identity(),
None,
);
}
for primitive in primitives {
self.draw_primitive(
primitive,
@ -55,6 +99,7 @@ impl Backend {
None,
scale_factor,
Vector::ZERO,
&damage,
);
}
@ -81,6 +126,7 @@ impl Backend {
None,
scale_factor,
Vector::ZERO,
&[],
);
}
@ -101,6 +147,7 @@ impl Backend {
clip_bounds: Option<Rectangle>,
scale_factor: f32,
translation: Vector,
damage: &[Rectangle],
) {
match primitive {
Primitive::Quad {
@ -110,6 +157,10 @@ impl Backend {
border_width,
border_color,
} => {
if !damage.iter().any(|damage| damage.intersects(bounds)) {
return;
}
let transform = tiny_skia::Transform::from_translate(
translation.x,
translation.y,
@ -165,6 +216,13 @@ impl Backend {
horizontal_alignment,
vertical_alignment,
} => {
if !damage
.iter()
.any(|damage| damage.intersects(&primitive.bounds()))
{
return;
}
self.text_pipeline.draw(
content,
(*bounds + translation) * scale_factor,
@ -179,6 +237,10 @@ impl Backend {
}
#[cfg(feature = "image")]
Primitive::Image { handle, bounds } => {
if !damage.iter().any(|damage| damage.intersects(bounds)) {
return;
}
let transform = tiny_skia::Transform::from_translate(
translation.x,
translation.y,
@ -248,6 +310,7 @@ impl Backend {
clip_bounds,
scale_factor,
translation,
damage,
);
}
}
@ -262,6 +325,7 @@ impl Backend {
clip_bounds,
scale_factor,
translation + *offset,
damage,
);
}
Primitive::Clip { bounds, content } => {
@ -284,6 +348,7 @@ impl Backend {
Some(bounds),
scale_factor,
translation,
damage,
);
if let Some(bounds) = clip_bounds {
@ -300,6 +365,7 @@ impl Backend {
clip_bounds,
scale_factor,
translation,
damage,
);
}
Primitive::SolidMesh { .. } | Primitive::GradientMesh { .. } => {

View file

@ -1,82 +0,0 @@
use crate::{Rectangle, Vector};
use std::sync::Arc;
#[derive(Debug, Clone)]
pub enum Primitive {
/// A group of primitives
Group {
/// The primitives of the group
primitives: Vec<Primitive>,
},
/// A clip primitive
Clip {
/// The bounds of the clip
bounds: Rectangle,
/// The content of the clip
content: Box<Primitive>,
},
/// A primitive that applies a translation
Translate {
/// The translation vector
translation: Vector,
/// The primitive to translate
content: Box<Primitive>,
},
/// A cached primitive.
///
/// This can be useful if you are implementing a widget where primitive
/// generation is expensive.
Cached {
/// The cached primitive
cache: Arc<Primitive>,
},
/// A basic primitive.
Basic(iced_graphics::Primitive),
}
impl iced_graphics::backend::Primitive for Primitive {
fn translate(self, translation: Vector) -> Self {
Self::Translate {
translation,
content: Box::new(self),
}
}
fn clip(self, bounds: Rectangle) -> Self {
Self::Clip {
bounds,
content: Box::new(self),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct Recording(pub(crate) Vec<Primitive>);
impl iced_graphics::backend::Recording for Recording {
type Primitive = Primitive;
fn push(&mut self, primitive: Primitive) {
self.0.push(primitive);
}
fn push_basic(&mut self, basic: iced_graphics::Primitive) {
self.0.push(Primitive::Basic(basic));
}
fn group(self) -> Self::Primitive {
Primitive::Group { primitives: self.0 }
}
fn clear(&mut self) {
self.0.clear();
}
}
impl Recording {
pub fn primitives(&self) -> &[Primitive] {
&self.0
}
}