diff options
Diffstat (limited to 'tiny_skia/src/geometry.rs')
-rw-r--r-- | tiny_skia/src/geometry.rs | 143 |
1 files changed, 91 insertions, 52 deletions
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<Text>, + primitives: Vec<Primitive>, + 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>) -> 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<tiny_skia::Transform>, primitives: Vec<Primitive>, + text: Vec<Text>, } 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<Fill>) { @@ -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<Stroke<'a>>) { @@ -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<Text>) { + fn fill_text(&mut self, text: impl Into<geometry::Text>) { 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, + } } } |