layout: Draw elements with position: relative; z-index: auto over

ordinary content per CSS 2.1 Appendix E.

Improves Talking Points Memo.
This commit is contained in:
Patrick Walton 2015-05-11 16:29:24 -07:00
parent 234fb68a16
commit 87a620e1b3
7 changed files with 117 additions and 17 deletions

View file

@ -87,8 +87,10 @@ pub struct DisplayList {
pub block_backgrounds_and_borders: LinkedList<DisplayItem>, pub block_backgrounds_and_borders: LinkedList<DisplayItem>,
/// Floats: step 5. These are treated as pseudo-stacking contexts. /// Floats: step 5. These are treated as pseudo-stacking contexts.
pub floats: LinkedList<DisplayItem>, pub floats: LinkedList<DisplayItem>,
/// All other content. /// All non-positioned content.
pub content: LinkedList<DisplayItem>, pub content: LinkedList<DisplayItem>,
/// All positioned content that does not get a stacking context.
pub positioned_content: LinkedList<DisplayItem>,
/// Outlines: step 10. /// Outlines: step 10.
pub outlines: LinkedList<DisplayItem>, pub outlines: LinkedList<DisplayItem>,
/// Child stacking contexts. /// Child stacking contexts.
@ -104,6 +106,7 @@ impl DisplayList {
block_backgrounds_and_borders: LinkedList::new(), block_backgrounds_and_borders: LinkedList::new(),
floats: LinkedList::new(), floats: LinkedList::new(),
content: LinkedList::new(), content: LinkedList::new(),
positioned_content: LinkedList::new(),
outlines: LinkedList::new(), outlines: LinkedList::new(),
children: LinkedList::new(), children: LinkedList::new(),
} }
@ -117,6 +120,7 @@ impl DisplayList {
self.block_backgrounds_and_borders.append(&mut other.block_backgrounds_and_borders); self.block_backgrounds_and_borders.append(&mut other.block_backgrounds_and_borders);
self.floats.append(&mut other.floats); self.floats.append(&mut other.floats);
self.content.append(&mut other.content); self.content.append(&mut other.content);
self.positioned_content.append(&mut other.positioned_content);
self.outlines.append(&mut other.outlines); self.outlines.append(&mut other.outlines);
self.children.append(&mut other.children); self.children.append(&mut other.children);
} }
@ -125,11 +129,23 @@ impl DisplayList {
#[inline] #[inline]
pub fn form_float_pseudo_stacking_context(&mut self) { pub fn form_float_pseudo_stacking_context(&mut self) {
prepend_from(&mut self.floats, &mut self.outlines); prepend_from(&mut self.floats, &mut self.outlines);
prepend_from(&mut self.floats, &mut self.positioned_content);
prepend_from(&mut self.floats, &mut self.content); prepend_from(&mut self.floats, &mut self.content);
prepend_from(&mut self.floats, &mut self.block_backgrounds_and_borders); prepend_from(&mut self.floats, &mut self.block_backgrounds_and_borders);
prepend_from(&mut self.floats, &mut self.background_and_borders); prepend_from(&mut self.floats, &mut self.background_and_borders);
} }
/// Merges all display items from all non-positioned-content stacking levels to the
/// positioned-content stacking level.
#[inline]
pub fn form_pseudo_stacking_context_for_positioned_content(&mut self) {
prepend_from(&mut self.positioned_content, &mut self.outlines);
prepend_from(&mut self.positioned_content, &mut self.content);
prepend_from(&mut self.positioned_content, &mut self.floats);
prepend_from(&mut self.positioned_content, &mut self.block_backgrounds_and_borders);
prepend_from(&mut self.positioned_content, &mut self.background_and_borders);
}
/// Returns a list of all items in this display list concatenated together. This is extremely /// Returns a list of all items in this display list concatenated together. This is extremely
/// inefficient and should only be used for debugging. /// inefficient and should only be used for debugging.
pub fn all_display_items(&self) -> Vec<DisplayItem> { pub fn all_display_items(&self) -> Vec<DisplayItem> {
@ -146,6 +162,9 @@ impl DisplayList {
for display_item in self.content.iter() { for display_item in self.content.iter() {
result.push((*display_item).clone()) result.push((*display_item).clone())
} }
for display_item in self.positioned_content.iter() {
result.push((*display_item).clone())
}
for display_item in self.outlines.iter() { for display_item in self.outlines.iter() {
result.push((*display_item).clone()) result.push((*display_item).clone())
} }
@ -215,6 +234,7 @@ impl HeapSizeOf for DisplayList {
self.block_backgrounds_and_borders.heap_size_of_children() + self.block_backgrounds_and_borders.heap_size_of_children() +
self.floats.heap_size_of_children() + self.floats.heap_size_of_children() +
self.content.heap_size_of_children() + self.content.heap_size_of_children() +
self.positioned_content.heap_size_of_children() +
self.outlines.heap_size_of_children() + self.outlines.heap_size_of_children() +
self.children.heap_size_of_children() self.children.heap_size_of_children()
} }
@ -359,7 +379,12 @@ impl StackingContext {
display_item.draw_into_context(&mut paint_subcontext) display_item.draw_into_context(&mut paint_subcontext)
} }
// Steps 8 and 9: Positioned descendants with nonnegative z-indices. // Step 8: Positioned descendants with `z-index: auto`.
for display_item in display_list.positioned_content.iter() {
display_item.draw_into_context(&mut paint_subcontext)
}
// Step 9: Positioned descendants with nonnegative, numeric z-indices.
for positioned_kid in positioned_children.iter() { for positioned_kid in positioned_children.iter() {
if positioned_kid.z_index < 0 { if positioned_kid.z_index < 0 {
continue continue
@ -513,10 +538,12 @@ impl StackingContext {
} }
} }
// Steps 7, 5, and 4: Content, floats, and block backgrounds and borders. // Steps 8, 7, 5, and 4: Positioned content, content, floats, and block backgrounds and
// borders.
// //
// TODO(pcwalton): Step 6: Inlines that generate stacking contexts. // TODO(pcwalton): Step 6: Inlines that generate stacking contexts.
for display_list in [ for display_list in [
&self.display_list.positioned_content,
&self.display_list.content, &self.display_list.content,
&self.display_list.floats, &self.display_list.floats,
&self.display_list.block_backgrounds_and_borders, &self.display_list.block_backgrounds_and_borders,

View file

@ -35,6 +35,8 @@ impl DisplayListOptimizer {
display_list.block_backgrounds_and_borders.iter()); display_list.block_backgrounds_and_borders.iter());
self.add_in_bounds_display_items(&mut result.floats, display_list.floats.iter()); self.add_in_bounds_display_items(&mut result.floats, display_list.floats.iter());
self.add_in_bounds_display_items(&mut result.content, display_list.content.iter()); self.add_in_bounds_display_items(&mut result.content, display_list.content.iter());
self.add_in_bounds_display_items(&mut result.positioned_content,
display_list.positioned_content.iter());
self.add_in_bounds_display_items(&mut result.outlines, display_list.outlines.iter()); self.add_in_bounds_display_items(&mut result.outlines, display_list.outlines.iter());
self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter()); self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter());
result result

View file

@ -1364,8 +1364,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
background_border_level); background_border_level);
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
DisplayListBuildingResult::StackingContext(self.fragment.create_stacking_context(&self.base, display_list, None)) DisplayListBuildingResult::StackingContext(
self.fragment.create_stacking_context(&self.base, display_list, None))
} else { } else {
match self.fragment.style.get_box().position {
position::T::static_ => {}
_ => {
display_list.form_pseudo_stacking_context_for_positioned_content();
}
}
DisplayListBuildingResult::Normal(display_list) DisplayListBuildingResult::Normal(display_list)
} }
} }
@ -1384,8 +1391,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
!self.base.flags.contains(NEEDS_LAYER) { !self.base.flags.contains(NEEDS_LAYER) {
// We didn't need a layer. // We didn't need a layer.
self.base.display_list_building_result = self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(self.fragment DisplayListBuildingResult::StackingContext(
.create_stacking_context(&self.base, display_list, None)); self.fragment.create_stacking_context(&self.base, display_list, None));
return return
} }
@ -1398,10 +1405,10 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let transparent = color::transparent(); let transparent = color::transparent();
let stacking_context = self.fragment.create_stacking_context(&self.base, display_list, let stacking_context = self.fragment.create_stacking_context(
Some(Arc::new(PaintLayer::new(self.layer_id(0), &self.base,
transparent, display_list,
scroll_policy)))); Some(Arc::new(PaintLayer::new(self.layer_id(0), transparent, scroll_policy))));
self.base.display_list_building_result = self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(stacking_context) DisplayListBuildingResult::StackingContext(stacking_context)
} }
@ -1417,8 +1424,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
display_list.form_float_pseudo_stacking_context(); display_list.form_float_pseudo_stacking_context();
self.base.display_list_building_result = if self.fragment.establishes_stacking_context() { self.base.display_list_building_result = if self.fragment.establishes_stacking_context() {
DisplayListBuildingResult::StackingContext(self.fragment DisplayListBuildingResult::StackingContext(
.create_stacking_context(&self.base, display_list, None)) self.fragment.create_stacking_context(&self.base, display_list, None))
} else { } else {
DisplayListBuildingResult::Normal(display_list) DisplayListBuildingResult::Normal(display_list)
} }
@ -1496,11 +1503,16 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
// FIXME(Savago): fix Fragment::establishes_stacking_context() for absolute positioned item // FIXME(Savago): fix Fragment::establishes_stacking_context() for absolute positioned item
// and remove the check for filter presence. Further details on #5812. // and remove the check for filter presence. Further details on #5812.
if has_stacking_context && !self.fragments.fragments[0].style().get_effects().filter.is_empty() { if has_stacking_context &&
!self.fragments.fragments[0].style().get_effects().filter.is_empty() {
self.base.display_list_building_result = self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(self.fragments.fragments[0].create_stacking_context(&self.base, display_list, None)); DisplayListBuildingResult::StackingContext(
self.fragments.fragments[0].create_stacking_context(&self.base,
display_list,
None));
} else { } else {
self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list); self.base.display_list_building_result =
DisplayListBuildingResult::Normal(display_list);
} }
if opts::get().validate_display_list_geometry { if opts::get().validate_display_list_geometry {
@ -1614,7 +1626,7 @@ pub enum StackingLevel {
BackgroundAndBorders, BackgroundAndBorders,
/// Borders and backgrounds for block-level descendants: step 4. /// Borders and backgrounds for block-level descendants: step 4.
BlockBackgroundsAndBorders, BlockBackgroundsAndBorders,
/// All other content. /// All non-positioned content.
Content, Content,
} }

@ -1 +1 @@
Subproject commit dc8aef3e1b8f1acd141986cfab492e3f57d2d5f6 Subproject commit 10116eb3af332f9565e0fb803e600511bb585d6b

View file

@ -252,6 +252,7 @@ experimental != overconstrained_block.html overconstrained_block_ref.html
== position_fixed_tile_edge_2.html position_fixed_tile_edge_ref.html == position_fixed_tile_edge_2.html position_fixed_tile_edge_ref.html
== position_fixed_tile_edge_3.html position_fixed_tile_edge_ref.html == position_fixed_tile_edge_3.html position_fixed_tile_edge_ref.html
== position_relative_a.html position_relative_b.html == position_relative_a.html position_relative_b.html
== position_relative_painting_order_a.html position_relative_painting_order_ref.html
== position_relative_top_percentage_a.html position_relative_top_percentage_b.html == position_relative_top_percentage_a.html position_relative_top_percentage_b.html
== pre_ignorable_whitespace_a.html pre_ignorable_whitespace_ref.html == pre_ignorable_whitespace_a.html pre_ignorable_whitespace_ref.html
== pre_with_tab.html pre_with_tab_ref.html == pre_with_tab.html pre_with_tab_ref.html

View file

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
margin: 0;
}
div {
height: 100px;
width: 100px;
}
#a {
position: relative;
top: 50px;
left: 50px;
background: purple;
}
#b {
background: steelblue;
}
</style>
</head>
<body>
<div id=a></div>
<div id=b></div>
</body>
</html>

View file

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<style>
html, body {
margin: 0;
}
div {
position: absolute;
height: 100px;
width: 100px;
}
#a {
top: 50px;
left: 50px;
background: purple;
}
#b {
background: steelblue;
left: 0;
top: 100px;
}
</style>
</head>
<body>
<div id=b></div>
<div id=a></div>
</body>
</html>