diff options
Diffstat (limited to 'components')
-rw-r--r-- | components/layout/display_list/builder.rs | 73 | ||||
-rw-r--r-- | components/layout/fragment.rs | 11 | ||||
-rw-r--r-- | components/layout/tests/size_of.rs | 2 |
3 files changed, 67 insertions, 19 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 2539f648964..5d9a738606e 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -576,6 +576,12 @@ pub trait FragmentDisplayListBuilding { state: &mut StackingContextCollectionState, ) -> bool; + fn create_stacking_context_for_inline_block( + &mut self, + base: &BaseFlow, + state: &mut StackingContextCollectionState, + ) -> bool; + /// Adds the display items necessary to paint the background of this fragment to the display /// list if necessary. fn build_display_list_for_background_if_applicable( @@ -816,6 +822,35 @@ impl FragmentDisplayListBuilding for Fragment { } } + fn create_stacking_context_for_inline_block( + &mut self, + base: &BaseFlow, + state: &mut StackingContextCollectionState, + ) -> bool { + self.stacking_context_id = state.allocate_stacking_context_info(StackingContextType::Real); + + let established_reference_frame = if self.can_establish_reference_frame() { + // WebRender currently creates reference frames automatically, so just add + // a placeholder node to allocate a ClipScrollNodeIndex for this reference frame. + self.established_reference_frame = + Some(state.add_clip_scroll_node(ClipScrollNode::placeholder())); + self.established_reference_frame + } else { + None + }; + + let current_stacking_context_id = state.current_stacking_context_id; + let stacking_context = self.create_stacking_context( + self.stacking_context_id, + &base, + StackingContextType::Real, + established_reference_frame, + state.current_clipping_and_scrolling, + ); + state.add_stacking_context(current_stacking_context_id, stacking_context); + true + } + fn build_display_list_for_background_if_applicable( &self, state: &mut DisplayListBuildState, @@ -1562,6 +1597,11 @@ impl FragmentDisplayListBuilding for Fragment { display_list_section: DisplayListSection, clip: Rect<Au>, ) { + let previous_clipping_and_scrolling = state.current_clipping_and_scrolling; + if let Some(index) = self.established_reference_frame { + state.current_clipping_and_scrolling = ClippingAndScrolling::simple(index); + } + self.restyle_damage.remove(ServoRestyleDamage::REPAINT); self.build_display_list_no_damage( state, @@ -1569,7 +1609,9 @@ impl FragmentDisplayListBuilding for Fragment { border_painting_mode, display_list_section, clip, - ) + ); + + state.current_clipping_and_scrolling = previous_clipping_and_scrolling; } fn build_display_list_no_damage( @@ -2861,8 +2903,11 @@ impl InlineFlowDisplayListBuilding for InlineFlow { .cloned() .unwrap_or_else(Rect::max_rect); + let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling; + for fragment in self.fragments.fragments.iter_mut() { - let previous_cb_clipping_and_scrolling = state.containing_block_clipping_and_scrolling; + state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling; + if establishes_containing_block_for_absolute( StackingContextCollectionFlags::empty(), fragment.style.get_box().position, @@ -2871,26 +2916,20 @@ impl InlineFlowDisplayListBuilding for InlineFlow { state.current_clipping_and_scrolling; } - if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) { - if fragment.establishes_stacking_context() { - fragment.stacking_context_id = - state.allocate_stacking_context_info(StackingContextType::Real); - - let current_stacking_context_id = state.current_stacking_context_id; - let stacking_context = fragment.create_stacking_context( - fragment.stacking_context_id, - &self.base, - StackingContextType::Real, - None, - state.current_clipping_and_scrolling, - ); + // We clear this here, but it might be set again if we create a stacking context for + // this fragment. + fragment.established_reference_frame = None; - state.add_stacking_context(current_stacking_context_id, stacking_context); - } else { + if !fragment.collect_stacking_contexts_for_blocklike_fragment(state) { + if !fragment.establishes_stacking_context() { fragment.stacking_context_id = state.current_stacking_context_id; + } else { + fragment.create_stacking_context_for_inline_block(&self.base, state); } } + // Reset the containing block clipping and scrolling before each loop iteration, + // so we don't pollute subsequent fragments. state.containing_block_clipping_and_scrolling = previous_cb_clipping_and_scrolling; } } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 38ea9d03b93..c3b3ce5fb3e 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -11,7 +11,7 @@ use app_units::Au; use canvas_traits::canvas::{CanvasMsg, CanvasId}; use context::{LayoutContext, with_thread_local_font_context}; use display_list::ToLayout; -use display_list::items::{BLUR_INFLATION_FACTOR, OpaqueNode}; +use display_list::items::{BLUR_INFLATION_FACTOR, ClipScrollNodeIndex, OpaqueNode}; use euclid::{Point2D, Vector2D, Rect, Size2D}; use floats::ClearType; use flow::{GetBaseFlow, ImmutableFlowUtils}; @@ -152,6 +152,11 @@ pub struct Fragment { /// to 0, but it assigned during the collect_stacking_contexts phase of display /// list construction. pub stacking_context_id: StackingContextId, + + /// The indices of this Fragment's ClipScrollNode. If this fragment doesn't have a + /// `established_reference_frame` assigned, it will use the `clipping_and_scrolling` of the + /// parent block. + pub established_reference_frame: Option<ClipScrollNodeIndex>, } impl Serialize for Fragment { @@ -633,6 +638,7 @@ impl Fragment { flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::root(), + established_reference_frame: None, } } @@ -662,6 +668,7 @@ impl Fragment { flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::root(), + established_reference_frame: None, } } @@ -687,6 +694,7 @@ impl Fragment { flags: FragmentFlags::empty(), debug_id: DebugId::new(), stacking_context_id: StackingContextId::root(), + established_reference_frame: None, } } @@ -715,6 +723,7 @@ impl Fragment { flags: FragmentFlags::empty(), debug_id: self.debug_id.clone(), stacking_context_id: StackingContextId::root(), + established_reference_frame: None, } } diff --git a/components/layout/tests/size_of.rs b/components/layout/tests/size_of.rs index 54b5ef39830..f12b0049f4b 100644 --- a/components/layout/tests/size_of.rs +++ b/components/layout/tests/size_of.rs @@ -10,5 +10,5 @@ extern crate layout; use layout::Fragment; use layout::SpecificFragmentInfo; -size_of_test!(test_size_of_fragment, Fragment, 160); +size_of_test!(test_size_of_fragment, Fragment, 176); size_of_test!(test_size_of_specific_fragment_info, SpecificFragmentInfo, 24); |