mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Implemented paint worklets drawing to a border.
This commit is contained in:
parent
2b92a7e82d
commit
3f71be7d08
6 changed files with 91 additions and 101 deletions
|
@ -41,7 +41,6 @@ use range::Range;
|
||||||
use script_layout_interface::wrapper_traits::PseudoElementType;
|
use script_layout_interface::wrapper_traits::PseudoElementType;
|
||||||
use servo_config::opts;
|
use servo_config::opts;
|
||||||
use servo_geometry::max_rect;
|
use servo_geometry::max_rect;
|
||||||
use servo_url::ServoUrl;
|
|
||||||
use std::{cmp, f32};
|
use std::{cmp, f32};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
@ -393,17 +392,6 @@ pub trait FragmentDisplayListBuilding {
|
||||||
image: &WebRenderImageInfo, index: usize)
|
image: &WebRenderImageInfo, index: usize)
|
||||||
-> Size2D<Au>;
|
-> 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
|
/// Adds the display items necessary to paint a webrender image of this fragment to the
|
||||||
/// appropriate section of the display list.
|
/// appropriate section of the display list.
|
||||||
fn build_display_list_for_webrender_image(&self,
|
fn build_display_list_for_webrender_image(&self,
|
||||||
|
@ -415,16 +403,15 @@ pub trait FragmentDisplayListBuilding {
|
||||||
webrender_image: WebRenderImageInfo,
|
webrender_image: WebRenderImageInfo,
|
||||||
index: usize);
|
index: usize);
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background image created by this fragment's
|
/// Calculates the webrender image for a paint worklet.
|
||||||
/// worklet to the appropriate section of the display list.
|
/// Returns None if the worklet is not registered.
|
||||||
fn build_display_list_for_background_paint_worklet(&self,
|
/// 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,
|
state: &mut DisplayListBuildState,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
display_list_section: DisplayListSection,
|
|
||||||
absolute_bounds: &Rect<Au>,
|
|
||||||
clip: &LocalClip,
|
|
||||||
paint_worklet: &PaintWorklet,
|
paint_worklet: &PaintWorklet,
|
||||||
index: usize);
|
size: Size2D<Au>)
|
||||||
|
-> Option<WebRenderImageInfo>;
|
||||||
|
|
||||||
fn convert_linear_gradient(&self,
|
fn convert_linear_gradient(&self,
|
||||||
bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
|
@ -926,24 +913,48 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
Either::Second(Image::Url(ref image_url)) => {
|
Either::Second(Image::Url(ref image_url)) => {
|
||||||
if let Some(url) = image_url.url() {
|
if let Some(url) = image_url.url() {
|
||||||
self.build_display_list_for_background_image(state,
|
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,
|
style,
|
||||||
display_list_section,
|
display_list_section,
|
||||||
&bounds,
|
&bounds,
|
||||||
&clip,
|
&clip,
|
||||||
url,
|
webrender_image,
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
|
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
|
||||||
self.build_display_list_for_background_paint_worklet(state,
|
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,
|
style,
|
||||||
display_list_section,
|
display_list_section,
|
||||||
&bounds,
|
&bounds,
|
||||||
&clip,
|
&clip,
|
||||||
paint_worklet,
|
webrender_image,
|
||||||
i);
|
i);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Either::Second(Image::Rect(_)) => {
|
Either::Second(Image::Rect(_)) => {
|
||||||
// TODO: Implement `-moz-image-rect`
|
// TODO: Implement `-moz-image-rect`
|
||||||
}
|
}
|
||||||
|
@ -999,30 +1010,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,
|
fn build_display_list_for_webrender_image(&self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
|
@ -1160,34 +1147,14 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_background_paint_worklet(&self,
|
fn get_webrender_image_for_paint_worklet(&self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
style: &ComputedValues,
|
style: &ComputedValues,
|
||||||
display_list_section: DisplayListSection,
|
|
||||||
absolute_bounds: &Rect<Au>,
|
|
||||||
clip: &LocalClip,
|
|
||||||
paint_worklet: &PaintWorklet,
|
paint_worklet: &PaintWorklet,
|
||||||
index: usize)
|
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 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());
|
let size_in_px = TypedSize2D::new(size_in_au.width.to_f32_px(), size_in_au.height.to_f32_px());
|
||||||
|
|
||||||
// TODO: less copying.
|
// TODO: less copying.
|
||||||
|
@ -1205,7 +1172,10 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
.collect();
|
.collect();
|
||||||
painter.draw_a_paint_image(size_in_px, device_pixel_ratio, properties, arguments)
|
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 {
|
let webrender_image = WebRenderImageInfo {
|
||||||
|
@ -1220,13 +1190,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
state.layout_context.get_webrender_image_for_url(self.node, url, UsePlaceholder::No);
|
state.layout_context.get_webrender_image_for_url(self.node, url, UsePlaceholder::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.build_display_list_for_webrender_image(state,
|
Some(webrender_image)
|
||||||
style,
|
|
||||||
display_list_section,
|
|
||||||
absolute_bounds,
|
|
||||||
clip,
|
|
||||||
webrender_image,
|
|
||||||
index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_linear_gradient(&self,
|
fn convert_linear_gradient(&self,
|
||||||
|
@ -1450,6 +1414,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
BorderPaintingMode::Hidden => return,
|
BorderPaintingMode::Hidden => return,
|
||||||
}
|
}
|
||||||
if border.is_zero() {
|
if border.is_zero() {
|
||||||
|
// TODO: check if image-border-outset is zero
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1540,8 +1505,33 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Either::Second(Image::PaintWorklet(..)) => {
|
Either::Second(Image::PaintWorklet(ref paint_worklet)) => {
|
||||||
// TODO: Handle border-image with `paint()`.
|
// 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(..)) => {
|
Either::Second(Image::Rect(..)) => {
|
||||||
// TODO: Handle border-image with `-moz-image-rect`.
|
// TODO: Handle border-image with `-moz-image-rect`.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[geometry-border-image-001.html]
|
[geometry-border-image-001.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
bug: https://github.com/servo/servo/issues/1767
|
bug: https://github.com/servo/servo/issues/17861
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[geometry-border-image-002.html]
|
[geometry-border-image-002.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
bug: https://github.com/servo/servo/issues/17451
|
bug: https://github.com/servo/servo/issues/17860
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[geometry-border-image-003.html]
|
[geometry-border-image-003.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
bug: https://github.com/servo/servo/issues/17451
|
bug: https://github.com/servo/servo/issues/17860
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[geometry-border-image-004.html]
|
[geometry-border-image-004.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
bug: https://github.com/servo/servo/issues/17451
|
bug: https://github.com/servo/servo/issues/17860
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[geometry-border-image-005.html]
|
[geometry-border-image-005.html]
|
||||||
type: reftest
|
type: reftest
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
bug: https://github.com/w3c/web-platform-tests/issues/6610
|
bug: https://github.com/servo/servo/issues/17860
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue