From 9490d735c531ee128484d6a0ffd11f1aef6be29b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Tue, 19 Aug 2025 08:06:25 +0200 Subject: [PATCH] Avoid merging into empty layers in `layer::Stack` --- graphics/src/layer.rs | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs index bd14718c..31cfe68a 100644 --- a/graphics/src/layer.rs +++ b/graphics/src/layer.rs @@ -143,39 +143,56 @@ impl 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 last = &self.layers[current]; - let mut last_start = last.start(); + 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; } - 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; } - last = candidate; - last_start = start; + // Candidate is not empty and can be merged into + target = candidate; + target_start = start; + target_index = current; current -= 1; } - let (head, tail) = self.layers.split_at_mut(current + 1); - let layer = &mut head[current]; + // 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 - current - 1] { + for middle in &mut tail[0..left - target_index - 1] { layer.merge(middle); } + // Empty layers found after the target can be skipped left = current; } }