From 87cd668a338f80cf98279734fd9c928636b70972 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Mon, 30 Aug 2021 17:15:09 +0200 Subject: [PATCH] Replace foreground layers with stacking contexts Co-Authored-By: Nathan Sobo --- gpui/src/elements/overlay.rs | 4 +- gpui/src/scene.rs | 91 ++++++++++++++++++++++++------------ 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/gpui/src/elements/overlay.rs b/gpui/src/elements/overlay.rs index 25d3a8d3daf5bf242970da033bf3a2bf7ec766b1..a4c44a00130ef94f1041fc255bfdce24e54958fb 100644 --- a/gpui/src/elements/overlay.rs +++ b/gpui/src/elements/overlay.rs @@ -29,9 +29,9 @@ impl Element for Overlay { fn paint(&mut self, bounds: RectF, size: &mut Self::LayoutState, cx: &mut PaintContext) { let bounds = RectF::new(bounds.origin(), *size); - cx.scene.push_foreground_layer(Some(bounds)); + cx.scene.push_stacking_context(None); self.child.paint(bounds.origin(), cx); - cx.scene.pop_layer(); + cx.scene.pop_stacking_context(); } fn dispatch_event( diff --git a/gpui/src/scene.rs b/gpui/src/scene.rs index d974db73e193d80fb223bd5c4ba51c06ffda9012..4edf58c40f95ab9f0896770e07bb32056280d074 100644 --- a/gpui/src/scene.rs +++ b/gpui/src/scene.rs @@ -11,10 +11,13 @@ use crate::{ pub struct Scene { scale_factor: f32, + stacking_contexts: Vec, + active_stacking_context_stack: Vec, +} + +struct StackingContext { layers: Vec, - foreground_layers: Vec, - active_layer_stack: Vec<(usize, bool)>, - pending_foreground_layers: usize, + active_layer_stack: Vec, } #[derive(Default)] @@ -122,12 +125,11 @@ pub struct PathVertex { impl Scene { pub fn new(scale_factor: f32) -> Self { + let stacking_context = StackingContext::new(None); Scene { scale_factor, - layers: vec![Layer::new(None)], - foreground_layers: Default::default(), - active_layer_stack: vec![(0, false)], - pending_foreground_layers: 0, + stacking_contexts: vec![stacking_context], + active_stacking_context_stack: vec![0], } } @@ -136,31 +138,27 @@ impl Scene { } pub fn layers(&self) -> impl Iterator { - self.layers.iter().chain(self.foreground_layers.iter()) + self.stacking_contexts.iter().flat_map(|s| &s.layers) } - pub fn push_layer(&mut self, clip_bounds: Option) { - if self.pending_foreground_layers == 0 { - let ix = self.layers.len(); - self.layers.push(Layer::new(clip_bounds)); - self.active_layer_stack.push((ix, false)); - } else { - let ix = self.foreground_layers.len(); - self.foreground_layers.push(Layer::new(clip_bounds)); - self.active_layer_stack.push((ix, true)); - } + pub fn push_stacking_context(&mut self, clip_bounds: Option) { + self.active_stacking_context_stack + .push(self.stacking_contexts.len()); + self.stacking_contexts + .push(StackingContext::new(clip_bounds)) + } + + pub fn pop_stacking_context(&mut self) { + self.active_stacking_context_stack.pop(); + assert!(!self.active_stacking_context_stack.is_empty()); } - pub fn push_foreground_layer(&mut self, clip_bounds: Option) { - self.pending_foreground_layers += 1; - self.push_layer(clip_bounds); + pub fn push_layer(&mut self, clip_bounds: Option) { + self.active_stacking_context().push_layer(clip_bounds); } pub fn pop_layer(&mut self) { - let (_, foreground) = self.active_layer_stack.pop().unwrap(); - if foreground { - self.pending_foreground_layers -= 1; - } + self.active_stacking_context().pop_layer(); } pub fn push_quad(&mut self, quad: Quad) { @@ -183,14 +181,47 @@ impl Scene { self.active_layer().push_path(path); } + fn active_stacking_context(&mut self) -> &mut StackingContext { + let ix = *self.active_stacking_context_stack.last().unwrap(); + &mut self.stacking_contexts[ix] + } + fn active_layer(&mut self) -> &mut Layer { - let (ix, foreground) = *self.active_layer_stack.last().unwrap(); - if foreground { - &mut self.foreground_layers[ix] - } else { - &mut self.layers[ix] + self.active_stacking_context().active_layer() + } +} + +impl StackingContext { + fn new(clip_bounds: Option) -> Self { + Self { + layers: vec![Layer::new(clip_bounds)], + active_layer_stack: vec![0], } } + + fn active_layer(&mut self) -> &mut Layer { + &mut self.layers[*self.active_layer_stack.last().unwrap()] + } + + fn push_layer(&mut self, clip_bounds: Option) { + let clip_bounds = clip_bounds.map(|clip_bounds| { + clip_bounds + .intersection(self.active_layer().clip_bounds.unwrap_or(clip_bounds)) + .unwrap_or_else(|| { + log::warn!("specified clip bounds are disjoint from parent layer"); + RectF::default() + }) + }); + + let ix = self.layers.len(); + self.layers.push(Layer::new(clip_bounds)); + self.active_layer_stack.push(ix); + } + + fn pop_layer(&mut self) { + self.active_layer_stack.pop().unwrap(); + assert!(!self.active_layer_stack.is_empty()); + } } impl Layer {