summaryrefslogtreecommitdiffstats
path: root/wgpu/src/widget/canvas/cache.rs
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-04-19 21:55:23 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-04-19 21:55:23 +0200
commit592cc685067c36cbba87e4db14f4ebc71d65b951 (patch)
treefec66717a6558ddfa31a90352724be13e6a2dfd9 /wgpu/src/widget/canvas/cache.rs
parentbb424e54c5083402225a0fdda6130de575592dca (diff)
downloadiced-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.rs110
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(),
+ }
+ }
+}