layout: Implement outline per CSS 2.1 § 18.4.

`invert` is not yet supported.

Objects that get layers will not yet display outlines properly. This is
because our overflow calculation doesn't take styles into account and
because layers are always anchored to the top left of the border box.
Since fixing this is work that is not related to outline *per se* I'm
leaving that to a followup and making a note in the code.
This commit is contained in:
Patrick Walton 2014-12-08 23:29:41 -08:00
parent 512d55ecef
commit 52b9951cad
10 changed files with 242 additions and 6 deletions

View file

@ -75,6 +75,8 @@ pub struct DisplayList {
pub floats: DList<DisplayItem>,
/// All other content.
pub content: DList<DisplayItem>,
/// Outlines: step 10.
pub outlines: DList<DisplayItem>,
/// Child stacking contexts.
pub children: DList<Arc<StackingContext>>,
}
@ -88,6 +90,7 @@ impl DisplayList {
block_backgrounds_and_borders: DList::new(),
floats: DList::new(),
content: DList::new(),
outlines: DList::new(),
children: DList::new(),
}
}
@ -102,12 +105,14 @@ impl DisplayList {
&mut other.block_backgrounds_and_borders);
servo_dlist::append_from(&mut self.floats, &mut other.floats);
servo_dlist::append_from(&mut self.content, &mut other.content);
servo_dlist::append_from(&mut self.outlines, &mut other.outlines);
servo_dlist::append_from(&mut self.children, &mut other.children);
}
/// Merges all display items from all non-float stacking levels to the `float` stacking level.
#[inline]
pub fn form_float_pseudo_stacking_context(&mut self) {
servo_dlist::prepend_from(&mut self.floats, &mut self.outlines);
servo_dlist::prepend_from(&mut self.floats, &mut self.content);
servo_dlist::prepend_from(&mut self.floats, &mut self.block_backgrounds_and_borders);
servo_dlist::prepend_from(&mut self.floats, &mut self.background_and_borders);
@ -129,6 +134,9 @@ impl DisplayList {
for display_item in self.content.iter() {
result.push((*display_item).clone())
}
for display_item in self.outlines.iter() {
result.push((*display_item).clone())
}
result
}
}
@ -282,7 +290,10 @@ impl StackingContext {
}
}
// TODO(pcwalton): Step 10: Outlines.
// Step 10: Outlines.
for display_item in display_list.outlines.iter() {
display_item.draw_into_context(&mut paint_subcontext)
}
// Undo our clipping and transform.
if paint_subcontext.transient_clip_rect.is_some() {
@ -349,6 +360,12 @@ impl StackingContext {
// Iterate through display items in reverse stacking order. Steps here refer to the
// painting steps in CSS 2.1 Appendix E.
//
// Step 10: Outlines.
hit_test_in_list(point, result, topmost_only, self.display_list.outlines.iter().rev());
if topmost_only && !result.is_empty() {
return
}
// Steps 9 and 8: Positioned descendants with nonnegative z-indices.
for kid in self.display_list.children.iter().rev() {
if kid.z_index < 0 {

View file

@ -35,6 +35,7 @@ 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.outlines, display_list.outlines.iter());
self.add_in_bounds_stacking_contexts(&mut result.children, display_list.children.iter());
result
}