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>,
/// Floats: step 5. These are treated as pseudo-stacking contexts.
pub floats: LinkedList<DisplayItem>,
/// All other content.
/// All non-positioned content.
pub content: LinkedList<DisplayItem>,
/// All positioned content that does not get a stacking context.
pub positioned_content: LinkedList<DisplayItem>,
/// Outlines: step 10.
pub outlines: LinkedList<DisplayItem>,
/// Child stacking contexts.
@ -104,6 +106,7 @@ impl DisplayList {
block_backgrounds_and_borders: LinkedList::new(),
floats: LinkedList::new(),
content: LinkedList::new(),
positioned_content: LinkedList::new(),
outlines: LinkedList::new(),
children: LinkedList::new(),
}
@ -117,6 +120,7 @@ impl DisplayList {
self.block_backgrounds_and_borders.append(&mut other.block_backgrounds_and_borders);
self.floats.append(&mut other.floats);
self.content.append(&mut other.content);
self.positioned_content.append(&mut other.positioned_content);
self.outlines.append(&mut other.outlines);
self.children.append(&mut other.children);
}
@ -125,11 +129,23 @@ impl DisplayList {
#[inline]
pub fn form_float_pseudo_stacking_context(&mut self) {
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.block_backgrounds_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
/// inefficient and should only be used for debugging.
pub fn all_display_items(&self) -> Vec<DisplayItem> {
@ -146,6 +162,9 @@ impl DisplayList {
for display_item in self.content.iter() {
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() {
result.push((*display_item).clone())
}
@ -215,6 +234,7 @@ impl HeapSizeOf for DisplayList {
self.block_backgrounds_and_borders.heap_size_of_children() +
self.floats.heap_size_of_children() +
self.content.heap_size_of_children() +
self.positioned_content.heap_size_of_children() +
self.outlines.heap_size_of_children() +
self.children.heap_size_of_children()
}
@ -359,7 +379,12 @@ impl StackingContext {
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() {
if positioned_kid.z_index < 0 {
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.
for display_list in [
&self.display_list.positioned_content,
&self.display_list.content,
&self.display_list.floats,
&self.display_list.block_backgrounds_and_borders,

View file

@ -35,6 +35,8 @@ impl DisplayListOptimizer {
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.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_stacking_contexts(&mut result.children, display_list.children.iter());
result

View file

@ -1364,8 +1364,15 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
background_border_level);
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 {
match self.fragment.style.get_box().position {
position::T::static_ => {}
_ => {
display_list.form_pseudo_stacking_context_for_positioned_content();
}
}
DisplayListBuildingResult::Normal(display_list)
}
}
@ -1384,8 +1391,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
!self.base.flags.contains(NEEDS_LAYER) {
// We didn't need a layer.
self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(self.fragment
.create_stacking_context(&self.base, display_list, None));
DisplayListBuildingResult::StackingContext(
self.fragment.create_stacking_context(&self.base, display_list, None));
return
}
@ -1398,10 +1405,10 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let transparent = color::transparent();
let stacking_context = self.fragment.create_stacking_context(&self.base, display_list,
Some(Arc::new(PaintLayer::new(self.layer_id(0),
transparent,
scroll_policy))));
let stacking_context = self.fragment.create_stacking_context(
&self.base,
display_list,
Some(Arc::new(PaintLayer::new(self.layer_id(0), transparent, scroll_policy))));
self.base.display_list_building_result =
DisplayListBuildingResult::StackingContext(stacking_context)
}
@ -1417,8 +1424,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
display_list.form_float_pseudo_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 {
DisplayListBuildingResult::Normal(display_list)
}
@ -1496,11 +1503,16 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
// FIXME(Savago): fix Fragment::establishes_stacking_context() for absolute positioned item
// 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 =
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 {
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 {
@ -1614,7 +1626,7 @@ pub enum StackingLevel {
BackgroundAndBorders,
/// Borders and backgrounds for block-level descendants: step 4.
BlockBackgroundsAndBorders,
/// All other content.
/// All non-positioned 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_3.html position_fixed_tile_edge_ref.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
== pre_ignorable_whitespace_a.html pre_ignorable_whitespace_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>