Replace Servo DL items with WR ones

The Servo internal display list items are already pretty much
equivalent to the WebRender ones. Except that Servo items contain
base information and associated glyphs and gradient stops which are
stored implicitly in WebRender. Remove the display items for
rectangles, text, images, border, gradients and box shadow and
replace them with their WebRender counter parts.
This commit is contained in:
Pyfisch 2018-08-06 19:47:00 +02:00
parent 025ba5cbe3
commit 9e971f9d8f
4 changed files with 381 additions and 465 deletions

View file

@ -13,7 +13,7 @@
use app_units::Au;
use display_list::ToLayout;
use display_list::items::{BorderDetails, Gradient, RadialGradient, WebRenderImageInfo};
use display_list::items::WebRenderImageInfo;
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Vector2D};
use model::{self, MaybeAuto};
use style::computed_values::background_attachment::single_value::T as BackgroundAttachment;
@ -34,8 +34,9 @@ use style::values::generics::image::EndingShape as GenericEndingShape;
use style::values::generics::image::GradientItem as GenericGradientItem;
use style::values::specified::background::BackgroundRepeatKeyword;
use style::values::specified::position::{X, Y};
use webrender_api::{BorderRadius, BorderSide, BorderStyle, ColorF, ExtendMode, GradientStop};
use webrender_api::{LayoutSize, NinePatchBorder, NinePatchBorderSource, NormalBorder};
use webrender_api::{BorderDetails, BorderRadius, BorderSide, BorderStyle, ColorF, ExtendMode};
use webrender_api::{Gradient, GradientStop, LayoutSize, NinePatchBorder, NinePatchBorderSource};
use webrender_api::{NormalBorder, RadialGradient};
/// A helper data structure for gradients.
#[derive(Clone, Copy)]
@ -543,7 +544,7 @@ pub fn convert_linear_gradient(
stops: &[GradientItem],
direction: LineDirection,
repeating: bool,
) -> Gradient {
) -> (Gradient, Vec<GradientStop>) {
let angle = match direction {
LineDirection::Angle(angle) => angle.radians(),
LineDirection::Horizontal(x) => match x {
@ -591,12 +592,14 @@ pub fn convert_linear_gradient(
let center = Point2D::new(size.width / 2, size.height / 2);
Gradient {
start_point: (center - delta).to_layout(),
end_point: (center + delta).to_layout(),
(
Gradient {
start_point: (center - delta).to_layout(),
end_point: (center + delta).to_layout(),
extend_mode: as_gradient_extend_mode(repeating),
},
stops,
extend_mode: as_gradient_extend_mode(repeating),
}
)
}
pub fn convert_radial_gradient(
@ -606,7 +609,7 @@ pub fn convert_radial_gradient(
shape: EndingShape,
center: Position,
repeating: bool,
) -> RadialGradient {
) -> (RadialGradient, Vec<GradientStop>) {
let center = Point2D::new(
center.horizontal.to_used_value(size.width),
center.vertical.to_used_value(size.height),
@ -629,12 +632,17 @@ pub fn convert_radial_gradient(
let stops = convert_gradient_stops(style, stops, radius.width);
RadialGradient {
center: center.to_layout(),
radius: radius.to_layout(),
stops: stops,
extend_mode: as_gradient_extend_mode(repeating),
}
(
RadialGradient {
center: center.to_layout(),
radius: radius.to_layout(),
extend_mode: as_gradient_extend_mode(repeating),
// FIXME(pyfisch): These values are calculated by WR.
start_offset: 0.0,
end_offset: 0.0,
},
stops,
)
}
/// Returns the the distance to the nearest or farthest corner depending on the comperator.
@ -799,7 +807,7 @@ pub fn build_image_border_details(
let corners = &border_style_struct.border_image_slice.offsets;
let border_image_repeat = &border_style_struct.border_image_repeat;
if let Some(image_key) = webrender_image.key {
Some(BorderDetails::Image(NinePatchBorder {
Some(BorderDetails::NinePatch(NinePatchBorder {
source: NinePatchBorderSource::Image(image_key),
width: webrender_image.width,
height: webrender_image.height,

View file

@ -20,15 +20,13 @@ use display_list::background::{calculate_border_image_outset, calculate_inner_bo
use display_list::background::{compute_background_clip, compute_background_placement};
use display_list::background::{convert_linear_gradient, convert_radial_gradient, get_cyclic};
use display_list::background::simple_normal_border;
use display_list::items::{BaseDisplayItem, BorderDetails, BorderDisplayItem, BLUR_INFLATION_FACTOR};
use display_list::items::{BoxShadowDisplayItem, ClipScrollNode};
use display_list::items::{BaseDisplayItem, BLUR_INFLATION_FACTOR, ClipScrollNode};
use display_list::items::{ClipScrollNodeIndex, ClipScrollNodeType, ClippingAndScrolling};
use display_list::items::{ClippingRegion, DisplayItem, DisplayItemMetadata, DisplayList};
use display_list::items::{DisplayListSection, GradientBorder, GradientDisplayItem};
use display_list::items::{IframeDisplayItem, ImageDisplayItem, LineDisplayItem, OpaqueNode};
use display_list::items::{DisplayListSection, CommonDisplayItem};
use display_list::items::{IframeDisplayItem, LineDisplayItem, OpaqueNode};
use display_list::items::{PopAllTextShadowsDisplayItem, PushTextShadowDisplayItem};
use display_list::items::{RadialGradientBorder, RadialGradientDisplayItem, SolidColorDisplayItem};
use display_list::items::{StackingContext, StackingContextType, StickyFrameData, TextDisplayItem};
use display_list::items::{StackingContext, StackingContextType, StickyFrameData};
use display_list::items::{TextOrientation, WebRenderImageInfo};
use euclid::{rect, Point2D, Rect, SideOffsets2D, Size2D, TypedSize2D, Vector2D};
use flex::FlexFlow;
@ -71,10 +69,10 @@ use style_traits::CSSPixel;
use style_traits::ToCss;
use style_traits::cursor::CursorKind;
use table_cell::CollapsedBordersForCell;
use webrender_api::{self, BorderRadius, BorderSide, BoxShadowClipMode, ColorF, ExternalScrollId};
use webrender_api::{FilterOp, GlyphInstance, ImageRendering, LayoutRect, LayoutSize};
use webrender_api::{LayoutTransform, LayoutVector2D, LineStyle, NormalBorder, ScrollSensitivity};
use webrender_api::StickyOffsetBounds;
use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF};
use webrender_api::{ExternalScrollId, FilterOp, GlyphInstance, ImageRendering, LayoutRect};
use webrender_api::{LayoutSize, LayoutTransform, LayoutVector2D, LineStyle, NormalBorder};
use webrender_api::{StickyOffsetBounds, ScrollSensitivity};
fn establishes_containing_block_for_absolute(
flags: StackingContextCollectionFlags,
@ -371,15 +369,17 @@ impl<'a> DisplayListBuildState<'a> {
clip_scroll_nodes: state.clip_scroll_nodes,
processing_scrolling_overflow_element: false,
current_stacking_context_id: StackingContextId::root(),
current_clipping_and_scrolling:
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
current_clipping_and_scrolling: ClippingAndScrolling::simple(
ClipScrollNodeIndex::root_scroll_node(),
),
iframe_sizes: Vec::new(),
indexable_text: IndexableText::default(),
}
}
fn add_display_item(&mut self, display_item: DisplayItem) {
let items = self.items
let items = self
.items
.entry(display_item.stacking_context_id())
.or_insert(Vec::new());
items.push(display_item);
@ -408,9 +408,9 @@ impl<'a> DisplayListBuildState<'a> {
section: DisplayListSection,
) -> BaseDisplayItem {
let clipping_and_scrolling = if self.is_background_or_border_of_clip_scroll_node(section) {
ClippingAndScrolling::simple(self.parent_clip_scroll_node_index(
self.current_clipping_and_scrolling.scrolling,
))
ClippingAndScrolling::simple(
self.parent_clip_scroll_node_index(self.current_clipping_and_scrolling.scrolling),
)
} else {
self.current_clipping_and_scrolling
};
@ -474,13 +474,15 @@ impl<'a> DisplayListBuildState<'a> {
list: &mut Vec<DisplayItem>,
stacking_context: StackingContext,
) {
let mut child_items = self.items
let mut child_items = self
.items
.remove(&stacking_context.id)
.unwrap_or(Vec::new());
child_items.sort_by(|a, b| a.base().section.cmp(&b.base().section));
child_items.reverse();
let mut info = self.stacking_context_info
let mut info = self
.stacking_context_info
.remove(&stacking_context.id)
.unwrap();
@ -821,7 +823,8 @@ impl FragmentDisplayListBuilding for Fragment {
true
},
// FIXME: In the future, if #15144 is fixed we can remove this case. See #18510.
SpecificFragmentInfo::TruncatedFragment(ref mut info) => info.full
SpecificFragmentInfo::TruncatedFragment(ref mut info) => info
.full
.collect_stacking_contexts_for_blocklike_fragment(state),
_ => false,
}
@ -918,10 +921,12 @@ impl FragmentDisplayListBuilding for Fragment {
style.get_cursor(CursorKind::Default),
display_list_section,
);
state.add_display_item(DisplayItem::SolidColor(Box::new(SolidColorDisplayItem {
base: base,
color: background_color.to_layout(),
})));
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
base,
webrender_api::RectangleDisplayItem {
color: background_color.to_layout(),
},
)));
});
// The background image is painted on top of the background color.
@ -1047,13 +1052,16 @@ impl FragmentDisplayListBuilding for Fragment {
);
debug!("(building display list) adding background image.");
state.add_display_item(DisplayItem::Image(Box::new(ImageDisplayItem {
base: base,
id: webrender_image.key.unwrap(),
stretch_size: placement.tile_size.to_layout(),
tile_spacing: placement.tile_spacing.to_layout(),
image_rendering: style.get_inherited_box().image_rendering.to_layout(),
})));
state.add_display_item(DisplayItem::Image(CommonDisplayItem::new(
base,
webrender_api::ImageDisplayItem {
image_key: webrender_image.key.unwrap(),
stretch_size: placement.tile_size.to_layout(),
tile_spacing: placement.tile_spacing.to_layout(),
image_rendering: style.get_inherited_box().image_rendering.to_layout(),
alpha_type: webrender_api::AlphaType::PremultipliedAlpha,
},
)));
});
}
@ -1154,22 +1162,22 @@ impl FragmentDisplayListBuilding for Fragment {
let display_item = match gradient.kind {
GradientKind::Linear(angle_or_corner) => {
let gradient = convert_linear_gradient(
let (gradient, stops) = convert_linear_gradient(
style,
placement.tile_size,
&gradient.items[..],
angle_or_corner,
gradient.repeating,
);
DisplayItem::Gradient(Box::new(GradientDisplayItem {
base: base,
gradient: gradient,
tile: placement.tile_size.to_layout(),
let item = webrender_api::GradientDisplayItem {
gradient,
tile_size: placement.tile_size.to_layout(),
tile_spacing: placement.tile_spacing.to_layout(),
}))
};
DisplayItem::Gradient(CommonDisplayItem::with_data(base, item, stops))
},
GradientKind::Radial(shape, center, _angle) => {
let gradient = convert_radial_gradient(
let (gradient, stops) = convert_radial_gradient(
style,
placement.tile_size,
&gradient.items[..],
@ -1177,12 +1185,12 @@ impl FragmentDisplayListBuilding for Fragment {
center,
gradient.repeating,
);
DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem {
base: base,
gradient: gradient,
tile: placement.tile_size.to_layout(),
let item = webrender_api::RadialGradientDisplayItem {
gradient,
tile_size: placement.tile_size.to_layout(),
tile_spacing: placement.tile_spacing.to_layout(),
}))
};
DisplayItem::RadialGradient(CommonDisplayItem::with_data(base, item, stops))
},
};
state.add_display_item(display_item);
@ -1216,23 +1224,25 @@ impl FragmentDisplayListBuilding for Fragment {
display_list_section,
);
let border_radius = build_border_radius(absolute_bounds, style.get_border());
state.add_display_item(DisplayItem::BoxShadow(Box::new(BoxShadowDisplayItem {
base: base,
box_bounds: absolute_bounds.to_layout(),
color: style.resolve_color(box_shadow.base.color).to_layout(),
offset: LayoutVector2D::new(
box_shadow.base.horizontal.px(),
box_shadow.base.vertical.px(),
),
blur_radius: box_shadow.base.blur.px(),
spread_radius: box_shadow.spread.px(),
border_radius: border_radius,
clip_mode: if box_shadow.inset {
BoxShadowClipMode::Inset
} else {
BoxShadowClipMode::Outset
state.add_display_item(DisplayItem::BoxShadow(CommonDisplayItem::new(
base,
webrender_api::BoxShadowDisplayItem {
box_bounds: absolute_bounds.to_layout(),
color: style.resolve_color(box_shadow.base.color).to_layout(),
offset: LayoutVector2D::new(
box_shadow.base.horizontal.px(),
box_shadow.base.vertical.px(),
),
blur_radius: box_shadow.base.blur.px(),
spread_radius: box_shadow.spread.px(),
border_radius: border_radius,
clip_mode: if box_shadow.inset {
BoxShadowClipMode::Inset
} else {
BoxShadowClipMode::Outset
},
},
})));
)));
}
}
@ -1312,6 +1322,7 @@ impl FragmentDisplayListBuilding for Fragment {
);
let size = bounds.outer_rect(outset).size;
let mut stops = Vec::new();
let details = match border_style_struct.border_image_source {
Either::First(_) => Some(BorderDetails::Normal(NormalBorder {
left: BorderSide {
@ -1333,36 +1344,53 @@ impl FragmentDisplayListBuilding for Fragment {
radius: border_radius,
})),
Either::Second(Image::Gradient(ref gradient)) => Some(match gradient.kind {
GradientKind::Linear(angle_or_corner) => BorderDetails::Gradient(GradientBorder {
gradient: convert_linear_gradient(
GradientKind::Linear(angle_or_corner) => {
let (wr_gradient, linear_stops) = convert_linear_gradient(
style,
bounds.size,
&gradient.items[..],
angle_or_corner,
gradient.repeating,
),
outset: outset_layout,
}),
);
stops = linear_stops;
BorderDetails::NinePatch(webrender_api::NinePatchBorder {
source: webrender_api::NinePatchBorderSource::Gradient(wr_gradient),
width: 0,
height: 0,
slice: SideOffsets2D::zero(),
fill: false,
repeat_horizontal: webrender_api::RepeatMode::Stretch,
repeat_vertical: webrender_api::RepeatMode::Stretch,
outset: outset_layout,
})
},
GradientKind::Radial(shape, center, _angle) => {
BorderDetails::RadialGradient(RadialGradientBorder {
gradient: convert_radial_gradient(
style,
bounds.size,
&gradient.items[..],
shape,
center,
gradient.repeating,
),
let (wr_gradient, radial_stops) = convert_radial_gradient(
style,
bounds.size,
&gradient.items[..],
shape,
center,
gradient.repeating,
);
stops = radial_stops;
BorderDetails::NinePatch(webrender_api::NinePatchBorder {
source: webrender_api::NinePatchBorderSource::RadialGradient(wr_gradient),
width: 0,
height: 0,
slice: SideOffsets2D::zero(),
fill: false,
repeat_horizontal: webrender_api::RepeatMode::Stretch,
repeat_vertical: webrender_api::RepeatMode::Stretch,
outset: outset_layout,
})
},
}),
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
self.get_webrender_image_for_paint_worklet(state, style, paint_worklet, size)
.and_then(|image| {
build_image_border_details(image, border_style_struct, outset_layout)
})
},
Either::Second(Image::PaintWorklet(ref paint_worklet)) => self
.get_webrender_image_for_paint_worklet(state, style, paint_worklet, size)
.and_then(|image| {
build_image_border_details(image, border_style_struct, outset_layout)
}),
Either::Second(Image::Rect(..)) => {
// TODO: Handle border-image with `-moz-image-rect`.
None
@ -1385,11 +1413,14 @@ impl FragmentDisplayListBuilding for Fragment {
}),
};
if let Some(details) = details {
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
border_widths: border_widths.to_layout(),
details,
})));
webrender_api::BorderDisplayItem {
widths: border_widths.to_layout(),
details,
},
stops,
)));
}
}
@ -1429,11 +1460,17 @@ impl FragmentDisplayListBuilding for Fragment {
style.get_cursor(CursorKind::Default),
DisplayListSection::Outlines,
);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base,
border_widths: SideOffsets2D::new_all_same(width).to_layout(),
details: BorderDetails::Normal(simple_normal_border(color, outline_style.to_layout())),
})));
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(width).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
color,
outline_style.to_layout(),
)),
},
Vec::new(),
)));
}
fn build_debug_borders_around_text_fragments(
@ -1456,14 +1493,17 @@ impl FragmentDisplayListBuilding for Fragment {
style.get_cursor(CursorKind::Default),
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base,
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
ColorF::rgb(0, 0, 200),
webrender_api::BorderStyle::Solid,
)),
})));
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
ColorF::rgb(0, 0, 200),
webrender_api::BorderStyle::Solid,
)),
},
Vec::new(),
)));
// Draw a rectangle representing the baselines.
let mut baseline = LogicalRect::from_physical(
@ -1503,14 +1543,17 @@ impl FragmentDisplayListBuilding for Fragment {
self.style.get_cursor(CursorKind::Default),
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base,
border_widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
ColorF::rgb(0, 0, 200),
webrender_api::BorderStyle::Solid,
)),
})));
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(Au::from_px(1)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
ColorF::rgb(0, 0, 200),
webrender_api::BorderStyle::Solid,
)),
},
Vec::new(),
)));
}
fn build_display_items_for_selection_if_necessary(
@ -1540,10 +1583,12 @@ impl FragmentDisplayListBuilding for Fragment {
self.style.get_cursor(CursorKind::Default),
display_list_section,
);
state.add_display_item(DisplayItem::SolidColor(Box::new(SolidColorDisplayItem {
base: base,
color: background_color.to_layout(),
})));
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
base,
webrender_api::RectangleDisplayItem {
color: background_color.to_layout(),
},
)));
}
// Draw a caret at the insertion point.
@ -1584,10 +1629,12 @@ impl FragmentDisplayListBuilding for Fragment {
self.style.get_cursor(cursor),
display_list_section,
);
state.add_display_item(DisplayItem::SolidColor(Box::new(SolidColorDisplayItem {
base: base,
color: self.style().get_color().color.to_layout(),
})));
state.add_display_item(DisplayItem::Rectangle(CommonDisplayItem::new(
base,
webrender_api::RectangleDisplayItem {
color: self.style().get_color().color.to_layout(),
},
)));
}
fn build_display_list(
@ -1658,9 +1705,11 @@ impl FragmentDisplayListBuilding for Fragment {
state,
&*node.style,
Some(InlineNodeBorderInfo {
is_first_fragment_of_element: node.flags
is_first_fragment_of_element: node
.flags
.contains(InlineFragmentNodeFlags::FIRST_FRAGMENT_OF_ELEMENT),
is_last_fragment_of_element: node.flags
is_last_fragment_of_element: node
.flags
.contains(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT),
}),
border_painting_mode,
@ -1873,16 +1922,20 @@ impl FragmentDisplayListBuilding for Fragment {
if let Some(ref image) = image_fragment.image {
if let Some(id) = image.id {
let base = create_base_display_item(state);
state.add_display_item(DisplayItem::Image(Box::new(ImageDisplayItem {
state.add_display_item(DisplayItem::Image(CommonDisplayItem::new(
base,
id,
stretch_size: stacking_relative_content_box.size.to_layout(),
tile_spacing: LayoutSize::zero(),
image_rendering: self.style
.get_inherited_box()
.image_rendering
.to_layout(),
})));
webrender_api::ImageDisplayItem {
image_key: id,
stretch_size: stacking_relative_content_box.size.to_layout(),
tile_spacing: LayoutSize::zero(),
image_rendering: self
.style
.get_inherited_box()
.image_rendering
.to_layout(),
alpha_type: webrender_api::AlphaType::PremultipliedAlpha,
},
)));
}
}
},
@ -1906,13 +1959,16 @@ impl FragmentDisplayListBuilding for Fragment {
};
let base = create_base_display_item(state);
let display_item = DisplayItem::Image(Box::new(ImageDisplayItem {
let display_item = DisplayItem::Image(CommonDisplayItem::new(
base,
id: image_key,
stretch_size: stacking_relative_content_box.size.to_layout(),
tile_spacing: LayoutSize::zero(),
image_rendering: ImageRendering::Auto,
}));
webrender_api::ImageDisplayItem {
image_key,
stretch_size: stacking_relative_content_box.size.to_layout(),
tile_spacing: LayoutSize::zero(),
image_rendering: ImageRendering::Auto,
alpha_type: webrender_api::AlphaType::PremultipliedAlpha,
},
));
state.add_display_item(display_item);
},
@ -2092,12 +2148,15 @@ impl FragmentDisplayListBuilding for Fragment {
};
state.indexable_text.insert(self.node, indexable_text);
state.add_display_item(DisplayItem::Text(Box::new(TextDisplayItem {
base: base.clone(),
glyphs: glyphs,
font_key: text_fragment.run.font_key,
text_color: text_color.to_layout(),
})));
state.add_display_item(DisplayItem::Text(CommonDisplayItem::with_data(
base.clone(),
webrender_api::TextDisplayItem {
font_key: text_fragment.run.font_key,
color: text_color.to_layout(),
glyph_options: None,
},
glyphs,
)));
}
// TODO(#17715): emit text-emphasis marks here.
@ -2342,7 +2401,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
None => return,
};
let perspective = self.fragment
let perspective = self
.fragment
.perspective_matrix(&border_box)
.unwrap_or(LayoutTransform::identity());
let transform = transform.pre_mul(&perspective).inverse();
@ -2420,7 +2480,6 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if stacking_context_type == Some(StackingContextType::Real) {
state.current_real_stacking_context_id = self.base.stacking_context_id;
}
let established_reference_frame = if self.is_reference_frame(stacking_context_type) {
@ -2446,7 +2505,7 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if establishes_containing_block_for_absolute(
flags,
self.positioning(),
established_reference_frame.is_some()
established_reference_frame.is_some(),
) {
state.containing_block_clipping_and_scrolling = state.current_clipping_and_scrolling;
}
@ -2536,7 +2595,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
// We keep track of our position so that any stickily positioned elements can
// properly determine the extent of their movement relative to scrolling containers.
if !flags.contains(StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK) {
if !flags.contains(StackingContextCollectionFlags::POSITION_NEVER_CREATES_CONTAINING_BLOCK)
{
let border_box = if self.fragment.establishes_stacking_context() {
stacking_relative_border_box
} else {
@ -2566,7 +2626,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
}
let sticky_position = self.sticky_position();
if sticky_position.left == MaybeAuto::Auto && sticky_position.right == MaybeAuto::Auto &&
if sticky_position.left == MaybeAuto::Auto &&
sticky_position.right == MaybeAuto::Auto &&
sticky_position.top == MaybeAuto::Auto &&
sticky_position.bottom == MaybeAuto::Auto
{
@ -2663,7 +2724,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
ScrollSensitivity::ScriptAndInputEvents
};
let border_widths = self.fragment
let border_widths = self
.fragment
.style
.logical_border_width()
.to_physical(self.fragment.style.writing_mode);
@ -2804,7 +2866,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
let background_border_section = self.background_border_section();
state.processing_scrolling_overflow_element = self.has_scrolling_overflow();
let stacking_relative_border_box = self.base
let stacking_relative_border_box = self
.base
.stacking_relative_border_box_for_display_list(&self.fragment);
// Add the box that starts the block context.
self.fragment.build_display_list_no_damage(
@ -2838,7 +2901,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
background: &style_structs::Background,
background_color: RGBA,
) {
let stacking_relative_border_box = self.base
let stacking_relative_border_box = self
.base
.stacking_relative_border_box_for_display_list(&self.fragment);
let background_border_section = self.background_border_section();
@ -2866,7 +2930,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
return Some(StackingContextType::Real);
}
if self.base
if self
.base
.flags
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED)
{
@ -2943,7 +3008,8 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
index: usize,
) {
let fragment = self.fragments.fragments.get_mut(index).unwrap();
let stacking_relative_border_box = self.base
let stacking_relative_border_box = self
.base
.stacking_relative_border_box_for_display_list(fragment);
fragment.build_display_list(
state,
@ -2999,7 +3065,8 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
fn build_display_list_for_list_item(&mut self, state: &mut DisplayListBuildState) {
// Draw the marker, if applicable.
for marker in &mut self.marker_fragments {
let stacking_relative_border_box = self.block_flow
let stacking_relative_border_box = self
.block_flow
.base
.stacking_relative_border_box_for_display_list(marker);
marker.build_display_list(
@ -3062,14 +3129,17 @@ impl BaseFlowDisplayListBuilding for BaseFlow {
None,
DisplayListSection::Content,
);
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
base: base,
border_widths: SideOffsets2D::new_all_same(Au::from_px(2)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
color,
webrender_api::BorderStyle::Solid,
)),
})));
state.add_display_item(DisplayItem::Border(CommonDisplayItem::with_data(
base,
webrender_api::BorderDisplayItem {
widths: SideOffsets2D::new_all_same(Au::from_px(2)).to_layout(),
details: BorderDetails::Normal(simple_normal_border(
color,
webrender_api::BorderStyle::Solid,
)),
},
Vec::new(),
)));
}
}

