From 3645d34d6a1ba1247238e830e9eefd52d9e5b986 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 21 Mar 2024 22:27:17 +0100 Subject: Implement composable, type-safe renderer fallback --- tiny_skia/src/geometry.rs | 60 +++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 23 deletions(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 16787f89..6b1888d0 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -4,7 +4,7 @@ use crate::core::{ }; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::stroke::{self, Stroke}; -use crate::graphics::geometry::{Path, Style, Text}; +use crate::graphics::geometry::{self, Path, Style, Text}; use crate::graphics::Gradient; use crate::primitive::{self, Primitive}; @@ -25,23 +25,36 @@ impl Frame { } } - pub fn width(&self) -> f32 { + pub fn into_primitive(self) -> Primitive { + Primitive::Clip { + bounds: Rectangle::new(Point::ORIGIN, self.size), + content: Box::new(Primitive::Group { + primitives: self.primitives, + }), + } + } +} + +impl geometry::Frame for Frame { + type Geometry = Primitive; + + fn width(&self) -> f32 { self.size.width } - pub fn height(&self) -> f32 { + fn height(&self) -> f32 { self.size.height } - pub fn size(&self) -> Size { + fn size(&self) -> Size { self.size } - pub fn center(&self) -> Point { + fn center(&self) -> Point { Point::new(self.size.width / 2.0, self.size.height / 2.0) } - pub fn fill(&mut self, path: &Path, fill: impl Into) { + fn fill(&mut self, path: &Path, fill: impl Into) { let Some(path) = convert_path(path).and_then(|path| path.transform(self.transform)) else { @@ -61,7 +74,7 @@ impl Frame { })); } - pub fn fill_rectangle( + fn fill_rectangle( &mut self, top_left: Point, size: Size, @@ -89,7 +102,7 @@ impl Frame { })); } - pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into>) { + fn stroke<'a>(&mut self, path: &Path, stroke: impl Into>) { let Some(path) = convert_path(path).and_then(|path| path.transform(self.transform)) else { @@ -110,7 +123,7 @@ impl Frame { })); } - pub fn fill_text(&mut self, text: impl Into) { + fn fill_text(&mut self, text: impl Into) { let text = text.into(); let (scale_x, scale_y) = self.transform.get_scale(); @@ -174,51 +187,52 @@ impl Frame { } } - pub fn push_transform(&mut self) { + fn push_transform(&mut self) { self.stack.push(self.transform); } - pub fn pop_transform(&mut self) { + fn pop_transform(&mut self) { self.transform = self.stack.pop().expect("Pop transform"); } - pub fn clip(&mut self, frame: Self, at: Point) { + fn draft(&mut self, size: Size) -> Self { + Self::new(size) + } + + fn paste(&mut self, frame: Self, at: Point) { self.primitives.push(Primitive::Transform { transformation: Transformation::translate(at.x, at.y), content: Box::new(frame.into_primitive()), }); } - pub fn translate(&mut self, translation: Vector) { + fn translate(&mut self, translation: Vector) { self.transform = self.transform.pre_translate(translation.x, translation.y); } - pub fn rotate(&mut self, angle: impl Into) { + fn rotate(&mut self, angle: impl Into) { self.transform = self.transform.pre_concat( tiny_skia::Transform::from_rotate(angle.into().0.to_degrees()), ); } - pub fn scale(&mut self, scale: impl Into) { + fn scale(&mut self, scale: impl Into) { let scale = scale.into(); self.scale_nonuniform(Vector { x: scale, y: scale }); } - pub fn scale_nonuniform(&mut self, scale: impl Into) { + fn scale_nonuniform(&mut self, scale: impl Into) { let scale = scale.into(); self.transform = self.transform.pre_scale(scale.x, scale.y); } +} - pub fn into_primitive(self) -> Primitive { - Primitive::Clip { - bounds: Rectangle::new(Point::ORIGIN, self.size), - content: Box::new(Primitive::Group { - primitives: self.primitives, - }), - } +impl From for Primitive { + fn from(frame: Frame) -> Self { + frame.into_primitive() } } -- cgit From 53a183fe0d6aed460fbb8155ac9541757277aab3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 22 Mar 2024 01:35:14 +0100 Subject: Restore `canvas::Frame` API --- tiny_skia/src/geometry.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 6b1888d0..76482e12 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -35,7 +35,7 @@ impl Frame { } } -impl geometry::Frame for Frame { +impl geometry::frame::Backend for Frame { type Geometry = Primitive; fn width(&self) -> f32 { @@ -228,11 +228,9 @@ impl geometry::Frame for Frame { self.transform = self.transform.pre_scale(scale.x, scale.y); } -} -impl From for Primitive { - fn from(frame: Frame) -> Self { - frame.into_primitive() + fn into_geometry(self) -> Self::Geometry { + self.into_primitive() } } -- cgit From 6d3e1d835e1688fbc58622a03a784ed25ed3f0e1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 5 Apr 2024 23:59:21 +0200 Subject: Decouple caching from layering and simplify everything --- tiny_skia/src/geometry.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 76482e12..f1d11dce 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -195,8 +195,8 @@ impl geometry::frame::Backend for Frame { self.transform = self.stack.pop().expect("Pop transform"); } - fn draft(&mut self, size: Size) -> Self { - Self::new(size) + fn draft(&mut self, clip_bounds: Rectangle) -> Self { + Self::new(clip_bounds.size()) } fn paste(&mut self, frame: Self, at: Point) { -- cgit From 5cd98f069dea8720bca7748d6c12fa410cbe79b5 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sun, 7 Apr 2024 12:42:12 +0200 Subject: Use built-in `[lints]` table in `Cargo.toml` --- tiny_skia/src/geometry.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 76482e12..9bc3664d 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -8,6 +8,7 @@ use crate::graphics::geometry::{self, Path, Style, Text}; use crate::graphics::Gradient; use crate::primitive::{self, Primitive}; +#[derive(Debug)] pub struct Frame { size: Size, transform: tiny_skia::Transform, -- cgit From 6ad5bb3597f640ac329801adf735d633bf0a512f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 9 Apr 2024 22:25:16 +0200 Subject: Port `iced_tiny_skia` to new layering architecture --- tiny_skia/src/geometry.rs | 143 +++++++++++++++++++++++++++++----------------- 1 file changed, 91 insertions(+), 52 deletions(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index a9dcb610..04aabf0d 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -1,58 +1,98 @@ use crate::core::text::LineHeight; -use crate::core::{ - Pixels, Point, Radians, Rectangle, Size, Transformation, Vector, -}; +use crate::core::{Pixels, Point, Radians, Rectangle, Size, Vector}; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::stroke::{self, Stroke}; -use crate::graphics::geometry::{self, Path, Style, Text}; -use crate::graphics::Gradient; -use crate::primitive::{self, Primitive}; +use crate::graphics::geometry::{self, Path, Style}; +use crate::graphics::{Cached, Gradient, Text}; +use crate::Primitive; + +use std::rc::Rc; + +#[derive(Debug)] +pub enum Geometry { + Live { + text: Vec, + primitives: Vec, + clip_bounds: Rectangle, + }, + Cache(Cache), +} + +#[derive(Debug, Clone)] +pub struct Cache { + pub text: Rc<[Text]>, + pub primitives: Rc<[Primitive]>, + pub clip_bounds: Rectangle, +} + +impl Cached for Geometry { + type Cache = Cache; + + fn load(cache: &Cache) -> Self { + Self::Cache(cache.clone()) + } + + fn cache(self, _previous: Option) -> Cache { + match self { + Self::Live { + primitives, + text, + clip_bounds, + } => Cache { + primitives: Rc::from(primitives), + text: Rc::from(text), + clip_bounds, + }, + Self::Cache(cache) => cache, + } + } +} #[derive(Debug)] pub struct Frame { - size: Size, + clip_bounds: Rectangle, transform: tiny_skia::Transform, stack: Vec, primitives: Vec, + text: Vec, } impl Frame { pub fn new(size: Size) -> Self { + Self::with_clip(Rectangle::with_size(size)) + } + + pub fn with_clip(clip_bounds: Rectangle) -> Self { Self { - size, - transform: tiny_skia::Transform::identity(), + clip_bounds, stack: Vec::new(), primitives: Vec::new(), - } - } - - pub fn into_primitive(self) -> Primitive { - Primitive::Clip { - bounds: Rectangle::new(Point::ORIGIN, self.size), - content: Box::new(Primitive::Group { - primitives: self.primitives, - }), + text: Vec::new(), + transform: tiny_skia::Transform::from_translate( + clip_bounds.x, + clip_bounds.y, + ), } } } impl geometry::frame::Backend for Frame { - type Geometry = Primitive; + type Geometry = Geometry; fn width(&self) -> f32 { - self.size.width + self.clip_bounds.width } fn height(&self) -> f32 { - self.size.height + self.clip_bounds.height } fn size(&self) -> Size { - self.size + self.clip_bounds.size() } fn center(&self) -> Point { - Point::new(self.size.width / 2.0, self.size.height / 2.0) + Point::new(self.clip_bounds.width / 2.0, self.clip_bounds.height / 2.0) } fn fill(&mut self, path: &Path, fill: impl Into) { @@ -67,12 +107,11 @@ impl geometry::frame::Backend for Frame { let mut paint = into_paint(fill.style); paint.shader.transform(self.transform); - self.primitives - .push(Primitive::Custom(primitive::Custom::Fill { - path, - paint, - rule: into_fill_rule(fill.rule), - })); + self.primitives.push(Primitive::Fill { + path, + paint, + rule: into_fill_rule(fill.rule), + }); } fn fill_rectangle( @@ -95,12 +134,11 @@ impl geometry::frame::Backend for Frame { }; paint.shader.transform(self.transform); - self.primitives - .push(Primitive::Custom(primitive::Custom::Fill { - path, - paint, - rule: into_fill_rule(fill.rule), - })); + self.primitives.push(Primitive::Fill { + path, + paint, + rule: into_fill_rule(fill.rule), + }); } fn stroke<'a>(&mut self, path: &Path, stroke: impl Into>) { @@ -116,15 +154,14 @@ impl geometry::frame::Backend for Frame { let mut paint = into_paint(stroke.style); paint.shader.transform(self.transform); - self.primitives - .push(Primitive::Custom(primitive::Custom::Stroke { - path, - paint, - stroke: skia_stroke, - })); + self.primitives.push(Primitive::Stroke { + path, + paint, + stroke: skia_stroke, + }); } - fn fill_text(&mut self, text: impl Into) { + fn fill_text(&mut self, text: impl Into) { let text = text.into(); let (scale_x, scale_y) = self.transform.get_scale(); @@ -171,12 +208,12 @@ impl geometry::frame::Backend for Frame { }; // TODO: Honor layering! - self.primitives.push(Primitive::Text { + self.text.push(Text::Cached { content: text.content, bounds, color: text.color, size, - line_height, + line_height: line_height.to_absolute(size), font: text.font, horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, @@ -197,14 +234,12 @@ impl geometry::frame::Backend for Frame { } fn draft(&mut self, clip_bounds: Rectangle) -> Self { - Self::new(clip_bounds.size()) + Self::with_clip(clip_bounds) } - fn paste(&mut self, frame: Self, at: Point) { - self.primitives.push(Primitive::Transform { - transformation: Transformation::translate(at.x, at.y), - content: Box::new(frame.into_primitive()), - }); + fn paste(&mut self, frame: Self, _at: Point) { + self.primitives.extend(frame.primitives); + self.text.extend(frame.text); } fn translate(&mut self, translation: Vector) { @@ -230,8 +265,12 @@ impl geometry::frame::Backend for Frame { self.transform = self.transform.pre_scale(scale.x, scale.y); } - fn into_geometry(self) -> Self::Geometry { - self.into_primitive() + fn into_geometry(self) -> Geometry { + Geometry::Live { + primitives: self.primitives, + text: self.text, + clip_bounds: self.clip_bounds, + } } } -- cgit From 1e802e776cb591f3860d1bfbaa1423d356fc8456 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 10 Apr 2024 15:21:42 +0200 Subject: Reintroduce damage tracking for `iced_tiny_skia` --- tiny_skia/src/geometry.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 04aabf0d..117daf41 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -166,7 +166,7 @@ impl geometry::frame::Backend for Frame { let (scale_x, scale_y) = self.transform.get_scale(); - if self.transform.is_scale_translate() + if !self.transform.has_skew() && scale_x == scale_y && scale_x > 0.0 && scale_y > 0.0 -- cgit From b5b78d505e22cafccb4ecbf57dc61f536ca558ca Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 Apr 2024 07:57:54 +0200 Subject: Introduce `canvas::Cache` grouping Caches with the same `Group` will share their text atlas! --- tiny_skia/src/geometry.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src/geometry.rs') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 117daf41..02b6e1b9 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -1,9 +1,10 @@ use crate::core::text::LineHeight; use crate::core::{Pixels, Point, Radians, Rectangle, Size, Vector}; +use crate::graphics::cache::{self, Cached}; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::stroke::{self, Stroke}; use crate::graphics::geometry::{self, Path, Style}; -use crate::graphics::{Cached, Gradient, Text}; +use crate::graphics::{Gradient, Text}; use crate::Primitive; use std::rc::Rc; @@ -32,7 +33,7 @@ impl Cached for Geometry { Self::Cache(cache.clone()) } - fn cache(self, _previous: Option) -> Cache { + fn cache(self, _group: cache::Group, _previous: Option) -> Cache { match self { Self::Live { primitives, -- cgit