summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/src/backend.rs68
-rw-r--r--tiny_skia/src/primitive.rs82
2 files changed, 67 insertions, 83 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index 58076b84..fe84f83b 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -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 { .. } => {
diff --git a/tiny_skia/src/primitive.rs b/tiny_skia/src/primitive.rs
deleted file mode 100644
index 22daaedc..00000000
--- a/tiny_skia/src/primitive.rs
+++ /dev/null
@@ -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
- }
-}