mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Properly make stacking contexts for inlines
Instead of making a stacking context out of inline fragments parent flow, make the inline fragment itself the stacking context. This fixes positioning and rendering of these sort of fragments and prevents over-layerization. Fixes #7424. Fixes #5812.
This commit is contained in:
parent
fc98b8e126
commit
d572f1ca05
4 changed files with 123 additions and 58 deletions
|
@ -1738,19 +1738,20 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait InlineFlowDisplayListBuilding {
|
pub trait InlineFlowDisplayListBuilding {
|
||||||
|
fn build_display_list_for_inline_fragment_at_index(&mut self,
|
||||||
|
index: usize,
|
||||||
|
display_list: &mut DisplayList,
|
||||||
|
layout_context: &LayoutContext);
|
||||||
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext);
|
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineFlowDisplayListBuilding for InlineFlow {
|
impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) {
|
fn build_display_list_for_inline_fragment_at_index(&mut self,
|
||||||
// TODO(#228): Once we form lines and have their cached bounds, we can be smarter and
|
index: usize,
|
||||||
// not recurse on a line if nothing in it can intersect the dirty region.
|
display_list: &mut DisplayList,
|
||||||
debug!("Flow: building display list for {} inline fragments", self.fragments.len());
|
layout_context: &LayoutContext) {
|
||||||
|
let fragment = self.fragments.fragments.get_mut(index).unwrap();
|
||||||
let mut display_list = box DisplayList::new();
|
fragment.build_display_list(display_list,
|
||||||
let mut has_stacking_context = false;
|
|
||||||
for fragment in &mut self.fragments.fragments {
|
|
||||||
fragment.build_display_list(&mut *display_list,
|
|
||||||
layout_context,
|
layout_context,
|
||||||
&self.base.stacking_relative_position,
|
&self.base.stacking_relative_position,
|
||||||
&self.base
|
&self.base
|
||||||
|
@ -1764,8 +1765,6 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
&self.base.clip,
|
&self.base.clip,
|
||||||
&self.base.stacking_relative_position_of_display_port);
|
&self.base.stacking_relative_position_of_display_port);
|
||||||
|
|
||||||
has_stacking_context = fragment.establishes_stacking_context();
|
|
||||||
|
|
||||||
match fragment.specific {
|
match fragment.specific {
|
||||||
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
|
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
|
||||||
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
|
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
|
||||||
|
@ -1786,35 +1785,51 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) {
|
||||||
|
// TODO(#228): Once we form lines and have their cached bounds, we can be smarter and
|
||||||
|
// not recurse on a line if nothing in it can intersect the dirty region.
|
||||||
|
debug!("Flow: building display list for {} inline fragments", self.fragments.len());
|
||||||
|
|
||||||
|
let mut display_list = box DisplayList::new();
|
||||||
|
|
||||||
|
// We iterate using an index here, because we want to avoid doing a doing
|
||||||
|
// a double-borrow of self (one mutable for the method call and one immutable
|
||||||
|
// for the self.fragments.fragment iterator itself).
|
||||||
|
for index in (0..self.fragments.fragments.len()) {
|
||||||
|
let establishes_stacking_context = {
|
||||||
|
let fragment = self.fragments.fragments.get(index).unwrap();
|
||||||
|
match fragment.specific {
|
||||||
|
SpecificFragmentInfo::InlineBlock(_) |
|
||||||
|
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => false,
|
||||||
|
_ => fragment.establishes_stacking_context(),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if establishes_stacking_context {
|
||||||
|
let mut fragment_display_list = box DisplayList::new();
|
||||||
|
self.build_display_list_for_inline_fragment_at_index(index,
|
||||||
|
&mut *fragment_display_list,
|
||||||
|
layout_context);
|
||||||
|
let fragment = self.fragments.fragments.get(index).unwrap();
|
||||||
|
display_list.positioned_content.push_back(DisplayItem::StackingContextClass(
|
||||||
|
fragment.create_stacking_context(
|
||||||
|
&self.base,
|
||||||
|
fragment_display_list,
|
||||||
|
ScrollPolicy::Scrollable,
|
||||||
|
StackingContextCreationMode::Normal)));
|
||||||
|
} else {
|
||||||
|
self.build_display_list_for_inline_fragment_at_index(index,
|
||||||
|
&mut *display_list,
|
||||||
|
layout_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !self.fragments.fragments.is_empty() {
|
if !self.fragments.fragments.is_empty() {
|
||||||
self.base.build_display_items_for_debugging_tint(&mut *display_list,
|
self.base.build_display_items_for_debugging_tint(&mut *display_list,
|
||||||
self.fragments.fragments[0].node);
|
self.fragments.fragments[0].node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(Savago): fix Fragment::establishes_stacking_context() for absolute positioned item
|
self.base.display_list_building_result = Some(display_list);
|
||||||
// and remove the check for filter presence. Further details on #5812.
|
|
||||||
//
|
|
||||||
// FIXME(#7424, pcwalton): This is terribly bogus! What is even going on here?
|
|
||||||
if has_stacking_context {
|
|
||||||
match self.fragments.fragments[0].specific {
|
|
||||||
SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Iframe(_) => {}
|
|
||||||
_ => {
|
|
||||||
has_stacking_context =
|
|
||||||
!self.fragments.fragments[0].style().get_effects().filter.is_empty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.base.display_list_building_result = if has_stacking_context {
|
|
||||||
Some(DisplayList::new_with_stacking_context(
|
|
||||||
self.fragments.fragments[0].create_stacking_context(
|
|
||||||
&self.base,
|
|
||||||
display_list,
|
|
||||||
ScrollPolicy::Scrollable,
|
|
||||||
StackingContextCreationMode::Normal)))
|
|
||||||
} else {
|
|
||||||
Some(display_list)
|
|
||||||
};
|
|
||||||
|
|
||||||
if opts::get().validate_display_list_geometry {
|
if opts::get().validate_display_list_geometry {
|
||||||
self.base.validate_display_list_geometry();
|
self.base.validate_display_list_geometry();
|
||||||
|
|
|
@ -2015,6 +2015,18 @@
|
||||||
"url": "/_mozilla/css/inline_padding_a.html"
|
"url": "/_mozilla/css/inline_padding_a.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/inline_stacking_context.html": [
|
||||||
|
{
|
||||||
|
"path": "css/inline_stacking_context.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/inline_stacking_context_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/inline_stacking_context.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/inline_text_align_a.html": [
|
"css/inline_text_align_a.html": [
|
||||||
{
|
{
|
||||||
"path": "css/inline_text_align_a.html",
|
"path": "css/inline_text_align_a.html",
|
||||||
|
@ -6948,6 +6960,18 @@
|
||||||
"url": "/_mozilla/css/inline_padding_a.html"
|
"url": "/_mozilla/css/inline_padding_a.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"css/inline_stacking_context.html": [
|
||||||
|
{
|
||||||
|
"path": "css/inline_stacking_context.html",
|
||||||
|
"references": [
|
||||||
|
[
|
||||||
|
"/_mozilla/css/inline_stacking_context_ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"url": "/_mozilla/css/inline_stacking_context.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"css/inline_text_align_a.html": [
|
"css/inline_text_align_a.html": [
|
||||||
{
|
{
|
||||||
"path": "css/inline_text_align_a.html",
|
"path": "css/inline_text_align_a.html",
|
||||||
|
|
14
tests/wpt/mozilla/tests/css/inline_stacking_context.html
Normal file
14
tests/wpt/mozilla/tests/css/inline_stacking_context.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Inline stacking context positioned correctly</title>
|
||||||
|
<link rel=match href="inline_stacking_context_ref.html">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="font-size: 25px">
|
||||||
|
<span style="color: transparent;"><img src="100x100_green.png"></span>
|
||||||
|
<img style="filter: blur(0px);" src="100x100_green.png">
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
12
tests/wpt/mozilla/tests/css/inline_stacking_context_ref.html
Normal file
12
tests/wpt/mozilla/tests/css/inline_stacking_context_ref.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="font-size: 25px">
|
||||||
|
<span style="color: transparent;"><img src="100x100_green.png"></span>
|
||||||
|
<img src="100x100_green.png">
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue