mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #15905 - mephisto41:add-border-gradient, r=emilio
Add gradient border support. webrender add gradient border support in https://github.com/servo/webrender/pull/953. This pr add support in servo. --- <!-- 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 <!-- Either: --> - [X] These changes do not require tests because it should be covered by wpt <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15905) <!-- Reviewable:end -->
This commit is contained in:
commit
fd8127b23b
6 changed files with 174 additions and 31 deletions
|
@ -886,10 +886,7 @@ pub struct IframeDisplayItem {
|
|||
|
||||
/// Paints a gradient.
|
||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||
pub struct GradientDisplayItem {
|
||||
/// Fields common to all display items.
|
||||
pub base: BaseDisplayItem,
|
||||
|
||||
pub struct Gradient {
|
||||
/// The start point of the gradient (computed during display list construction).
|
||||
pub start_point: Point2D<Au>,
|
||||
|
||||
|
@ -900,6 +897,15 @@ pub struct GradientDisplayItem {
|
|||
pub stops: Vec<GradientStop>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, HeapSizeOf, 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,
|
||||
}
|
||||
|
||||
/// A normal border, supporting CSS border styles.
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||
pub struct NormalBorder {
|
||||
|
@ -939,11 +945,22 @@ pub struct ImageBorder {
|
|||
pub repeat_vertical: webrender_traits::RepeatMode,
|
||||
}
|
||||
|
||||
/// A border that is made of linear gradient
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, 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>,
|
||||
}
|
||||
|
||||
/// Specifies the type of border
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||
pub enum BorderDetails {
|
||||
Normal(NormalBorder),
|
||||
Image(ImageBorder),
|
||||
Gradient(GradientBorder),
|
||||
}
|
||||
|
||||
/// Paints a border.
|
||||
|
|
|
@ -20,6 +20,7 @@ use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
|
|||
use flow_ref::FlowRef;
|
||||
use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
|
||||
use fragment::{SpecificFragmentInfo, TruncatedFragmentInfo};
|
||||
use gfx::display_list;
|
||||
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDetails};
|
||||
use gfx::display_list::{BorderDisplayItem, ImageBorder, NormalBorder};
|
||||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
|
||||
|
@ -350,6 +351,12 @@ pub trait FragmentDisplayListBuilding {
|
|||
image_url: &ServoUrl,
|
||||
background_index: usize);
|
||||
|
||||
fn convert_gradient(&self,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
gradient: &Gradient,
|
||||
style: &ServoComputedValues)
|
||||
-> Option<display_list::Gradient>;
|
||||
|
||||
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
||||
/// to the appropriate section of the display list.
|
||||
fn build_display_list_for_background_gradient(&self,
|
||||
|
@ -831,20 +838,13 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_display_list_for_background_gradient(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &ClippingRegion,
|
||||
gradient: &Gradient,
|
||||
style: &ServoComputedValues) {
|
||||
let mut clip = clip.clone();
|
||||
clip.intersect_rect(absolute_bounds);
|
||||
|
||||
|
||||
fn convert_gradient(&self,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
gradient: &Gradient,
|
||||
style: &ServoComputedValues) -> Option<display_list::Gradient> {
|
||||
// FIXME: Repeating gradients aren't implemented yet.
|
||||
if gradient.repeating {
|
||||
return;
|
||||
return None;
|
||||
}
|
||||
let angle = if let GradientKind::Linear(angle_or_corner) = gradient.gradient_kind {
|
||||
match angle_or_corner {
|
||||
|
@ -869,7 +869,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
} else {
|
||||
// FIXME: Radial gradients aren't implemented yet.
|
||||
return;
|
||||
return None;
|
||||
};
|
||||
|
||||
// Get correct gradient line length, based on:
|
||||
|
@ -953,19 +953,39 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
let center = Point2D::new(absolute_bounds.origin.x + absolute_bounds.size.width / 2,
|
||||
absolute_bounds.origin.y + absolute_bounds.size.height / 2);
|
||||
|
||||
let base = state.create_base_display_item(absolute_bounds,
|
||||
&clip,
|
||||
self.node,
|
||||
style.get_cursor(Cursor::Default),
|
||||
display_list_section);
|
||||
let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem {
|
||||
base: base,
|
||||
Some(display_list::Gradient {
|
||||
start_point: center - delta,
|
||||
end_point: center + delta,
|
||||
stops: stops,
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
state.add_display_item(gradient_display_item);
|
||||
fn build_display_list_for_background_gradient(&self,
|
||||
state: &mut DisplayListBuildState,
|
||||
display_list_section: DisplayListSection,
|
||||
absolute_bounds: &Rect<Au>,
|
||||
clip: &ClippingRegion,
|
||||
gradient: &Gradient,
|
||||
style: &ServoComputedValues) {
|
||||
let mut clip = clip.clone();
|
||||
clip.intersect_rect(absolute_bounds);
|
||||
|
||||
let grad = self.convert_gradient(absolute_bounds, gradient, style);
|
||||
|
||||
if let Some(x) = grad {
|
||||
let base = state.create_base_display_item(absolute_bounds,
|
||||
&clip,
|
||||
self.node,
|
||||
style.get_cursor(Cursor::Default),
|
||||
display_list_section);
|
||||
|
||||
let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem {
|
||||
base: base,
|
||||
gradient: x,
|
||||
});
|
||||
|
||||
state.add_display_item(gradient_display_item);
|
||||
}
|
||||
}
|
||||
|
||||
fn build_display_list_for_box_shadow_if_applicable(&self,
|
||||
|
@ -1076,8 +1096,28 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}),
|
||||
}));
|
||||
}
|
||||
Some(computed::Image::Gradient(..)) => {
|
||||
// TODO(gw): Handle border-image with gradient.
|
||||
Some(computed::Image::Gradient(ref gradient)) => {
|
||||
match gradient.gradient_kind {
|
||||
GradientKind::Linear(_) => {
|
||||
let grad = self.convert_gradient(&bounds, gradient, style);
|
||||
|
||||
if let Some(x) = grad {
|
||||
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
||||
base: base,
|
||||
border_widths: border.to_physical(style.writing_mode),
|
||||
details: BorderDetails::Gradient(display_list::GradientBorder {
|
||||
gradient: x,
|
||||
|
||||
// TODO(gw): Support border-image-outset
|
||||
outset: SideOffsets2D::zero(),
|
||||
}),
|
||||
}));
|
||||
}
|
||||
}
|
||||
GradientKind::Radial(_, _) => {
|
||||
// TODO(gw): Handle border-image with radial gradient.
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(computed::Image::ImageRect(..)) => {
|
||||
// TODO: Handle border-image with `-moz-image-rect`.
|
||||
|
|
|
@ -351,20 +351,30 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
BorderDetails::Gradient(ref gradient) => {
|
||||
webrender_traits::BorderDetails::Gradient(webrender_traits::GradientBorder {
|
||||
gradient: builder.create_gradient(
|
||||
gradient.gradient.start_point.to_pointf(),
|
||||
gradient.gradient.end_point.to_pointf(),
|
||||
gradient.gradient.stops.clone(),
|
||||
ExtendMode::Clamp),
|
||||
outset: gradient.outset,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
builder.push_border(rect, clip, widths, details);
|
||||
}
|
||||
DisplayItem::Gradient(ref item) => {
|
||||
let rect = item.base.bounds.to_rectf();
|
||||
let start_point = item.start_point.to_pointf();
|
||||
let end_point = item.end_point.to_pointf();
|
||||
let start_point = item.gradient.start_point.to_pointf();
|
||||
let end_point = item.gradient.end_point.to_pointf();
|
||||
let clip = item.base.clip.to_clip_region(builder);
|
||||
builder.push_gradient(rect,
|
||||
clip,
|
||||
start_point,
|
||||
end_point,
|
||||
item.stops.clone(),
|
||||
item.gradient.stops.clone(),
|
||||
ExtendMode::Clamp);
|
||||
}
|
||||
DisplayItem::Line(..) => {
|
||||
|
|
|
@ -755,6 +755,18 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/border-image-linear-gradient.html": [
|
||||
[
|
||||
"/_mozilla/css/border-image-linear-gradient.html",
|
||||
[
|
||||
[
|
||||
"/_mozilla/css/border-image-linear-gradient-ref.html",
|
||||
"=="
|
||||
]
|
||||
],
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/border_black_ridge_a.html": [
|
||||
[
|
||||
"/_mozilla/css/border_black_ridge_a.html",
|
||||
|
@ -6993,6 +7005,11 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/border-image-linear-gradient-ref.html": [
|
||||
[
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/border_black_solid.html": [
|
||||
[
|
||||
{}
|
||||
|
@ -20351,6 +20368,14 @@
|
|||
"d0bf8fafec5ff2c0cfde8f0d47083ca23b745588",
|
||||
"support"
|
||||
],
|
||||
"css/border-image-linear-gradient-ref.html": [
|
||||
"3c1b61477c8a3cb7befc3ab81b80a128b142e3f1",
|
||||
"support"
|
||||
],
|
||||
"css/border-image-linear-gradient.html": [
|
||||
"40ea388a8a920eaecb2d0d12f998ed60ac3b56e8",
|
||||
"reftest"
|
||||
],
|
||||
"css/border_black_groove.html": [
|
||||
"42912352ee8f09ae0ddbac3dce35294dc8608bbe",
|
||||
"reftest_node"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>test of border-image-source: linear-gradient</title>
|
||||
<style>
|
||||
table { margin: 0; padding: 0; border-spacing: 0; empty-cells: show; }
|
||||
td { padding: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col style="width: 30px">
|
||||
<col style="width: 90px">
|
||||
<col style="width: 30px">
|
||||
<tr style="height: 30px">
|
||||
<td style="background-image: linear-gradient(red, #CC0033); background-size:30px 30px;"></td>
|
||||
<td style="background-image: linear-gradient(red, #CC0033); background-size:90px 30px;"></td>
|
||||
<td style="background-image: linear-gradient(red, #CC0033); background-size:30px 30px;"></td>
|
||||
</tr>
|
||||
<tr style="height: 90px">
|
||||
<td style="background-image: linear-gradient(#CC0033, #3300CC); background-size:30px 90px;"></td>
|
||||
<td style="background: white"></td>
|
||||
<td style="background-image: linear-gradient(#CC0033, #3300CC); background-size:30px 90px;"></td>
|
||||
</tr>
|
||||
<tr style="height: 30px">
|
||||
<td style="background-image: linear-gradient(#3300CC, blue); background-size:30px 30px;"></td>
|
||||
<td style="background-image: linear-gradient(#3300CC, blue); background-size:90px 30px;"></td>
|
||||
<td style="background-image: linear-gradient(#3300CC, blue); background-size:30px 30px;"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<link rel="match" href="border-image-linear-gradient-ref.html">
|
||||
<html lang="en-US">
|
||||
<head>
|
||||
<title>test of border-image-source: linear-gradient</title>
|
||||
<style>
|
||||
div.border {
|
||||
border: 30px solid black;
|
||||
border-image: linear-gradient(red, blue) 10;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="border"></div>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue