aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/display_list/builder.rs73
-rw-r--r--components/layout/fragment.rs11
-rw-r--r--components/layout/tests/size_of.rs2
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);