mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
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:
parent
512d55ecef
commit
52b9951cad
10 changed files with 242 additions and 6 deletions
|
@ -112,6 +112,12 @@ pub trait FragmentDisplayListBuilding {
|
|||
level: StackingLevel,
|
||||
clip_rect: &Rect<Au>);
|
||||
|
||||
fn build_display_list_for_outline_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
display_list: &mut DisplayList,
|
||||
bounds: &Rect<Au>,
|
||||
clip_rect: &Rect<Au>);
|
||||
|
||||
fn build_debug_borders_around_text_fragments(&self,
|
||||
display_list: &mut DisplayList,
|
||||
flow_origin: Point2D<Au>,
|
||||
|
@ -439,6 +445,40 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}), level);
|
||||
}
|
||||
|
||||
fn build_display_list_for_outline_if_applicable(&self,
|
||||
style: &ComputedValues,
|
||||
display_list: &mut DisplayList,
|
||||
bounds: &Rect<Au>,
|
||||
clip_rect: &Rect<Au>) {
|
||||
let width = style.get_outline().outline_width;
|
||||
if width == Au(0) {
|
||||
return
|
||||
}
|
||||
|
||||
let outline_style = style.get_outline().outline_style;
|
||||
if outline_style == border_style::none {
|
||||
return
|
||||
}
|
||||
|
||||
// Outlines are not accounted for in the dimensions of the border box, so adjust the
|
||||
// absolute bounds.
|
||||
let mut bounds = *bounds;
|
||||
bounds.origin.x = bounds.origin.x - width;
|
||||
bounds.origin.y = bounds.origin.y - width;
|
||||
bounds.size.width = bounds.size.width + width + width;
|
||||
bounds.size.height = bounds.size.height + width + width;
|
||||
|
||||
// Append the outline to the display list.
|
||||
let color = style.resolve_color(style.get_outline().outline_color).to_gfx_color();
|
||||
display_list.outlines.push_back(BorderDisplayItemClass(box BorderDisplayItem {
|
||||
base: BaseDisplayItem::new(bounds, self.node, *clip_rect),
|
||||
border_widths: SideOffsets2D::new_all_same(width),
|
||||
color: SideOffsets2D::new_all_same(color),
|
||||
style: SideOffsets2D::new_all_same(outline_style),
|
||||
radius: Default::default(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn build_debug_borders_around_text_fragments(&self,
|
||||
display_list: &mut DisplayList,
|
||||
flow_origin: Point2D<Au>,
|
||||
|
@ -578,9 +618,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
// Add a border, if applicable.
|
||||
//
|
||||
// TODO: Outlines.
|
||||
// Add a border and outlines, if applicable.
|
||||
match self.inline_context {
|
||||
Some(ref inline_context) => {
|
||||
for style in inline_context.styles.iter().rev() {
|
||||
|
@ -590,6 +628,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
&absolute_fragment_bounds,
|
||||
level,
|
||||
clip_rect);
|
||||
self.build_display_list_for_outline_if_applicable(
|
||||
&**style,
|
||||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
|
@ -603,6 +646,11 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
&absolute_fragment_bounds,
|
||||
level,
|
||||
clip_rect);
|
||||
self.build_display_list_for_outline_if_applicable(
|
||||
&*self.style,
|
||||
display_list,
|
||||
&absolute_fragment_bounds,
|
||||
clip_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -870,8 +918,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
let stacking_context =
|
||||
self.create_stacking_context(display_list,
|
||||
Some(Arc::new(PaintLayer::new(self.layer_id(0),
|
||||
transparent,
|
||||
scroll_policy))));
|
||||
transparent,
|
||||
scroll_policy))));
|
||||
self.base.display_list_building_result = StackingContextResult(stacking_context)
|
||||
}
|
||||
|
||||
|
|
|
@ -1177,6 +1177,11 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
|||
/// Assumption: Absolute descendants have had their overflow calculated.
|
||||
fn store_overflow(self, _: &LayoutContext) {
|
||||
let my_position = mut_base(self).position;
|
||||
|
||||
// FIXME(pcwalton): We should calculate overflow on a per-fragment basis, because their
|
||||
// styles can affect overflow regions. Consider `box-shadow`, `outline`, etc.--anything
|
||||
// that can draw outside the border box. For now we assume overflow is the border box, but
|
||||
// that is wrong.
|
||||
let mut overflow = my_position;
|
||||
|
||||
if self.is_block_container() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue