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)] | 
