diff options
author | 2020-04-19 21:55:23 +0200 | |
---|---|---|
committer | 2020-04-19 21:55:23 +0200 | |
commit | 592cc685067c36cbba87e4db14f4ebc71d65b951 (patch) | |
tree | fec66717a6558ddfa31a90352724be13e6a2dfd9 /wgpu/src/widget/canvas/cache.rs | |
parent | bb424e54c5083402225a0fdda6130de575592dca (diff) | |
download | iced-592cc685067c36cbba87e4db14f4ebc71d65b951.tar.gz iced-592cc685067c36cbba87e4db14f4ebc71d65b951.tar.bz2 iced-592cc685067c36cbba87e4db14f4ebc71d65b951.zip |
Remove `Layer` trait and simplify `Canvas`
Diffstat (limited to 'wgpu/src/widget/canvas/cache.rs')
-rw-r--r-- | wgpu/src/widget/canvas/cache.rs | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/wgpu/src/widget/canvas/cache.rs b/wgpu/src/widget/canvas/cache.rs new file mode 100644 index 00000000..c88239af --- /dev/null +++ b/wgpu/src/widget/canvas/cache.rs @@ -0,0 +1,110 @@ +use crate::{ + canvas::{Drawable, Frame, Geometry}, + Primitive, +}; + +use iced_native::Size; +use std::{cell::RefCell, sync::Arc}; + +enum State { + Empty, + Filled { + bounds: Size, + primitive: Arc<Primitive>, + }, +} + +impl Default for State { + fn default() -> Self { + State::Empty + } +} +/// A simple cache that stores generated geometry to avoid recomputation. +/// +/// A [`Cache`] will not redraw its geometry unless the dimensions of its layer +/// change or it is explicitly cleared. +/// +/// [`Layer`]: ../trait.Layer.html +/// [`Cache`]: struct.Cache.html +#[derive(Debug, Default)] +pub struct Cache { + state: RefCell<State>, +} + +impl Cache { + /// Creates a new empty [`Cache`]. + /// + /// [`Cache`]: struct.Cache.html + pub fn new() -> Self { + Cache { + state: Default::default(), + } + } + + /// Clears the cache, forcing a redraw the next time it is used. + /// + /// [`Cached`]: struct.Cached.html + pub fn clear(&mut self) { + *self.state.borrow_mut() = State::Empty; + } + + pub fn draw<T>(&self, new_bounds: Size, input: T) -> Geometry + where + T: Drawable + std::fmt::Debug, + { + use std::ops::Deref; + + if let State::Filled { bounds, primitive } = self.state.borrow().deref() + { + if *bounds == new_bounds { + return Geometry::from_primitive(primitive.clone()); + } + } + + let mut frame = Frame::new(new_bounds.width, new_bounds.height); + input.draw(&mut frame); + + let primitive = Arc::new(frame.into_primitive()); + + *self.state.borrow_mut() = State::Filled { + bounds: new_bounds, + primitive: primitive.clone(), + }; + + Geometry::from_primitive(primitive) + } + + pub fn with<'a, T>(&'a self, input: T) -> impl crate::canvas::State + 'a + where + T: Drawable + std::fmt::Debug + 'a, + { + Bind { cache: self, input } + } +} + +struct Bind<'a, T> { + cache: &'a Cache, + input: T, +} + +impl<'a, T> crate::canvas::State for Bind<'a, T> +where + T: Drawable + std::fmt::Debug + 'a, +{ + fn draw(&self, bounds: Size) -> Vec<Geometry> { + vec![self.cache.draw(bounds, &self.input)] + } +} + +impl std::fmt::Debug for State { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + State::Empty => write!(f, "Empty"), + State::Filled { primitive, bounds } => f + .debug_struct("Filled") + .field("primitive", primitive) + .field("bounds", bounds) + .finish(), + } + } +} |