Avoid merging into empty layers in layer::Stack
This commit is contained in:
parent
806500048d
commit
9490d735c5
1 changed files with 25 additions and 8 deletions
|
|
@ -143,39 +143,56 @@ impl<T: Layer> Stack<T> {
|
||||||
pub fn merge(&mut self) {
|
pub fn merge(&mut self) {
|
||||||
self.flush();
|
self.flush();
|
||||||
|
|
||||||
|
// These are the layers left to process
|
||||||
let mut left = self.active_count;
|
let mut left = self.active_count;
|
||||||
|
|
||||||
|
// There must be at least 2 or more layers to merge
|
||||||
while left > 1 {
|
while left > 1 {
|
||||||
|
// We set our target as the topmost layer left to process
|
||||||
let mut current = left - 1;
|
let mut current = left - 1;
|
||||||
let mut last = &self.layers[current];
|
let mut target = &self.layers[current];
|
||||||
let mut last_start = last.start();
|
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 {
|
while current > 0 {
|
||||||
let candidate = &self.layers[current - 1];
|
let candidate = &self.layers[current - 1];
|
||||||
let start = candidate.start();
|
let start = candidate.start();
|
||||||
let end = candidate.end();
|
let end = candidate.end();
|
||||||
|
|
||||||
|
// We skip empty layers
|
||||||
if end == 0 {
|
if end == 0 {
|
||||||
current -= 1;
|
current -= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if end > last_start || candidate.bounds() != last.bounds() {
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
last = candidate;
|
// Candidate is not empty and can be merged into
|
||||||
last_start = start;
|
target = candidate;
|
||||||
|
target_start = start;
|
||||||
|
target_index = current;
|
||||||
current -= 1;
|
current -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (head, tail) = self.layers.split_at_mut(current + 1);
|
// We merge all the layers scanned into the target
|
||||||
let layer = &mut head[current];
|
//
|
||||||
|
// 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 - current - 1] {
|
for middle in &mut tail[0..left - target_index - 1] {
|
||||||
layer.merge(middle);
|
layer.merge(middle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Empty layers found after the target can be skipped
|
||||||
left = current;
|
left = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue