aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2018-06-05 04:16:56 -0400
committerGitHub <noreply@github.com>2018-06-05 04:16:56 -0400
commita07c71889524f947fb39bcb65baf135bd2a04d0d (patch)
tree44acf0acd09c25b484c36ab4bf27b3047aea3b8e /components/layout
parenteb1dfd07756f690dfbebae2e53447bc747c5763a (diff)
parent32f00ef821c895ada5eb5cf7c291d5a0a220eb58 (diff)
downloadservo-a07c71889524f947fb39bcb65baf135bd2a04d0d.tar.gz
servo-a07c71889524f947fb39bcb65baf135bd2a04d0d.zip
Auto merge of #20767 - mrobinson:use-reference-frame-for-fixed-position, r=gw3583
Use reference frames explicitly for fixed positioning <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes because they should not change behavior. - [ ] These changes do not require tests because _____ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20767) <!-- Reviewable:end -->
Diffstat (limited to 'components/layout')
-rw-r--r--components/layout/display_list/builder.rs123
-rw-r--r--components/layout/display_list/items.rs56
-rw-r--r--components/layout/display_list/webrender_helpers.rs25
-rw-r--r--components/layout/fragment.rs6
4 files changed, 160 insertions, 50 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs
index a3a40a98cc0..b5c252cc64e 100644
--- a/components/layout/display_list/builder.rs
+++ b/components/layout/display_list/builder.rs
@@ -192,12 +192,16 @@ pub struct StackingContextCollectionState {
/// recursively building and processing the display list.
pub current_stacking_context_id: StackingContextId,
- /// The current stacking real context id, which doesn't include pseudo-stacking contexts.
+ /// The current reference frame ClipScrollNodeIndex.
pub current_real_stacking_context_id: StackingContextId,
/// The next stacking context id that we will assign to a stacking context.
pub next_stacking_context_id: StackingContextId,
+ /// The current reference frame id. This is used to assign items to the parent
+ /// reference frame when we encounter a fixed position stacking context.
+ pub current_parent_reference_frame_id: ClipScrollNodeIndex,
+
/// The current clip and scroll info, used to keep track of state when
/// recursively building and processing the display list.
pub current_clipping_and_scrolling: ClippingAndScrolling,
@@ -221,19 +225,8 @@ pub struct StackingContextCollectionState {
impl StackingContextCollectionState {
pub fn new(pipeline_id: PipelineId) -> StackingContextCollectionState {
- let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
-
- // This is just a dummy node to take up a slot in the array. WebRender
- // takes care of adding this root node and it can be ignored during DL conversion.
- let root_node = ClipScrollNode {
- parent_index: ClipScrollNodeIndex(0),
- clip: ClippingRegion::from_rect(LayoutRect::zero()),
- content_rect: LayoutRect::zero(),
- node_type: ClipScrollNodeType::ScrollFrame(
- ScrollSensitivity::ScriptAndInputEvents,
- pipeline_id.root_scroll_id(),
- ),
- };
+ let root_clip_indices =
+ ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node());
let mut stacking_context_info = FnvHashMap::default();
stacking_context_info.insert(
@@ -241,14 +234,22 @@ impl StackingContextCollectionState {
StackingContextInfo::new(StackingContextId::root()),
);
+ // We add two empty nodes to represent the WebRender root reference frame and
+ // root scroll nodes. WebRender adds these automatically and we add them here
+ // so that the ids in the array match up with the ones we assign during display
+ // list building. We ignore these two nodes during conversion to WebRender
+ // display lists.
+ let clip_scroll_nodes = vec![ClipScrollNode::placeholder(), ClipScrollNode::placeholder()];
+
StackingContextCollectionState {
pipeline_id: pipeline_id,
root_stacking_context: StackingContext::root(),
stacking_context_info,
- clip_scroll_nodes: vec![root_node],
+ clip_scroll_nodes,
current_stacking_context_id: StackingContextId::root(),
current_real_stacking_context_id: StackingContextId::root(),
next_stacking_context_id: StackingContextId::root().next(),
+ current_parent_reference_frame_id: ClipScrollNodeIndex::root_reference_frame(),
current_clipping_and_scrolling: root_clip_indices,
containing_block_clipping_and_scrolling: root_clip_indices,
clip_stack: Vec::new(),
@@ -291,17 +292,27 @@ impl StackingContextCollectionState {
}
fn add_clip_scroll_node(&mut self, clip_scroll_node: ClipScrollNode) -> ClipScrollNodeIndex {
- // We want the scroll root to be defined before any possible item that could use it,
- // so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
- // stacking context. This ensures that item reordering will not result in an item using
- // the scroll root before it is defined.
+ let is_placeholder = clip_scroll_node.is_placeholder();
+
self.clip_scroll_nodes.push(clip_scroll_node);
- let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
- self.stacking_context_info
- .get_mut(&self.current_real_stacking_context_id)
- .unwrap()
- .clip_scroll_nodes
- .push(index);
+ let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
+
+ // If this node is a placeholder node (currently just reference frames), then don't add
+ // it to the stacking context list. Placeholder nodes are created automatically by
+ // WebRender and we don't want to explicitly create them in the display list. The node
+ // is just there to take up a spot in the global list of ClipScrollNodes.
+ if !is_placeholder {
+ // We want the scroll root to be defined before any possible item that could use it,
+ // so we make sure that it is added to the beginning of the parent "real" (non-pseudo)
+ // stacking context. This ensures that item reordering will not result in an item using
+ // the scroll root before it is defined.
+ self.stacking_context_info
+ .get_mut(&self.current_real_stacking_context_id)
+ .unwrap()
+ .clip_scroll_nodes
+ .push(index);
+ }
+
index
}
}
@@ -347,7 +358,6 @@ impl<'a> DisplayListBuildState<'a> {
layout_context: &'a LayoutContext,
state: StackingContextCollectionState,
) -> DisplayListBuildState<'a> {
- let root_clip_indices = ClippingAndScrolling::simple(ClipScrollNodeIndex(0));
DisplayListBuildState {
layout_context: layout_context,
root_stacking_context: state.root_stacking_context,
@@ -356,7 +366,8 @@ impl<'a> DisplayListBuildState<'a> {
clip_scroll_nodes: state.clip_scroll_nodes,
processing_scrolling_overflow_element: false,
current_stacking_context_id: StackingContextId::root(),
- current_clipping_and_scrolling: root_clip_indices,
+ current_clipping_and_scrolling:
+ ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
iframe_sizes: Vec::new(),
indexable_text: IndexableText::default(),
}
@@ -374,7 +385,7 @@ impl<'a> DisplayListBuildState<'a> {
return index;
}
- self.clip_scroll_nodes[index.0].parent_index
+ self.clip_scroll_nodes[index.to_index()].parent_index
}
fn is_background_or_border_of_clip_scroll_node(&self, section: DisplayListSection) -> bool {
@@ -429,7 +440,7 @@ impl<'a> DisplayListBuildState<'a> {
// stacking context. This ensures that item reordering will not result in an item using
// the scroll root before it is defined.
self.clip_scroll_nodes.push(node);
- let index = ClipScrollNodeIndex(self.clip_scroll_nodes.len() - 1);
+ let index = ClipScrollNodeIndex::new(self.clip_scroll_nodes.len() - 1);
let real_stacking_context_id =
self.stacking_context_info[&self.current_stacking_context_id].real_stacking_context_id;
self.stacking_context_info
@@ -751,6 +762,7 @@ pub trait FragmentDisplayListBuilding {
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
context_type: StackingContextType,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
parent_clipping_and_scrolling: ClippingAndScrolling,
) -> StackingContext;
@@ -1873,6 +1885,7 @@ impl FragmentDisplayListBuilding for Fragment {
base_flow: &BaseFlow,
scroll_policy: ScrollPolicy,
context_type: StackingContextType,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
parent_clipping_and_scrolling: ClippingAndScrolling,
) -> StackingContext {
let border_box = self.stacking_relative_border_box(
@@ -1916,6 +1929,7 @@ impl FragmentDisplayListBuilding for Fragment {
self.perspective_matrix(&border_box),
scroll_policy,
parent_clipping_and_scrolling,
+ established_reference_frame,
)
}
@@ -2135,6 +2149,7 @@ pub trait BlockFlowDisplayListBuilding {
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_context_type: Option<StackingContextType>,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
flags: StackingContextCollectionFlags,
) -> ClippingAndScrolling;
fn setup_clip_scroll_node_for_position(
@@ -2164,6 +2179,7 @@ pub trait BlockFlowDisplayListBuilding {
&mut self,
parent_stacking_context_id: StackingContextId,
parent_clipping_and_scrolling: ClippingAndScrolling,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
state: &mut StackingContextCollectionState,
);
fn build_display_list_for_block(
@@ -2187,6 +2203,8 @@ pub trait BlockFlowDisplayListBuilding {
&self,
flags: StackingContextCollectionFlags,
) -> Option<StackingContextType>;
+
+ fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool;
}
/// This structure manages ensuring that modification to StackingContextCollectionState is
@@ -2197,6 +2215,7 @@ pub trait BlockFlowDisplayListBuilding {
pub struct SavedStackingContextCollectionState {
stacking_context_id: StackingContextId,
real_stacking_context_id: StackingContextId,
+ parent_reference_frame_id: ClipScrollNodeIndex,
clipping_and_scrolling: ClippingAndScrolling,
containing_block_clipping_and_scrolling: ClippingAndScrolling,
clips_pushed: usize,
@@ -2209,6 +2228,7 @@ impl SavedStackingContextCollectionState {
SavedStackingContextCollectionState {
stacking_context_id: state.current_stacking_context_id,
real_stacking_context_id: state.current_real_stacking_context_id,
+ parent_reference_frame_id: state.current_parent_reference_frame_id,
clipping_and_scrolling: state.current_clipping_and_scrolling,
containing_block_clipping_and_scrolling: state.containing_block_clipping_and_scrolling,
clips_pushed: 0,
@@ -2230,6 +2250,7 @@ impl SavedStackingContextCollectionState {
fn restore(self, state: &mut StackingContextCollectionState) {
state.current_stacking_context_id = self.stacking_context_id;
state.current_real_stacking_context_id = self.real_stacking_context_id;
+ state.current_parent_reference_frame_id = self.parent_reference_frame_id;
state.current_clipping_and_scrolling = self.clipping_and_scrolling;
state.containing_block_clipping_and_scrolling =
self.containing_block_clipping_and_scrolling;
@@ -2332,6 +2353,16 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
}
+ /// Returns true if this fragment may establish a reference frame and this block
+ /// creates a stacking context. Both are necessary in order to establish a reference
+ /// frame.
+ fn is_reference_frame(&self, context_type: Option<StackingContextType>) -> bool {
+ match context_type {
+ Some(StackingContextType::Real) => self.fragment.can_establish_reference_frame(),
+ _ => false,
+ }
+ }
+
fn collect_stacking_contexts_for_block(
&mut self,
state: &mut StackingContextCollectionState,
@@ -2348,8 +2379,17 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if stacking_context_type == Some(StackingContextType::Real) {
state.current_real_stacking_context_id = self.base.stacking_context_id;
+
}
+ let established_reference_frame = if self.is_reference_frame(stacking_context_type) {
+ // WebRender currently creates reference frames automatically, so just add
+ // a placeholder node to allocate a ClipScrollNodeIndex for this reference frame.
+ Some(state.add_clip_scroll_node(ClipScrollNode::placeholder()))
+ } else {
+ None
+ };
+
// We are getting the id of the scroll root that contains us here, not the id of
// any scroll root that we create. If we create a scroll root, its index will be
// stored in state.current_clipping_and_scrolling. If we create a stacking context,
@@ -2358,6 +2398,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
state,
&mut preserved_state,
stacking_context_type,
+ established_reference_frame,
flags,
);
@@ -2371,6 +2412,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
self.create_real_stacking_context_for_block(
preserved_state.stacking_context_id,
containing_clipping_and_scrolling,
+ established_reference_frame,
state,
);
},
@@ -2392,6 +2434,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
state: &mut StackingContextCollectionState,
preserved_state: &mut SavedStackingContextCollectionState,
stacking_context_type: Option<StackingContextType>,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
flags: StackingContextCollectionFlags,
) -> ClippingAndScrolling {
// If this block is absolutely positioned, we should be clipped and positioned by
@@ -2404,13 +2447,23 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
state.containing_block_clipping_and_scrolling
},
StylePosition::Fixed => {
+ // If we are a fixed positioned stacking context, we want to be scrolled by
+ // our reference frame instead of the clip scroll node that we are inside.
preserved_state.push_clip(state, Rect::max_rect(), StylePosition::Fixed);
+ state.current_clipping_and_scrolling.scrolling =
+ state.current_parent_reference_frame_id;
state.current_clipping_and_scrolling
},
_ => state.current_clipping_and_scrolling,
};
self.base.clipping_and_scrolling = Some(containing_clipping_and_scrolling);
+ if let Some(reference_frame_index) = established_reference_frame {
+ let clipping_and_scrolling = ClippingAndScrolling::simple(reference_frame_index);
+ state.current_clipping_and_scrolling = clipping_and_scrolling;
+ self.base.clipping_and_scrolling = Some(clipping_and_scrolling);
+ }
+
let stacking_relative_border_box = if self.fragment.establishes_stacking_context() {
self.stacking_relative_border_box(CoordinateSystem::Own)
} else {
@@ -2658,6 +2711,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&self.base,
ScrollPolicy::Scrollable,
stacking_context_type,
+ None,
parent_clipping_and_scrolling,
);
state.add_stacking_context(parent_stacking_context_id, new_context);
@@ -2683,19 +2737,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
&mut self,
parent_stacking_context_id: StackingContextId,
parent_clipping_and_scrolling: ClippingAndScrolling,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
state: &mut StackingContextCollectionState,
) {
- let scroll_policy = if self.is_fixed() {
- ScrollPolicy::Fixed
- } else {
- ScrollPolicy::Scrollable
- };
-
let stacking_context = self.fragment.create_stacking_context(
self.base.stacking_context_id,
&self.base,
- scroll_policy,
+ ScrollPolicy::Scrollable,
StackingContextType::Real,
+ established_reference_frame,
parent_clipping_and_scrolling,
);
@@ -2833,6 +2883,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
&self.base,
ScrollPolicy::Scrollable,
StackingContextType::Real,
+ None,
state.current_clipping_and_scrolling,
);
diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs
index 09539050789..7d293996c58 100644
--- a/components/layout/display_list/items.rs
+++ b/components/layout/display_list/items.rs
@@ -38,14 +38,25 @@ pub static BLUR_INFLATION_FACTOR: i32 = 3;
/// An index into the vector of ClipScrollNodes. During WebRender conversion these nodes
/// are given ClipIds.
#[derive(Clone, Copy, Debug, PartialEq, Serialize)]
-pub struct ClipScrollNodeIndex(pub usize);
+pub struct ClipScrollNodeIndex(usize);
impl ClipScrollNodeIndex {
+ pub fn root_scroll_node() -> ClipScrollNodeIndex {
+ ClipScrollNodeIndex(1)
+ }
+
+ pub fn root_reference_frame() -> ClipScrollNodeIndex {
+ ClipScrollNodeIndex(0)
+ }
+
+ pub fn new(index: usize) -> ClipScrollNodeIndex {
+ assert_ne!(index, 0, "Use the root_reference_frame constructor");
+ assert_ne!(index, 1, "Use the root_scroll_node constructor");
+ ClipScrollNodeIndex(index)
+ }
+
pub fn is_root_scroll_node(&self) -> bool {
- match *self {
- ClipScrollNodeIndex(0) => true,
- _ => false,
- }
+ *self == Self::root_scroll_node()
}
pub fn to_define_item(&self) -> DisplayItem {
@@ -54,6 +65,10 @@ impl ClipScrollNodeIndex {
node_index: *self,
}))
}
+
+ pub fn to_index(self) -> usize {
+ self.0
+ }
}
/// A set of indices into the clip scroll node vector for a given item.
@@ -193,6 +208,9 @@ pub struct StackingContext {
/// The clip and scroll info for this StackingContext.
pub parent_clipping_and_scrolling: ClippingAndScrolling,
+
+ /// The index of the reference frame that this stacking context estalishes.
+ pub established_reference_frame: Option<ClipScrollNodeIndex>,
}
impl StackingContext {
@@ -211,6 +229,7 @@ impl StackingContext {
perspective: Option<LayoutTransform>,
scroll_policy: ScrollPolicy,
parent_clipping_and_scrolling: ClippingAndScrolling,
+ established_reference_frame: Option<ClipScrollNodeIndex>,
) -> StackingContext {
StackingContext {
id,
@@ -225,6 +244,7 @@ impl StackingContext {
perspective,
scroll_policy,
parent_clipping_and_scrolling,
+ established_reference_frame,
}
}
@@ -242,7 +262,8 @@ impl StackingContext {
TransformStyle::Flat,
None,
ScrollPolicy::Scrollable,
- ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
+ ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
+ None,
)
}
@@ -309,15 +330,16 @@ impl fmt::Debug for StackingContext {
}
}
-#[derive(Clone, Debug, Serialize)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
pub struct StickyFrameData {
pub margins: SideOffsets2D<Option<f32>>,
pub vertical_offset_bounds: StickyOffsetBounds,
pub horizontal_offset_bounds: StickyOffsetBounds,
}
-#[derive(Clone, Debug, Serialize)]
+#[derive(Clone, Debug, PartialEq, Serialize)]
pub enum ClipScrollNodeType {
+ Placeholder,
ScrollFrame(ScrollSensitivity, ExternalScrollId),
StickyFrame(StickyFrameData),
Clip,
@@ -339,6 +361,21 @@ pub struct ClipScrollNode {
pub node_type: ClipScrollNodeType,
}
+impl ClipScrollNode {
+ pub fn placeholder() -> ClipScrollNode {
+ ClipScrollNode {
+ parent_index: ClipScrollNodeIndex(0),
+ clip: ClippingRegion::from_rect(LayoutRect::zero()),
+ content_rect: LayoutRect::zero(),
+ node_type: ClipScrollNodeType::Placeholder,
+ }
+ }
+
+ pub fn is_placeholder(&self) -> bool {
+ self.node_type == ClipScrollNodeType::Placeholder
+ }
+}
+
/// One drawing command in the list.
#[derive(Clone, Serialize)]
pub enum DisplayItem {
@@ -412,7 +449,8 @@ impl BaseDisplayItem {
clip_rect: LayoutRect::max_rect(),
section: DisplayListSection::Content,
stacking_context_id: StackingContextId::root(),
- clipping_and_scrolling: ClippingAndScrolling::simple(ClipScrollNodeIndex(0)),
+ clipping_and_scrolling:
+ ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
}
}
}
diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs
index 30f61386b92..da66b9c2b80 100644
--- a/components/layout/display_list/webrender_helpers.rs
+++ b/components/layout/display_list/webrender_helpers.rs
@@ -41,7 +41,12 @@ impl WebRenderDisplayListConverter for DisplayList {
let mut clip_ids = Vec::with_capacity(self.clip_scroll_nodes.len());
clip_ids.resize(self.clip_scroll_nodes.len(), None);
- clip_ids[0] = Some(ClipId::root_scroll_node(pipeline_id.to_webrender()));
+
+ // We need to add the WebRender root reference frame and root scroll node ids
+ // here manually, because WebRender creates these automatically.
+ let webrender_pipeline = pipeline_id.to_webrender();
+ clip_ids[0] = Some(ClipId::root_reference_frame(webrender_pipeline));
+ clip_ids[1] = Some(ClipId::root_scroll_node(webrender_pipeline));
for item in &self.list {
item.convert_to_webrender(
@@ -78,7 +83,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
current_clip_and_scroll_info: &mut ClipAndScrollInfo,
) {
let get_id = |clip_ids: &[Option<ClipId>], index: ClipScrollNodeIndex| -> ClipId {
- match clip_ids[index.0] {
+ match clip_ids[index.to_index()] {
Some(id) => id,
None => unreachable!("Tried to use WebRender ClipId before it was defined."),
}
@@ -214,7 +219,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
let stacking_context = &item.stacking_context;
debug_assert_eq!(stacking_context.context_type, StackingContextType::Real);
- builder.push_stacking_context(
+ let reference_frame_clip_id = builder.push_stacking_context(
&webrender_api::LayoutPrimitiveInfo::new(stacking_context.bounds),
None,
stacking_context.scroll_policy,
@@ -225,10 +230,17 @@ impl WebRenderDisplayItemConverter for DisplayItem {
stacking_context.filters.clone(),
GlyphRasterSpace::Screen,
);
+
+ match (reference_frame_clip_id, stacking_context.established_reference_frame) {
+ (Some(webrender_id), Some(frame_index)) =>
+ clip_ids[frame_index.to_index()] = Some(webrender_id),
+ (None, None) => {},
+ _ => warn!("Mismatch between reference frame establishment!"),
+ }
},
DisplayItem::PopStackingContext(_) => builder.pop_stacking_context(),
DisplayItem::DefineClipScrollNode(ref item) => {
- let node = &clip_scroll_nodes[item.node_index.0];
+ let node = &clip_scroll_nodes[item.node_index.to_index()];
let parent_id = get_id(clip_ids, node.parent_index);
let item_rect = node.clip.main;
@@ -262,9 +274,12 @@ impl WebRenderDisplayItemConverter for DisplayItem {
builder.pop_clip_id();
id
},
+ ClipScrollNodeType::Placeholder => {
+ unreachable!("Found DefineClipScrollNode for Placeholder type node.");
+ }
};
- clip_ids[item.node_index.0] = Some(webrender_id);
+ clip_ids[item.node_index.to_index()] = Some(webrender_id);
},
}
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index a1c84da3569..38ea9d03b93 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -2474,6 +2474,12 @@ impl Fragment {
stacking_relative_border_box.size.height - border_padding.vertical()))
}
+ /// Returns true if this fragment may establish a reference frame.
+ pub fn can_establish_reference_frame(&self) -> bool {
+ !self.style().get_box().transform.0.is_empty() ||
+ self.style().get_box().perspective != Perspective::None
+ }
+
/// Returns true if this fragment has a filter, transform, or perspective property set.
pub fn has_filter_transform_or_perspective(&self) -> bool {
!self.style().get_box().transform.0.is_empty() ||