Port iced_tiny_skia to new layering architecture
This commit is contained in:
parent
2c6fd9ac14
commit
6ad5bb3597
28 changed files with 1948 additions and 1935 deletions
139
graphics/src/layer.rs
Normal file
139
graphics/src/layer.rs
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
//! 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<T: Layer> {
|
||||
layers: Vec<T>,
|
||||
transformations: Vec<Transformation>,
|
||||
previous: Vec<usize>,
|
||||
current: usize,
|
||||
active_count: usize,
|
||||
}
|
||||
|
||||
impl<T: Layer> Stack<T> {
|
||||
/// 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<Item = &mut T> {
|
||||
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<Item = &T> {
|
||||
self.layers[..self.active_count].iter()
|
||||
}
|
||||
|
||||
/// 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<T: Layer> Default for Stack<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue