diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index 4036c2efd2c5..f66f70ee17a4 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -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) { 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) { 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, diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 134468b29eb8..d21294177ccc 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -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, 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(), + ))); } } diff --git a/components/layout/display_list/items.rs b/components/layout/display_list/items.rs index 1010e8ada5df..de5e324aee8c 100644 --- a/components/layout/display_list/items.rs +++ b/components/layout/display_list/items.rs @@ -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), - Text(Box), - Image(Box), - Border(Box), - Gradient(Box), - RadialGradient(Box), + Rectangle(Box>), + Text(Box>>), + Image(Box>), + Border(Box>>), + Gradient(Box>>), + RadialGradient(Box>>), Line(Box), - BoxShadow(Box), + BoxShadow(Box>), PushTextShadow(Box), PopAllTextShadows(Box), Iframe(Box), @@ -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, } -/// 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, - /// 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, - - /// 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, - - /// 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, -} - -/// 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, -} - -/// 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 { 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, - - /// 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, +impl CommonDisplayItem { + pub fn new(base: BaseDisplayItem, item: T) -> Box> { + Box::new(CommonDisplayItem { + base, + item, + data: (), + }) + } +} - /// How we should clip the result. - pub clip_mode: BoxShadowClipMode, +impl CommonDisplayItem { + pub fn with_data(base: BaseDisplayItem, item: T, data: U) -> Box> { + 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 } } diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs index 987259ed5b98..43ae47c52418 100644 --- a/components/layout/display_list/webrender_helpers.rs +++ b/components/layout/display_list/webrender_helpers.rs @@ -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);