diff options
author | 2024-04-05 23:59:21 +0200 | |
---|---|---|
committer | 2024-04-05 23:59:21 +0200 | |
commit | 6d3e1d835e1688fbc58622a03a784ed25ed3f0e1 (patch) | |
tree | b1a14b0ec7b2da4368d5c98850fe9e9eebc5490a /wgpu/src/geometry.rs | |
parent | 4a356cfc16f3b45d64826732009d9feeac016b28 (diff) | |
download | iced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.tar.gz iced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.tar.bz2 iced-6d3e1d835e1688fbc58622a03a784ed25ed3f0e1.zip |
Decouple caching from layering and simplify everything
Diffstat (limited to 'wgpu/src/geometry.rs')
-rw-r--r-- | wgpu/src/geometry.rs | 188 |
1 files changed, 80 insertions, 108 deletions
diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 611e81f1..c8c350c5 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -6,40 +6,44 @@ use crate::core::{ use crate::graphics::color; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::{ - self, LineCap, LineDash, LineJoin, Path, Stroke, Style, Text, + self, LineCap, LineDash, LineJoin, Path, Stroke, Style, }; use crate::graphics::gradient::{self, Gradient}; use crate::graphics::mesh::{self, Mesh}; -use crate::graphics::{self, Cached}; -use crate::layer; +use crate::graphics::{self, Cached, Text}; use crate::text; +use crate::triangle; use lyon::geom::euclid; use lyon::tessellation; use std::borrow::Cow; -use std::cell::RefCell; -use std::rc::Rc; /// A frame for drawing some geometry. #[allow(missing_debug_implementations)] pub struct Frame { - size: Size, + clip_bounds: Rectangle, buffers: BufferStack, - layers: Vec<layer::Live>, - text: text::Batch, + meshes: Vec<Mesh>, + text: Vec<Text>, transforms: Transforms, fill_tessellator: tessellation::FillTessellator, stroke_tessellator: tessellation::StrokeTessellator, } pub enum Geometry { - Live(Vec<layer::Live>), - Cached(Rc<[Rc<RefCell<layer::Cached>>]>), + Live { meshes: Vec<Mesh>, text: Vec<Text> }, + Cached(Cache), +} + +#[derive(Clone)] +pub struct Cache { + pub meshes: triangle::Cache, + pub text: text::Cache, } impl Cached for Geometry { - type Cache = Rc<[Rc<RefCell<layer::Cached>>]>; + type Cache = Cache; fn load(cache: &Self::Cache) -> Self { Geometry::Cached(cache.clone()) @@ -47,31 +51,18 @@ impl Cached for Geometry { fn cache(self, previous: Option<Self::Cache>) -> Self::Cache { match self { - Self::Live(live) => { - let mut layers = live.into_iter(); - - let mut new: Vec<_> = previous - .map(|previous| { - previous - .iter() - .cloned() - .zip(layers.by_ref()) - .map(|(cached, live)| { - cached.borrow_mut().update(live); - cached - }) - .collect() - }) - .unwrap_or_default(); - - new.extend( - layers - .map(layer::Live::into_cached) - .map(RefCell::new) - .map(Rc::new), - ); - - Rc::from(new) + Self::Live { meshes, text } => { + if let Some(mut previous) = previous { + previous.meshes.update(meshes); + previous.text.update(text); + + previous + } else { + Cache { + meshes: triangle::Cache::new(meshes), + text: text::Cache::new(text), + } + } } Self::Cached(cache) => cache, } @@ -81,69 +72,26 @@ impl Cached for Geometry { impl Frame { /// Creates a new [`Frame`] with the given [`Size`]. pub fn new(size: Size) -> Frame { + Self::with_clip(Rectangle::with_size(size)) + } + + /// Creates a new [`Frame`] with the given clip bounds. + pub fn with_clip(bounds: Rectangle) -> Frame { Frame { - size, + clip_bounds: bounds, buffers: BufferStack::new(), - layers: Vec::new(), - text: text::Batch::new(), + meshes: Vec::new(), + text: Vec::new(), transforms: Transforms { previous: Vec::new(), - current: Transform(lyon::math::Transform::identity()), + current: Transform(lyon::math::Transform::translation( + bounds.x, bounds.y, + )), }, fill_tessellator: tessellation::FillTessellator::new(), stroke_tessellator: tessellation::StrokeTessellator::new(), } } - - fn into_layers(mut self) -> Vec<layer::Live> { - if !self.text.is_empty() || !self.buffers.stack.is_empty() { - let clip_bounds = Rectangle::with_size(self.size); - let transformation = Transformation::IDENTITY; - - // TODO: Generate different meshes for different transformations (?) - // Instead of transforming each path - let meshes = self - .buffers - .stack - .into_iter() - .filter_map(|buffer| match buffer { - Buffer::Solid(buffer) if !buffer.indices.is_empty() => { - Some(Mesh::Solid { - buffers: mesh::Indexed { - vertices: buffer.vertices, - indices: buffer.indices, - }, - transformation: Transformation::IDENTITY, - size: self.size, - }) - } - Buffer::Gradient(buffer) if !buffer.indices.is_empty() => { - Some(Mesh::Gradient { - buffers: mesh::Indexed { - vertices: buffer.vertices, - indices: buffer.indices, - }, - transformation: Transformation::IDENTITY, - size: self.size, - }) - } - _ => None, - }) - .collect(); - - let layer = layer::Live { - bounds: Some(clip_bounds), - transformation, - meshes, - text: self.text, - ..layer::Live::default() - }; - - self.layers.push(layer); - } - - self.layers - } } impl geometry::frame::Backend for Frame { @@ -151,22 +99,22 @@ impl geometry::frame::Backend for Frame { #[inline] fn width(&self) -> f32 { - self.size.width + self.clip_bounds.width } #[inline] fn height(&self) -> f32 { - self.size.height + self.clip_bounds.height } #[inline] fn size(&self) -> Size { - self.size + self.clip_bounds.size() } #[inline] 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>) { @@ -269,7 +217,7 @@ impl geometry::frame::Backend for Frame { .expect("Stroke path"); } - 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.transforms.current.scale(); @@ -312,12 +260,12 @@ impl geometry::frame::Backend for Frame { 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, shaping: text.shaping, - clip_bounds: Rectangle::with_size(Size::INFINITY), + clip_bounds: self.clip_bounds, }); } else { text.draw_with(|path, color| self.fill(&path, color)); @@ -368,22 +316,25 @@ impl geometry::frame::Backend for Frame { self.transforms.current = self.transforms.previous.pop().unwrap(); } - fn draft(&mut self, size: Size) -> Frame { - Frame::new(size) + fn draft(&mut self, clip_bounds: Rectangle) -> Frame { + Frame::with_clip(clip_bounds) } - fn paste(&mut self, frame: Frame, at: Point) { - let translation = Transformation::translate(at.x, at.y); + fn paste(&mut self, frame: Frame, _at: Point) { + self.meshes + .extend(frame.buffers.into_meshes(frame.clip_bounds)); - self.layers - .extend(frame.into_layers().into_iter().map(|mut layer| { - layer.transformation = layer.transformation * translation; - layer - })); + self.text.extend(frame.text); } - fn into_geometry(self) -> Self::Geometry { - Geometry::Live(self.into_layers()) + fn into_geometry(mut self) -> Self::Geometry { + self.meshes + .extend(self.buffers.into_meshes(self.clip_bounds)); + + Geometry::Live { + meshes: self.meshes, + text: self.text, + } } } @@ -469,6 +420,27 @@ impl BufferStack { _ => unreachable!(), } } + + fn into_meshes(self, clip_bounds: Rectangle) -> impl Iterator<Item = Mesh> { + self.stack.into_iter().map(move |buffer| match buffer { + Buffer::Solid(buffer) => Mesh::Solid { + buffers: mesh::Indexed { + vertices: buffer.vertices, + indices: buffer.indices, + }, + clip_bounds, + transformation: Transformation::IDENTITY, + }, + Buffer::Gradient(buffer) => Mesh::Gradient { + buffers: mesh::Indexed { + vertices: buffer.vertices, + indices: buffer.indices, + }, + clip_bounds, + transformation: Transformation::IDENTITY, + }, + }) + } } #[derive(Debug)] |