mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-07 09:54:42 +00:00
servo: Merge #17862 - Implemented paint worklets drawing to a border (from asajeffrey:script-paint-worklet-border); r=pcwalton
<!-- Please describe your changes on the following line: --> Allow paint worklets to draw to a border. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #17451. - [X] These changes do not require tests because the existing css-paint-api test check this (but annoyingly, all fail for other reasons) <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: a5282cabe04ac836458652bcb2b5e40214d36390 --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 6924fe28fb30379d26e2be76e73a1521ea16239c
This commit is contained in:
parent
abe2f5e465
commit
bb5244cac3
@ -43,7 +43,6 @@ use range::Range;
|
||||
use script_layout_interface::wrapper_traits::PseudoElementType;
|
||||
use servo_config::opts;
|
||||
use servo_geometry::max_rect;
|
||||
use servo_url::ServoUrl;
|
||||
use std::{cmp, f32};
|
||||
use std::default::Default;
|
||||
use std::mem;
|
||||
@ -455,17 +454,6 @@ pub trait FragmentDisplayListBuilding {
|
||||
image: &WebRenderImageInfo, index: usize)
|
||||
-> Size2D<Au>;
|
||||
|
||||
/// Adds the display items necessary to paint the background image of this fragment to the
|
||||
/// appropriate section of the display list.
|
||||
fn build_display_list_for_background_image(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &LocalClip,
|
||||
image_url: &ServoUrl,
|
||||
background_index: usize);
|
||||
|
||||
/// Adds the display items necessary to paint a webrender image of this fragment to the
|
||||
/// appropriate section of the display list.
|
||||
fn build_display_list_for_webrender_image(&self,
|
||||
@ -477,16 +465,15 @@ pub trait FragmentDisplayListBuilding {
|
||||
webrender_image: WebRenderImageInfo,
|
||||
index: usize);
|
||||
|
||||
/// Adds the display items necessary to paint the background image created by this fragment's
|
||||
/// worklet to the appropriate section of the display list.
|
||||
fn build_display_list_for_background_paint_worklet(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &LocalClip,
|
||||
paint_worklet: &PaintWorklet,
|
||||
index: usize);
|
||||
/// Calculates the webrender image for a paint worklet.
|
||||
/// Returns None if the worklet is not registered.
|
||||
/// If the worklet has missing image URLs, it passes them to the image cache for loading.
|
||||
fn get_webrender_image_for_paint_worklet(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
paint_worklet: &PaintWorklet,
|
||||
size: Size2D<Au>)
|
||||
-> Option<WebRenderImageInfo>;
|
||||
|
||||
fn convert_linear_gradient(&self,
|
||||
bounds: &Rect<Au>,
|
||||
@ -1015,23 +1002,47 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
}
|
||||
Either::Second(Image::Url(ref image_url)) => {
|
||||
if let Some(url) = image_url.url() {
|
||||
self.build_display_list_for_background_image(state,
|
||||
style,
|
||||
display_list_section,
|
||||
&bounds,
|
||||
&clip,
|
||||
url,
|
||||
i);
|
||||
let webrender_image = state.layout_context
|
||||
.get_webrender_image_for_url(self.node,
|
||||
url.clone(),
|
||||
UsePlaceholder::No);
|
||||
if let Some(webrender_image) = webrender_image {
|
||||
self.build_display_list_for_webrender_image(state,
|
||||
style,
|
||||
display_list_section,
|
||||
&bounds,
|
||||
&clip,
|
||||
webrender_image,
|
||||
i);
|
||||
}
|
||||
}
|
||||
}
|
||||
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
|
||||
self.build_display_list_for_background_paint_worklet(state,
|
||||
style,
|
||||
display_list_section,
|
||||
&bounds,
|
||||
&clip,
|
||||
paint_worklet,
|
||||
i);
|
||||
let bounding_box = self.border_box - style.logical_border_width();
|
||||
let bounding_box_size = bounding_box.size.to_physical(style.writing_mode);
|
||||
let background_size = get_cyclic(&style.get_background().background_size.0, i).clone();
|
||||
let size = match background_size {
|
||||
BackgroundSize::Explicit { width, height } => {
|
||||
Size2D::new(MaybeAuto::from_style(width, bounding_box_size.width)
|
||||
.specified_or_default(bounding_box_size.width),
|
||||
MaybeAuto::from_style(height, bounding_box_size.height)
|
||||
.specified_or_default(bounding_box_size.height))
|
||||
},
|
||||
_ => bounding_box_size,
|
||||
};
|
||||
let webrender_image = self.get_webrender_image_for_paint_worklet(state,
|
||||
style,
|
||||
paint_worklet,
|
||||
size);
|
||||
if let Some(webrender_image) = webrender_image {
|
||||
self.build_display_list_for_webrender_image(state,
|
||||
style,
|
||||
display_list_section,
|
||||
&bounds,
|
||||
&clip,
|
||||
webrender_image,
|
||||
i);
|
||||
}
|
||||
}
|
||||
Either::Second(Image::Rect(_)) => {
|
||||
// TODO: Implement `-moz-image-rect`
|
||||
@ -1088,30 +1099,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
fn build_display_list_for_background_image(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &LocalClip,
|
||||
image_url: &ServoUrl,
|
||||
index: usize) {
|
||||
let webrender_image = state.layout_context
|
||||
.get_webrender_image_for_url(self.node,
|
||||
image_url.clone(),
|
||||
UsePlaceholder::No);
|
||||
|
||||
if let Some(webrender_image) = webrender_image {
|
||||
self.build_display_list_for_webrender_image(state,
|
||||
style,
|
||||
display_list_section,
|
||||
absolute_bounds,
|
||||
clip,
|
||||
webrender_image,
|
||||
index);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_display_list_for_webrender_image(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
@ -1249,34 +1236,14 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
|
||||
}
|
||||
|
||||
fn build_display_list_for_background_paint_worklet(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &LocalClip,
|
||||
paint_worklet: &PaintWorklet,
|
||||
index: usize)
|
||||
fn get_webrender_image_for_paint_worklet(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
style: &ComputedValues,
|
||||
paint_worklet: &PaintWorklet,
|
||||
size_in_au: Size2D<Au>)
|
||||
-> Option<WebRenderImageInfo>
|
||||
{
|
||||
// This should be the "concrete object size" of the fragment.
|
||||
// https://drafts.css-houdini.org/css-paint-api/#draw-a-paint-image
|
||||
// https://drafts.csswg.org/css-images-3/#concrete-object-size
|
||||
// Experimentally, chrome is using the size in px of the box,
|
||||
// including padding, but not border or margin, so we follow suit.
|
||||
// https://github.com/w3c/css-houdini-drafts/issues/417
|
||||
let unbordered_box = self.border_box - style.logical_border_width();
|
||||
let device_pixel_ratio = state.layout_context.style_context.device_pixel_ratio();
|
||||
let unbordered_box_size_in_au = unbordered_box.size.to_physical(style.writing_mode);
|
||||
let background_size = get_cyclic(&style.get_background().background_size.0, index).clone();
|
||||
let size_in_au = match background_size {
|
||||
BackgroundSize::Explicit { width, height } => {
|
||||
Size2D::new(MaybeAuto::from_style(width, unbordered_box_size_in_au.width)
|
||||
.specified_or_default(unbordered_box_size_in_au.width),
|
||||
MaybeAuto::from_style(height, unbordered_box_size_in_au.height)
|
||||
.specified_or_default(unbordered_box_size_in_au.height))
|
||||
},
|
||||
_ => unbordered_box_size_in_au,
|
||||
};
|
||||
let size_in_px = TypedSize2D::new(size_in_au.width.to_f32_px(), size_in_au.height.to_f32_px());
|
||||
|
||||
// TODO: less copying.
|
||||
@ -1294,7 +1261,10 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
.collect();
|
||||
painter.draw_a_paint_image(size_in_px, device_pixel_ratio, properties, arguments)
|
||||
},
|
||||
None => return debug!("Worklet {} called before registration.", name),
|
||||
None => {
|
||||
debug!("Worklet {} called before registration.", name);
|
||||
return None;
|
||||
},
|
||||
};
|
||||
|
||||
let webrender_image = WebRenderImageInfo {
|
||||
@ -1309,13 +1279,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
state.layout_context.get_webrender_image_for_url(self.node, url, UsePlaceholder::No);
|
||||
}
|
||||
|
||||
self.build_display_list_for_webrender_image(state,
|
||||
style,
|
||||
display_list_section,
|
||||
absolute_bounds,
|
||||
clip,
|
||||
webrender_image,
|
||||
index);
|
||||
Some(webrender_image)
|
||||
}
|
||||
|
||||
fn convert_linear_gradient(&self,
|
||||
@ -1541,6 +1505,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
BorderPaintingMode::Hidden => return,
|
||||
}
|
||||
if border.is_zero() {
|
||||
// TODO: check if image-border-outset is zero
|
||||
return
|
||||
}
|
||||
|
||||
@ -1631,8 +1596,33 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||
}
|
||||
}
|
||||
}
|
||||
Either::Second(Image::PaintWorklet(..)) => {
|
||||
// TODO: Handle border-image with `paint()`.
|
||||
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
|
||||
// TODO: this size should be increased by border-image-outset
|
||||
let size = self.border_box.size.to_physical(style.writing_mode);
|
||||
let webrender_image = self.get_webrender_image_for_paint_worklet(state,
|
||||
style,
|
||||
paint_worklet,
|
||||
size);
|
||||
if let Some(webrender_image) = webrender_image {
|
||||
let corners = &border_style_struct.border_image_slice.offsets;
|
||||
|
||||
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
||||
base: base,
|
||||
border_widths: border.to_physical(style.writing_mode),
|
||||
details: BorderDetails::Image(ImageBorder {
|
||||
image: webrender_image,
|
||||
fill: border_style_struct.border_image_slice.fill,
|
||||
slice: SideOffsets2D::new(corners.0.resolve(webrender_image.height),
|
||||
corners.1.resolve(webrender_image.width),
|
||||
corners.2.resolve(webrender_image.height),
|
||||
corners.3.resolve(webrender_image.width)),
|
||||
// TODO(gw): Support border-image-outset
|
||||
outset: SideOffsets2D::zero(),
|
||||
repeat_horizontal: convert_repeat_mode(border_style_struct.border_image_repeat.0),
|
||||
repeat_vertical: convert_repeat_mode(border_style_struct.border_image_repeat.1),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
}
|
||||
Either::Second(Image::Rect(..)) => {
|
||||
// TODO: Handle border-image with `-moz-image-rect`.
|
||||
|
Loading…
Reference in New Issue
Block a user