mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
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:
parent
234fb68a16
commit
87a620e1b3
7 changed files with 117 additions and 17 deletions
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
28
tests/ref/position_relative_painting_order_a.html
Normal file
28
tests/ref/position_relative_painting_order_a.html
Normal 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>
|
||||||
|
|
30
tests/ref/position_relative_painting_order_ref.html
Normal file
30
tests/ref/position_relative_painting_order_ref.html
Normal 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>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue