//! Draw and stack layers of graphical primitives. use crate::core::{Rectangle, Transformation}; /// A layer of graphical primitives. /// /// Layers normally dictate a set of primitives that are /// rendered in a specific order. pub trait Layer: Default { /// Creates a new [`Layer`] with the given bounds. fn with_bounds(bounds: Rectangle) -> Self; /// Flushes and settles any pending group of primitives in the [`Layer`]. /// /// This will be called when a [`Layer`] is finished. It allows layers to efficiently /// record primitives together and defer grouping until the end. fn flush(&mut self); /// Resizes the [`Layer`] to the given bounds. fn resize(&mut self, bounds: Rectangle); /// Clears all the layers contents and resets its bounds. fn reset(&mut self); } /// A stack of layers used for drawing. #[derive(Debug)] pub struct Stack { layers: Vec, transformations: Vec, previous: Vec, current: usize, active_count: usize, } impl Stack { /// Creates a new empty [`Stack`]. pub fn new() -> Self { Self { layers: vec![T::default()], transformations: vec![Transformation::IDENTITY], previous: vec![], current: 0, active_count: 1, } } /// Returns a mutable reference to the current [`Layer`] of the [`Stack`], together with /// the current [`Transformation`]. #[inline] pub fn current_mut(&mut self) -> (&mut T, Transformation) { let transformation = self.transformation(); (&mut self.layers[self.current], transformation) } /// Returns the current [`Transformation`] of the [`Stack`]. #[inline] pub fn transformation(&self) -> Transformation { self.transformations.last().copied().unwrap() } /// Pushes a new clipping region in the [`Stack`]; creating a new layer in the /// process. pub fn push_clip(&mut self, bounds: Rectangle) { self.previous.push(self.current); self.current = self.active_count; self.active_count += 1; let bounds = bounds * self.transformation(); if self.current == self.layers.len() { self.layers.push(T::with_bounds(bounds)); } else { self.layers[self.current].resize(bounds); } } /// Pops the current clipping region from the [`Stack`] and restores the previous one. /// /// The current layer will be recorded for drawing. pub fn pop_clip(&mut self) { self.flush(); self.current = self.previous.pop().unwrap(); } /// Pushes a new [`Transformation`] in the [`Stack`]. /// /// Future drawing operations will be affected by this new [`Transformation`] until /// it is popped using [`pop_transformation`]. /// /// [`pop_transformation`]: Self::pop_transformation pub fn push_transformation(&mut self, transformation: Transformation) { self.transformations .push(self.transformation() * transformation); } /// Pops the current [`Transformation`] in the [`Stack`]. pub fn pop_transformation(&mut self) { let _ = self.transformations.pop(); } /// Returns an iterator over mutable references to the layers in the [`Stack`]. pub fn iter_mut(&mut self) -> impl Iterator { self.flush(); self.layers[..self.active_count].iter_mut() } /// Returns an iterator over immutable references to the layers in the [`Stack`]. pub fn iter(&self) -> impl Iterator { self.layers[..self.active_count].iter() } /// Returns the slice of layers in the [`Stack`]. pub fn as_slice(&self) -> &[T] { &self.layers[..self.active_count] } /// Flushes and settles any primitives in the current layer of the [`Stack`]. pub fn flush(&mut self) { self.layers[self.current].flush(); } /// Clears the layers of the [`Stack`], allowing reuse. /// /// This will normally keep layer allocations for future drawing operations. pub fn clear(&mut self) { for layer in self.layers[..self.active_count].iter_mut() { layer.reset(); } self.current = 0; self.active_count = 1; self.previous.clear(); } } impl Default for Stack { fn default() -> Self { Self::new() } }