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