View file

@ -22,11 +22,12 @@ use std::cmp::Ordering;
use std::collections::HashMap;
use std::f32;
use std::fmt;
use webrender_api::{BorderRadius, BorderWidths, BoxShadowClipMode, ClipMode, ColorF};
use webrender_api::{ComplexClipRegion, ExtendMode, ExternalScrollId, FilterOp, FontInstanceKey};
use webrender_api::{GlyphInstance, GradientStop, ImageKey, ImageRendering, LayoutPoint};
use webrender_api as wr;
use webrender_api::{BorderRadius, ClipMode, ColorF};
use webrender_api::{ComplexClipRegion, ExternalScrollId, FilterOp};
use webrender_api::{GlyphInstance, GradientStop, ImageKey, LayoutPoint};
use webrender_api::{LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D, LineStyle};
use webrender_api::{MixBlendMode, NinePatchBorder, NormalBorder, ScrollSensitivity, Shadow};
use webrender_api::{MixBlendMode, ScrollSensitivity, Shadow};
use webrender_api::{StickyOffsetBounds, TransformStyle};
pub use style::dom::OpaqueNode;
@ -373,14 +374,14 @@ impl ClipScrollNode {
/// One drawing command in the list.
#[derive(Clone, Serialize)]
pub enum DisplayItem {
SolidColor(Box<SolidColorDisplayItem>),
Text(Box<TextDisplayItem>),
Image(Box<ImageDisplayItem>),
Border(Box<BorderDisplayItem>),
Gradient(Box<GradientDisplayItem>),
RadialGradient(Box<RadialGradientDisplayItem>),
Rectangle(Box<CommonDisplayItem<wr::RectangleDisplayItem>>),
Text(Box<CommonDisplayItem<wr::TextDisplayItem, Vec<GlyphInstance>>>),
Image(Box<CommonDisplayItem<wr::ImageDisplayItem>>),
Border(Box<CommonDisplayItem<wr::BorderDisplayItem, Vec<GradientStop>>>),
Gradient(Box<CommonDisplayItem<wr::GradientDisplayItem, Vec<GradientStop>>>),
RadialGradient(Box<CommonDisplayItem<wr::RadialGradientDisplayItem, Vec<GradientStop>>>),
Line(Box<LineDisplayItem>),
BoxShadow(Box<BoxShadowDisplayItem>),
BoxShadow(Box<CommonDisplayItem<wr::BoxShadowDisplayItem>>),
PushTextShadow(Box<PushTextShadowDisplayItem>),
PopAllTextShadows(Box<PopAllTextShadowsDisplayItem>),
Iframe(Box<IframeDisplayItem>),
@ -443,8 +444,9 @@ impl BaseDisplayItem {
clip_rect: LayoutRect::max_rect(),
section: DisplayListSection::Content,
stacking_context_id: StackingContextId::root(),
clipping_and_scrolling:
ClippingAndScrolling::simple(ClipScrollNodeIndex::root_scroll_node()),
clipping_and_scrolling: ClippingAndScrolling::simple(
ClipScrollNodeIndex::root_scroll_node(),
),
}
}
}
@ -579,7 +581,8 @@ impl ClippingRegion {
pub fn translate(&self, delta: &LayoutVector2D) -> ClippingRegion {
ClippingRegion {
main: self.main.translate(delta),
complex: self.complex
complex: self
.complex
.iter()
.map(|complex| ComplexClipRegion {
rect: complex.rect.translate(delta),
@ -624,11 +627,13 @@ impl CompletelyEncloses for ComplexClipRegion {
fn completely_encloses(&self, other: &Self) -> bool {
let left = self.radii.top_left.width.max(self.radii.bottom_left.width);
let top = self.radii.top_left.height.max(self.radii.top_right.height);
let right = self.radii
let right = self
.radii
.top_right
.width
.max(self.radii.bottom_right.width);
let bottom = self.radii
let bottom = self
.radii
.bottom_left
.height
.max(self.radii.bottom_right.height);
@ -639,8 +644,10 @@ impl CompletelyEncloses for ComplexClipRegion {
self.rect.size.height - top - bottom,
),
);
interior.origin.x <= other.rect.origin.x && interior.origin.y <= other.rect.origin.y &&
interior.max_x() >= other.rect.max_x() && interior.max_y() >= other.rect.max_y()
interior.origin.x <= other.rect.origin.x &&
interior.origin.y <= other.rect.origin.y &&
interior.max_x() >= other.rect.max_x() &&
interior.max_y() >= other.rect.max_y()
}
}
@ -656,29 +663,6 @@ pub struct DisplayItemMetadata {
pub pointing: Option<u16>,
}
/// Paints a solid color.
#[derive(Clone, Serialize)]
pub struct SolidColorDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// The color.
pub color: ColorF,
}
/// Paints text.
#[derive(Clone, Serialize)]
pub struct TextDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// A collection of (non-whitespace) glyphs to be displayed.
pub glyphs: Vec<GlyphInstance>,
/// Reference to the font to be used.
pub font_key: FontInstanceKey,
/// The color of the text.
pub text_color: ColorF,
}
#[derive(Clone, Eq, PartialEq, Serialize)]
pub enum TextOrientation {
Upright,
@ -686,26 +670,6 @@ pub enum TextOrientation {
SidewaysRight,
}
/// Paints an image.
#[derive(Clone, Serialize)]
pub struct ImageDisplayItem {
pub base: BaseDisplayItem,
pub id: ImageKey,
/// The dimensions to which the image display item should be stretched. If this is smaller than
/// the bounds of this display item, then the image will be repeated in the appropriate
/// direction to tile the entire bounds.
pub stretch_size: LayoutSize,
/// The amount of space to add to the right and bottom part of each tile, when the image
/// is tiled.
pub tile_spacing: LayoutSize,
/// The algorithm we should use to stretch the image. See `image_rendering` in CSS-IMAGES-3 §
/// 5.3.
pub image_rendering: ImageRendering,
}
/// Paints an iframe.
#[derive(Clone, Serialize)]
pub struct IframeDisplayItem {
@ -713,118 +677,6 @@ pub struct IframeDisplayItem {
pub iframe: PipelineId,
}
/// Paints a gradient.
#[derive(Clone, Serialize)]
pub struct Gradient {
/// The start point of the gradient (computed during display list construction).
pub start_point: LayoutPoint,
/// The end point of the gradient (computed during display list construction).
pub end_point: LayoutPoint,
/// A list of color stops.
pub stops: Vec<GradientStop>,
/// Whether the gradient is repeated or clamped.
pub extend_mode: ExtendMode,
}
#[derive(Clone, Serialize)]
pub struct GradientDisplayItem {
/// Fields common to all display item.
pub base: BaseDisplayItem,
/// Contains all gradient data. Included start, end point and color stops.
pub gradient: Gradient,
/// The size of a single gradient tile.
///
/// The gradient may fill an entire element background
/// but it can be composed from many smaller copys of
/// the same gradient.
///
/// Without tiles, the tile will be the same size as the background.
pub tile: LayoutSize,
pub tile_spacing: LayoutSize,
}
/// Paints a radial gradient.
#[derive(Clone, Serialize)]
pub struct RadialGradient {
/// The center point of the gradient.
pub center: LayoutPoint,
/// The radius of the gradient with an x and an y component.
pub radius: LayoutSize,
/// A list of color stops.
pub stops: Vec<GradientStop>,
/// Whether the gradient is repeated or clamped.
pub extend_mode: ExtendMode,
}
#[derive(Clone, Serialize)]
pub struct RadialGradientDisplayItem {
/// Fields common to all display item.
pub base: BaseDisplayItem,
/// Contains all gradient data.
pub gradient: RadialGradient,
/// The size of a single gradient tile.
///
/// The gradient may fill an entire element background
/// but it can be composed from many smaller copys of
/// the same gradient.
///
/// Without tiles, the tile will be the same size as the background.
pub tile: LayoutSize,
pub tile_spacing: LayoutSize,
}
/// A border that is made of linear gradient
#[derive(Clone, Serialize)]
pub struct GradientBorder {
/// The gradient info that this border uses, border-image-source.
pub gradient: Gradient,
/// Outsets for the border, as per border-image-outset.
pub outset: SideOffsets2D<f32>,
}
/// A border that is made of radial gradient
#[derive(Clone, Serialize)]
pub struct RadialGradientBorder {
/// The gradient info that this border uses, border-image-source.
pub gradient: RadialGradient,
/// Outsets for the border, as per border-image-outset.
pub outset: SideOffsets2D<f32>,
}
/// Specifies the type of border
#[derive(Clone, Serialize)]
pub enum BorderDetails {
Normal(NormalBorder),
Image(NinePatchBorder),
Gradient(GradientBorder),
RadialGradient(RadialGradientBorder),
}
/// Paints a border.
#[derive(Clone, Serialize)]
pub struct BorderDisplayItem {
/// Fields common to all display items.
pub base: BaseDisplayItem,
/// Border widths.
pub border_widths: BorderWidths,
/// Details for specific border type
pub details: BorderDetails,
}
/// Paints a line segment.
#[derive(Clone, Serialize)]
pub struct LineDisplayItem {
@ -837,32 +689,27 @@ pub struct LineDisplayItem {
pub style: LineStyle,
}
/// Paints a box shadow per CSS-BACKGROUNDS.
#[derive(Clone, Serialize)]
pub struct BoxShadowDisplayItem {
/// Fields common to all display items.
pub struct CommonDisplayItem<T, U = ()> {
pub base: BaseDisplayItem,
pub item: T,
pub data: U,
}
/// The dimensions of the box that we're placing a shadow around.
pub box_bounds: LayoutRect,
impl<T> CommonDisplayItem<T> {
pub fn new(base: BaseDisplayItem, item: T) -> Box<CommonDisplayItem<T>> {
Box::new(CommonDisplayItem {
base,
item,
data: (),
})
}
}
/// The offset of this shadow from the box.
pub offset: LayoutVector2D,
/// The color of this shadow.
pub color: ColorF,
/// The blur radius for this shadow.
pub blur_radius: f32,
/// The spread radius of this shadow.
pub spread_radius: f32,
/// The border radius of this shadow.
pub border_radius: BorderRadius,
/// How we should clip the result.
pub clip_mode: BoxShadowClipMode,
impl<T, U> CommonDisplayItem<T, U> {
pub fn with_data(base: BaseDisplayItem, item: T, data: U) -> Box<CommonDisplayItem<T, U>> {
Box::new(CommonDisplayItem { base, item, data })
}
}
/// Defines a text shadow that affects all items until the paired PopTextShadow.
@ -912,7 +759,7 @@ pub struct DefineClipScrollNodeItem {
impl DisplayItem {
pub fn base(&self) -> &BaseDisplayItem {
match *self {
DisplayItem::SolidColor(ref solid_color) => &solid_color.base,
DisplayItem::Rectangle(ref rect) => &rect.base,
DisplayItem::Text(ref text) => &text.base,
DisplayItem::Image(ref image_item) => &image_item.base,
DisplayItem::Border(ref border) => &border.base,
@ -976,13 +823,7 @@ impl fmt::Debug for DisplayItem {
f,
"{} @ {:?} {:?}",
match *self {
DisplayItem::SolidColor(ref solid_color) => format!(
"SolidColor rgba({}, {}, {}, {})",
solid_color.color.r,
solid_color.color.g,
solid_color.color.b,
solid_color.color.a
),
DisplayItem::Rectangle(_) => "Rectangle".to_owned(),
DisplayItem::Text(_) => "Text".to_owned(),
DisplayItem::Image(_) => "Image".to_owned(),
DisplayItem::Border(_) => "Border".to_owned(),
@ -1032,8 +873,18 @@ impl SimpleMatrixDetection for LayoutTransform {
#[inline]
fn is_identity_or_simple_translation(&self) -> bool {
let (_0, _1) = (0.0, 1.0);
self.m11 == _1 && self.m12 == _0 && self.m13 == _0 && self.m14 == _0 && self.m21 == _0 &&
self.m22 == _1 && self.m23 == _0 && self.m24 == _0 && self.m31 == _0 &&
self.m32 == _0 && self.m33 == _1 && self.m34 == _0 && self.m44 == _1
self.m11 == _1 &&
self.m12 == _0 &&
self.m13 == _0 &&
self.m14 == _0 &&
self.m21 == _0 &&
self.m22 == _1 &&
self.m23 == _0 &&
self.m24 == _0 &&
self.m31 == _0 &&
self.m32 == _0 &&
self.m33 == _1 &&
self.m34 == _0 &&
self.m44 == _1
}
}

View file

@ -7,9 +7,8 @@
// This might be achieved by sharing types between WR and Servo display lists, or
// completely converting layout to directly generate WebRender display lists, for example.
use display_list::items::{BorderDetails, ClipScrollNode, ClipScrollNodeIndex, ClipScrollNodeType};
use display_list::items::{ClipScrollNode, ClipScrollNodeIndex, ClipScrollNodeType};
use display_list::items::{DisplayItem, DisplayList, StackingContextType};
use euclid::SideOffsets2D;
use msg::constellation_msg::PipelineId;
use webrender_api::{self, ClipAndScrollInfo, ClipId, DisplayListBuilder, GlyphRasterSpace};
use webrender_api::LayoutPoint;
@ -104,105 +103,93 @@ impl WebRenderDisplayItemConverter for DisplayItem {
}
match *self {
DisplayItem::SolidColor(ref item) => {
builder.push_rect(&self.prim_info(), item.color);
DisplayItem::Rectangle(ref item) => {
builder.push_rect(&self.prim_info(), item.item.color);
},
DisplayItem::Text(ref item) => {
builder.push_text(
&self.prim_info(),
&item.glyphs,
item.font_key,
item.text_color,
None,
&item.data,
item.item.font_key,
item.item.color,
item.item.glyph_options,
);
},
DisplayItem::Image(ref item) => {
if item.stretch_size.width > 0.0 && item.stretch_size.height > 0.0 {
builder.push_image(
&self.prim_info(),
item.stretch_size,
item.tile_spacing,
item.image_rendering,
webrender_api::AlphaType::PremultipliedAlpha,
item.id,
);
}
builder.push_image(
&self.prim_info(),
item.item.stretch_size,
item.item.tile_spacing,
item.item.image_rendering,
item.item.alpha_type,
item.item.image_key,
);
},
DisplayItem::Border(ref item) => {
let details = match item.details {
BorderDetails::Normal(ref border) => {
webrender_api::BorderDetails::Normal(*border)
},
BorderDetails::Image(ref image) => {
webrender_api::BorderDetails::NinePatch(*image)
if item.data.is_empty() {
builder.push_border(&self.prim_info(), item.item.widths, item.item.details);
} else {
let mut details = item.item.details.clone();
match &mut details {
webrender_api::BorderDetails::NinePatch(
webrender_api::NinePatchBorder {
source:
webrender_api::NinePatchBorderSource::Gradient(ref mut gradient),
..
},
) => {
*gradient = builder.create_gradient(
gradient.start_point,
gradient.end_point,
item.data.clone(),
gradient.extend_mode,
);
},
webrender_api::BorderDetails::NinePatch(
webrender_api::NinePatchBorder {
source:
webrender_api::NinePatchBorderSource::RadialGradient(gradient),
..
},
) => {
*gradient = builder.create_radial_gradient(
gradient.center,
gradient.radius,
item.data.clone(),
gradient.extend_mode,
)
},
_ => unreachable!(),
}
BorderDetails::Gradient(ref gradient) => {
let wr_gradient = builder.create_gradient(
gradient.gradient.start_point,
gradient.gradient.end_point,
gradient.gradient.stops.clone(),
gradient.gradient.extend_mode,
);
let details = webrender_api::NinePatchBorder {
source: webrender_api::NinePatchBorderSource::Gradient(wr_gradient),
width: 0,
height: 0,
slice: SideOffsets2D::zero(),
fill: false,
repeat_horizontal: webrender_api::RepeatMode::Stretch,
repeat_vertical: webrender_api::RepeatMode::Stretch,
outset: gradient.outset,
};
webrender_api::BorderDetails::NinePatch(details)
},
BorderDetails::RadialGradient(ref gradient) => {
let wr_gradient = builder.create_radial_gradient(
gradient.gradient.center,
gradient.gradient.radius,
gradient.gradient.stops.clone(),
gradient.gradient.extend_mode,
);
let details = webrender_api::NinePatchBorder {
source: webrender_api::NinePatchBorderSource::RadialGradient(wr_gradient),
width: 0,
height: 0,
slice: SideOffsets2D::zero(),
fill: false,
repeat_horizontal: webrender_api::RepeatMode::Stretch,
repeat_vertical: webrender_api::RepeatMode::Stretch,
outset: gradient.outset,
};
webrender_api::BorderDetails::NinePatch(details)
},
};
builder.push_border(&self.prim_info(), item.border_widths, details);
builder.push_border(&self.prim_info(), item.item.widths, details);
}
},
DisplayItem::Gradient(ref item) => {
let gradient = builder.create_gradient(
item.gradient.start_point,
item.gradient.end_point,
item.gradient.stops.clone(),
item.gradient.extend_mode,
item.item.gradient.start_point,
item.item.gradient.end_point,
item.data.clone(),
item.item.gradient.extend_mode,
);
builder.push_gradient(
&self.prim_info(),
gradient,
item.item.tile_size,
item.item.tile_spacing,
);
builder.push_gradient(&self.prim_info(), gradient, item.tile, item.tile_spacing);
},
DisplayItem::RadialGradient(ref item) => {
let gradient = builder.create_radial_gradient(
item.gradient.center,
item.gradient.radius,
item.gradient.stops.clone(),
item.gradient.extend_mode,
item.item.gradient.center,
item.item.gradient.radius,
item.data.clone(),
item.item.gradient.extend_mode,
);
builder.push_radial_gradient(
&self.prim_info(),
gradient,
item.tile,
item.tile_spacing,
item.item.tile_size,
item.item.tile_spacing,
);
},
DisplayItem::Line(ref item) => {
@ -218,13 +205,13 @@ impl WebRenderDisplayItemConverter for DisplayItem {
DisplayItem::BoxShadow(ref item) => {
builder.push_box_shadow(
&self.prim_info(),
item.box_bounds,
item.offset,
item.color,
item.blur_radius,
item.spread_radius,
item.border_radius,
item.clip_mode,
item.item.box_bounds,
item.item.offset,
item.item.color,
item.item.blur_radius,
item.item.spread_radius,
item.item.border_radius,
item.item.clip_mode,
);
},
DisplayItem::PushTextShadow(ref item) => {
@ -244,7 +231,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
if let Some(frame_index) = stacking_context.established_reference_frame {
debug_assert!(
stacking_context.transform.is_some() ||
stacking_context.perspective.is_some()
stacking_context.perspective.is_some()
);
let clip_id = builder.push_reference_frame(
@ -310,7 +297,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
},
ClipScrollNodeType::Placeholder => {
unreachable!("Found DefineClipScrollNode for Placeholder type node.");
}
},
};
clip_ids[item.node_index.to_index()] = Some(webrender_id);