iced_graphics/
layer.rs

1//! Draw and stack layers of graphical primitives.
2use crate::core::{Rectangle, Transformation};
3
4/// A layer of graphical primitives.
5///
6/// Layers normally dictate a set of primitives that are
7/// rendered in a specific order.
8pub trait Layer: Default {
9    /// Creates a new [`Layer`] with the given bounds.
10    fn with_bounds(bounds: Rectangle) -> Self;
11
12    /// Returns the current bounds of the [`Layer`].
13    fn bounds(&self) -> Rectangle;
14
15    /// Flushes and settles any pending group of primitives in the [`Layer`].
16    ///
17    /// This will be called when a [`Layer`] is finished. It allows layers to efficiently
18    /// record primitives together and defer grouping until the end.
19    fn flush(&mut self);
20
21    /// Resizes the [`Layer`] to the given bounds.
22    fn resize(&mut self, bounds: Rectangle);
23
24    /// Clears all the layers contents and resets its bounds.
25    fn reset(&mut self);
26
27    /// Returns the start level of the [`Layer`].
28    ///
29    /// A level is a "sublayer" index inside of a [`Layer`].
30    ///
31    /// A [`Layer`] may draw multiple primitive types in a certain order.
32    /// The level represents the lowest index of the primitive types it
33    /// contains.
34    ///
35    /// Two layers A and B can therefore be merged if they have the same bounds,
36    /// and the end level of A is lower or equal than the start level of B.
37    fn start(&self) -> usize;
38
39    /// Returns the end level of the [`Layer`].
40    fn end(&self) -> usize;
41
42    /// Merges a [`Layer`] with the current one.
43    fn merge(&mut self, _layer: &mut Self);
44}
45
46/// A stack of layers used for drawing.
47#[derive(Debug)]
48pub struct Stack<T: Layer> {
49    layers: Vec<T>,
50    transformations: Vec<Transformation>,
51    previous: Vec<usize>,
52    current: usize,
53    active_count: usize,
54}
55
56impl<T: Layer> Stack<T> {
57    /// Creates a new empty [`Stack`].
58    pub fn new() -> Self {
59        Self {
60            layers: vec![T::default()],
61            transformations: vec![Transformation::IDENTITY],
62            previous: vec![],
63            current: 0,
64            active_count: 1,
65        }
66    }
67
68    /// Returns a mutable reference to the current [`Layer`] of the [`Stack`], together with
69    /// the current [`Transformation`].
70    #[inline]
71    pub fn current_mut(&mut self) -> (&mut T, Transformation) {
72        let transformation = self.transformation();
73
74        (&mut self.layers[self.current], transformation)
75    }
76
77    /// Returns the current [`Transformation`] of the [`Stack`].
78    #[inline]
79    pub fn transformation(&self) -> Transformation {
80        self.transformations.last().copied().unwrap()
81    }
82
83    /// Pushes a new clipping region in the [`Stack`]; creating a new layer in the
84    /// process.
85    pub fn push_clip(&mut self, bounds: Rectangle) {
86        self.previous.push(self.current);
87
88        self.current = self.active_count;
89        self.active_count += 1;
90
91        let bounds = bounds * self.transformation();
92
93        if self.current == self.layers.len() {
94            self.layers.push(T::with_bounds(bounds));
95        } else {
96            self.layers[self.current].resize(bounds);
97        }
98    }
99
100    /// Pops the current clipping region from the [`Stack`] and restores the previous one.
101    ///
102    /// The current layer will be recorded for drawing.
103    pub fn pop_clip(&mut self) {
104        self.flush();
105
106        self.current = self.previous.pop().unwrap();
107    }
108
109    /// Pushes a new [`Transformation`] in the [`Stack`].
110    ///
111    /// Future drawing operations will be affected by this new [`Transformation`] until
112    /// it is popped using [`pop_transformation`].
113    ///
114    /// [`pop_transformation`]: Self::pop_transformation
115    pub fn push_transformation(&mut self, transformation: Transformation) {
116        self.transformations
117            .push(self.transformation() * transformation);
118    }
119
120    /// Pops the current [`Transformation`] in the [`Stack`].
121    pub fn pop_transformation(&mut self) {
122        let _ = self.transformations.pop();
123    }
124
125    /// Returns an iterator over immutable references to the layers in the [`Stack`].
126    pub fn iter(&self) -> impl Iterator<Item = &T> {
127        self.layers[..self.active_count].iter()
128    }
129
130    /// Returns the slice of layers in the [`Stack`].
131    pub fn as_slice(&self) -> &[T] {
132        &self.layers[..self.active_count]
133    }
134
135    /// Flushes and settles any primitives in the [`Stack`].
136    pub fn flush(&mut self) {
137        self.layers[self.current].flush();
138    }
139
140    /// Performs layer merging wherever possible.
141    ///
142    /// Flushes and settles any primitives in the [`Stack`].
143    pub fn merge(&mut self) {
144        self.flush();
145
146        // These are the layers left to process
147        let mut left = self.active_count;
148
149        // There must be at least 2 or more layers to merge
150        while left > 1 {
151            // We set our target as the topmost layer left to process
152            let mut current = left - 1;
153            let mut target = &self.layers[current];
154            let mut target_start = target.start();
155            let mut target_index = current;
156
157            // We scan downwards for a contiguous block of mergeable layer candidates
158            while current > 0 {
159                let candidate = &self.layers[current - 1];
160                let start = candidate.start();
161                let end = candidate.end();
162
163                // We skip empty layers
164                if end == 0 {
165                    current -= 1;
166                    continue;
167                }
168
169                // Candidate can be merged if primitive sublayers do not overlap with
170                // previous targets and the clipping bounds match
171                if end > target_start || candidate.bounds() != target.bounds() {
172                    break;
173                }
174
175                // Candidate is not empty and can be merged into
176                target = candidate;
177                target_start = start;
178                target_index = current;
179                current -= 1;
180            }
181
182            // We merge all the layers scanned into the target
183            //
184            // Since we use `target_index` instead of `current`, we
185            // deliberately avoid merging into empty layers.
186            //
187            // If no candidates were mergeable, this is a no-op.
188            let (head, tail) = self.layers.split_at_mut(target_index + 1);
189            let layer = &mut head[target_index];
190
191            for middle in &mut tail[0..left - target_index - 1] {
192                layer.merge(middle);
193            }
194
195            // Empty layers found after the target can be skipped
196            left = current;
197        }
198    }
199
200    /// Clears the layers of the [`Stack`], allowing reuse.
201    ///
202    /// It resizes the base layer bounds to the `new_bounds`.
203    ///
204    /// This will normally keep layer allocations for future drawing operations.
205    pub fn reset(&mut self, new_bounds: Rectangle) {
206        for layer in self.layers[..self.active_count].iter_mut() {
207            layer.reset();
208        }
209
210        self.layers[0].resize(new_bounds);
211        self.current = 0;
212        self.active_count = 1;
213        self.previous.clear();
214    }
215}
216
217impl<T: Layer> Default for Stack<T> {
218    fn default() -> Self {
219        Self::new()
220    }
221}