mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
layout: support tiled gradients
Use background-size, background-position properties to render CSS gradients. Some cleanup in display_list_builder.rs related to gradient calculations. Adds two wpt tests for tiled gradients. Note: For now even gradients with background-repeat: no-repeat are repeated. Sometimes the gradient is not repeated everywhere. Enable vars-background-shorthand-001.html CSS test.
This commit is contained in:
parent
80341b291b
commit
9502e9f42a
9 changed files with 353 additions and 164 deletions
|
@ -720,6 +720,15 @@ pub struct GradientDisplayItem {
|
||||||
|
|
||||||
/// Contains all gradient data. Included start, end point and color stops.
|
/// Contains all gradient data. Included start, end point and color stops.
|
||||||
pub gradient: Gradient,
|
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: Size2D<Au>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Paints a radial gradient.
|
/// Paints a radial gradient.
|
||||||
|
@ -745,6 +754,15 @@ pub struct RadialGradientDisplayItem {
|
||||||
|
|
||||||
/// Contains all gradient data.
|
/// Contains all gradient data.
|
||||||
pub gradient: RadialGradient,
|
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: Size2D<Au>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A normal border, supporting CSS border styles.
|
/// A normal border, supporting CSS border styles.
|
||||||
|
|
|
@ -503,21 +503,6 @@ pub trait FragmentDisplayListBuilding {
|
||||||
size: Size2D<Au>)
|
size: Size2D<Au>)
|
||||||
-> Option<WebRenderImageInfo>;
|
-> Option<WebRenderImageInfo>;
|
||||||
|
|
||||||
fn convert_linear_gradient(&self,
|
|
||||||
bounds: &Rect<Au>,
|
|
||||||
stops: &[GradientItem],
|
|
||||||
direction: &LineDirection,
|
|
||||||
repeating: bool)
|
|
||||||
-> display_list::Gradient;
|
|
||||||
|
|
||||||
fn convert_radial_gradient(&self,
|
|
||||||
bounds: &Rect<Au>,
|
|
||||||
stops: &[GradientItem],
|
|
||||||
shape: &EndingShape,
|
|
||||||
center: &Position,
|
|
||||||
repeating: bool)
|
|
||||||
-> display_list::RadialGradient;
|
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
/// Adds the display items necessary to paint the background linear gradient of this fragment
|
||||||
/// to the appropriate section of the display list.
|
/// to the appropriate section of the display list.
|
||||||
fn build_display_list_for_background_gradient(&self,
|
fn build_display_list_for_background_gradient(&self,
|
||||||
|
@ -526,7 +511,8 @@ pub trait FragmentDisplayListBuilding {
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &LocalClip,
|
clip: &LocalClip,
|
||||||
gradient: &Gradient,
|
gradient: &Gradient,
|
||||||
style: &ComputedValues);
|
style: &ComputedValues,
|
||||||
|
index: usize);
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the borders of this fragment to a display list if
|
/// Adds the display items necessary to paint the borders of this fragment to a display list if
|
||||||
/// necessary.
|
/// necessary.
|
||||||
|
@ -819,6 +805,120 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
|
||||||
stops
|
stops
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn convert_linear_gradient(size: Size2D<Au>,
|
||||||
|
stops: &[GradientItem],
|
||||||
|
direction: LineDirection,
|
||||||
|
repeating: bool)
|
||||||
|
-> display_list::Gradient {
|
||||||
|
let angle = match direction {
|
||||||
|
LineDirection::Angle(angle) => angle.radians(),
|
||||||
|
LineDirection::Horizontal(x) => {
|
||||||
|
match x {
|
||||||
|
X::Left => Angle::Deg(270.).radians(),
|
||||||
|
X::Right => Angle::Deg(90.).radians(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
LineDirection::Vertical(y) => {
|
||||||
|
match y {
|
||||||
|
Y::Top => Angle::Deg(0.).radians(),
|
||||||
|
Y::Bottom => Angle::Deg(180.).radians(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
LineDirection::Corner(horizontal, vertical) => {
|
||||||
|
// This the angle for one of the diagonals of the box. Our angle
|
||||||
|
// will either be this one, this one + PI, or one of the other
|
||||||
|
// two perpendicular angles.
|
||||||
|
let atan = (size.height.to_f32_px() /
|
||||||
|
size.width.to_f32_px()).atan();
|
||||||
|
match (horizontal, vertical) {
|
||||||
|
(X::Right, Y::Bottom)
|
||||||
|
=> f32::consts::PI - atan,
|
||||||
|
(X::Left, Y::Bottom)
|
||||||
|
=> f32::consts::PI + atan,
|
||||||
|
(X::Right, Y::Top)
|
||||||
|
=> atan,
|
||||||
|
(X::Left, Y::Top)
|
||||||
|
=> -atan,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get correct gradient line length, based on:
|
||||||
|
// https://drafts.csswg.org/css-images-3/#linear-gradients
|
||||||
|
let dir = Point2D::new(angle.sin(), -angle.cos());
|
||||||
|
|
||||||
|
let line_length = (dir.x * size.width.to_f32_px()).abs() +
|
||||||
|
(dir.y * size.height.to_f32_px()).abs();
|
||||||
|
|
||||||
|
let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
|
||||||
|
|
||||||
|
// This is the vector between the center and the ending point; i.e. half
|
||||||
|
// of the distance between the starting point and the ending point.
|
||||||
|
let delta = Vector2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
|
||||||
|
Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
|
||||||
|
|
||||||
|
// This is the length of the gradient line.
|
||||||
|
let length = Au::from_f32_px(
|
||||||
|
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
|
||||||
|
|
||||||
|
let mut stops = convert_gradient_stops(stops, length);
|
||||||
|
|
||||||
|
// Only clamped gradients need to be fixed because in repeating gradients
|
||||||
|
// there is no "first" or "last" stop because they repeat infinitly in
|
||||||
|
// both directions, so the rendering is always correct.
|
||||||
|
if !repeating {
|
||||||
|
fix_gradient_stops(&mut stops);
|
||||||
|
}
|
||||||
|
|
||||||
|
let center = Point2D::new(size.width / 2, size.height / 2);
|
||||||
|
|
||||||
|
display_list::Gradient {
|
||||||
|
start_point: center - delta,
|
||||||
|
end_point: center + delta,
|
||||||
|
stops: stops,
|
||||||
|
repeating: repeating,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_radial_gradient(size: Size2D<Au>,
|
||||||
|
stops: &[GradientItem],
|
||||||
|
shape: EndingShape,
|
||||||
|
center: Position,
|
||||||
|
repeating: bool)
|
||||||
|
-> display_list::RadialGradient {
|
||||||
|
let center = Point2D::new(center.horizontal.to_used_value(size.width),
|
||||||
|
center.vertical.to_used_value(size.height));
|
||||||
|
let radius = match shape {
|
||||||
|
GenericEndingShape::Circle(Circle::Radius(length)) => {
|
||||||
|
let length = Au::from(length);
|
||||||
|
Size2D::new(length, length)
|
||||||
|
},
|
||||||
|
GenericEndingShape::Circle(Circle::Extent(extent)) => {
|
||||||
|
convert_circle_size_keyword(extent, &size, ¢er)
|
||||||
|
},
|
||||||
|
GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
|
||||||
|
Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height))
|
||||||
|
},
|
||||||
|
GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => {
|
||||||
|
convert_ellipse_size_keyword(extent, &size, ¢er)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut stops = convert_gradient_stops(stops, radius.width);
|
||||||
|
// Repeating gradients have no last stops that can be ignored. So
|
||||||
|
// fixup is not necessary but may actually break the gradient.
|
||||||
|
if !repeating {
|
||||||
|
fix_gradient_stops(&mut stops);
|
||||||
|
}
|
||||||
|
|
||||||
|
display_list::RadialGradient {
|
||||||
|
center: center,
|
||||||
|
radius: radius,
|
||||||
|
stops: stops,
|
||||||
|
repeating: repeating,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
/// Duplicate the first and last stops if necessary.
|
/// Duplicate the first and last stops if necessary.
|
||||||
///
|
///
|
||||||
|
@ -1026,7 +1126,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
&absolute_bounds,
|
&absolute_bounds,
|
||||||
&clip,
|
&clip,
|
||||||
gradient,
|
gradient,
|
||||||
style);
|
style,
|
||||||
|
i);
|
||||||
}
|
}
|
||||||
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() {
|
||||||
|
@ -1310,136 +1411,37 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
Some(webrender_image)
|
Some(webrender_image)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_linear_gradient(&self,
|
|
||||||
bounds: &Rect<Au>,
|
|
||||||
stops: &[GradientItem],
|
|
||||||
direction: &LineDirection,
|
|
||||||
repeating: bool)
|
|
||||||
-> display_list::Gradient {
|
|
||||||
let angle = match *direction {
|
|
||||||
LineDirection::Angle(angle) => angle.radians(),
|
|
||||||
LineDirection::Horizontal(x) => {
|
|
||||||
match x {
|
|
||||||
X::Left => Angle::Deg(270.).radians(),
|
|
||||||
X::Right => Angle::Deg(90.).radians(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LineDirection::Vertical(y) => {
|
|
||||||
match y {
|
|
||||||
Y::Top => Angle::Deg(0.).radians(),
|
|
||||||
Y::Bottom => Angle::Deg(180.).radians(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
LineDirection::Corner(horizontal, vertical) => {
|
|
||||||
// This the angle for one of the diagonals of the box. Our angle
|
|
||||||
// will either be this one, this one + PI, or one of the other
|
|
||||||
// two perpendicular angles.
|
|
||||||
let atan = (bounds.size.height.to_f32_px() /
|
|
||||||
bounds.size.width.to_f32_px()).atan();
|
|
||||||
match (horizontal, vertical) {
|
|
||||||
(X::Right, Y::Bottom)
|
|
||||||
=> f32::consts::PI - atan,
|
|
||||||
(X::Left, Y::Bottom)
|
|
||||||
=> f32::consts::PI + atan,
|
|
||||||
(X::Right, Y::Top)
|
|
||||||
=> atan,
|
|
||||||
(X::Left, Y::Top)
|
|
||||||
=> -atan,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get correct gradient line length, based on:
|
|
||||||
// https://drafts.csswg.org/css-images-3/#linear-gradients
|
|
||||||
let dir = Point2D::new(angle.sin(), -angle.cos());
|
|
||||||
|
|
||||||
let line_length = (dir.x * bounds.size.width.to_f32_px()).abs() +
|
|
||||||
(dir.y * bounds.size.height.to_f32_px()).abs();
|
|
||||||
|
|
||||||
let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
|
|
||||||
|
|
||||||
// This is the vector between the center and the ending point; i.e. half
|
|
||||||
// of the distance between the starting point and the ending point.
|
|
||||||
let delta = Vector2D::new(Au::from_f32_px(dir.x * inv_dir_length * line_length / 2.0),
|
|
||||||
Au::from_f32_px(dir.y * inv_dir_length * line_length / 2.0));
|
|
||||||
|
|
||||||
// This is the length of the gradient line.
|
|
||||||
let length = Au::from_f32_px(
|
|
||||||
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
|
|
||||||
|
|
||||||
let mut stops = convert_gradient_stops(stops, length);
|
|
||||||
|
|
||||||
// Only clamped gradients need to be fixed because in repeating gradients
|
|
||||||
// there is no "first" or "last" stop because they repeat infinitly in
|
|
||||||
// both directions, so the rendering is always correct.
|
|
||||||
if !repeating {
|
|
||||||
fix_gradient_stops(&mut stops);
|
|
||||||
}
|
|
||||||
|
|
||||||
let center = Point2D::new(bounds.size.width / 2, bounds.size.height / 2);
|
|
||||||
|
|
||||||
display_list::Gradient {
|
|
||||||
start_point: center - delta,
|
|
||||||
end_point: center + delta,
|
|
||||||
stops: stops,
|
|
||||||
repeating: repeating,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn convert_radial_gradient(&self,
|
|
||||||
bounds: &Rect<Au>,
|
|
||||||
stops: &[GradientItem],
|
|
||||||
shape: &EndingShape,
|
|
||||||
center: &Position,
|
|
||||||
repeating: bool)
|
|
||||||
-> display_list::RadialGradient {
|
|
||||||
let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
|
|
||||||
center.vertical.to_used_value(bounds.size.height));
|
|
||||||
let radius = match *shape {
|
|
||||||
GenericEndingShape::Circle(Circle::Radius(length)) => {
|
|
||||||
let length = Au::from(length);
|
|
||||||
Size2D::new(length, length)
|
|
||||||
},
|
|
||||||
GenericEndingShape::Circle(Circle::Extent(extent)) => {
|
|
||||||
convert_circle_size_keyword(extent, &bounds.size, ¢er)
|
|
||||||
},
|
|
||||||
GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
|
|
||||||
Size2D::new(x.to_used_value(bounds.size.width), y.to_used_value(bounds.size.height))
|
|
||||||
},
|
|
||||||
GenericEndingShape::Ellipse(Ellipse::Extent(extent)) => {
|
|
||||||
convert_ellipse_size_keyword(extent, &bounds.size, ¢er)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut stops = convert_gradient_stops(stops, radius.width);
|
|
||||||
// Repeating gradients have no last stops that can be ignored. So
|
|
||||||
// fixup is not necessary but may actually break the gradient.
|
|
||||||
if !repeating {
|
|
||||||
fix_gradient_stops(&mut stops);
|
|
||||||
}
|
|
||||||
|
|
||||||
display_list::RadialGradient {
|
|
||||||
center: center,
|
|
||||||
radius: radius,
|
|
||||||
stops: stops,
|
|
||||||
repeating: repeating,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_display_list_for_background_gradient(&self,
|
fn build_display_list_for_background_gradient(&self,
|
||||||
state: &mut DisplayListBuildState,
|
state: &mut DisplayListBuildState,
|
||||||
display_list_section: DisplayListSection,
|
display_list_section: DisplayListSection,
|
||||||
absolute_bounds: &Rect<Au>,
|
absolute_bounds: &Rect<Au>,
|
||||||
clip: &LocalClip,
|
clip: &LocalClip,
|
||||||
gradient: &Gradient,
|
gradient: &Gradient,
|
||||||
style: &ComputedValues) {
|
style: &ComputedValues,
|
||||||
|
index: usize) {
|
||||||
|
let bg = style.get_background();
|
||||||
|
let bg_size = get_cyclic(&bg.background_size.0, index).clone();
|
||||||
|
let bg_position_x = get_cyclic(&bg.background_position_x.0, index).clone();
|
||||||
|
let bg_position_y = get_cyclic(&bg.background_position_y.0, index).clone();
|
||||||
let border = self.border_width().to_physical(style.writing_mode);
|
let border = self.border_width().to_physical(style.writing_mode);
|
||||||
|
|
||||||
let mut bounds = *absolute_bounds;
|
let mut bounds = *absolute_bounds;
|
||||||
bounds.origin.x = bounds.origin.x + border.left;
|
bounds.origin.x = bounds.origin.x + border.left + bg_position_x.to_used_value(bounds.size.width);
|
||||||
bounds.origin.y = bounds.origin.y + border.top;
|
bounds.origin.y = bounds.origin.y + border.top + bg_position_y.to_used_value(bounds.size.height);
|
||||||
bounds.size.width = bounds.size.width - border.horizontal();
|
bounds.size.width = bounds.size.width - border.horizontal();
|
||||||
bounds.size.height = bounds.size.height - border.vertical();
|
bounds.size.height = bounds.size.height - border.vertical();
|
||||||
|
|
||||||
|
let tile = match bg_size {
|
||||||
|
BackgroundSize::Cover | BackgroundSize::Contain => bounds.size,
|
||||||
|
BackgroundSize::Explicit { width, height } => {
|
||||||
|
Size2D::new(
|
||||||
|
MaybeAuto::from_style(width, bounds.size.width)
|
||||||
|
.specified_or_default(bounds.size.width),
|
||||||
|
MaybeAuto::from_style(height, bounds.size.height)
|
||||||
|
.specified_or_default(bounds.size.height))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let base = state.create_base_display_item(&bounds,
|
let base = state.create_base_display_item(&bounds,
|
||||||
*clip,
|
*clip,
|
||||||
self.node,
|
self.node,
|
||||||
|
@ -1447,18 +1449,21 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
display_list_section);
|
display_list_section);
|
||||||
|
|
||||||
let display_item = match gradient.kind {
|
let display_item = match gradient.kind {
|
||||||
GradientKind::Linear(ref angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let gradient = self.convert_linear_gradient(&bounds,
|
let gradient = convert_linear_gradient(
|
||||||
|
tile,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
angle_or_corner,
|
angle_or_corner,
|
||||||
gradient.repeating);
|
gradient.repeating);
|
||||||
DisplayItem::Gradient(Box::new(GradientDisplayItem {
|
DisplayItem::Gradient(Box::new(GradientDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
|
tile: tile,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
GradientKind::Radial(ref shape, ref center, _angle) => {
|
GradientKind::Radial(shape, center, _angle) => {
|
||||||
let gradient = self.convert_radial_gradient(&bounds,
|
let gradient = convert_radial_gradient(
|
||||||
|
tile,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
shape,
|
shape,
|
||||||
center,
|
center,
|
||||||
|
@ -1466,6 +1471,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem {
|
DisplayItem::RadialGradient(Box::new(RadialGradientDisplayItem {
|
||||||
base: base,
|
base: base,
|
||||||
gradient: gradient,
|
gradient: gradient,
|
||||||
|
tile: tile,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1594,9 +1600,9 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
Either::Second(Image::Gradient(ref gradient)) => {
|
Either::Second(Image::Gradient(ref gradient)) => {
|
||||||
match gradient.kind {
|
match gradient.kind {
|
||||||
GradientKind::Linear(angle_or_corner) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let grad = self.convert_linear_gradient(&bounds,
|
let grad = convert_linear_gradient(bounds.size,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
&angle_or_corner,
|
angle_or_corner,
|
||||||
gradient.repeating);
|
gradient.repeating);
|
||||||
|
|
||||||
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
|
state.add_display_item(DisplayItem::Border(Box::new(BorderDisplayItem {
|
||||||
|
@ -1610,8 +1616,8 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}),
|
}),
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
GradientKind::Radial(ref shape, ref center, _angle) => {
|
GradientKind::Radial(shape, center, _angle) => {
|
||||||
let grad = self.convert_radial_gradient(&bounds,
|
let grad = convert_radial_gradient(bounds.size,
|
||||||
&gradient.items[..],
|
&gradient.items[..],
|
||||||
shape,
|
shape,
|
||||||
center,
|
center,
|
||||||
|
|
|
@ -428,7 +428,6 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
builder.push_border(&self.prim_info(), widths, details);
|
builder.push_border(&self.prim_info(), widths, details);
|
||||||
}
|
}
|
||||||
DisplayItem::Gradient(ref item) => {
|
DisplayItem::Gradient(ref item) => {
|
||||||
let rect = item.base.bounds;
|
|
||||||
let start_point = item.gradient.start_point.to_pointf();
|
let start_point = item.gradient.start_point.to_pointf();
|
||||||
let end_point = item.gradient.end_point.to_pointf();
|
let end_point = item.gradient.end_point.to_pointf();
|
||||||
let extend_mode = if item.gradient.repeating {
|
let extend_mode = if item.gradient.repeating {
|
||||||
|
@ -442,11 +441,10 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
extend_mode);
|
extend_mode);
|
||||||
builder.push_gradient(&self.prim_info(),
|
builder.push_gradient(&self.prim_info(),
|
||||||
gradient,
|
gradient,
|
||||||
rect.size.to_sizef(),
|
item.tile.to_sizef(),
|
||||||
webrender_api::LayoutSize::zero());
|
webrender_api::LayoutSize::zero());
|
||||||
}
|
}
|
||||||
DisplayItem::RadialGradient(ref item) => {
|
DisplayItem::RadialGradient(ref item) => {
|
||||||
let rect = item.base.bounds;
|
|
||||||
let center = item.gradient.center.to_pointf();
|
let center = item.gradient.center.to_pointf();
|
||||||
let radius = item.gradient.radius.to_sizef();
|
let radius = item.gradient.radius.to_sizef();
|
||||||
let extend_mode = if item.gradient.repeating {
|
let extend_mode = if item.gradient.repeating {
|
||||||
|
@ -460,7 +458,7 @@ impl WebRenderDisplayItemConverter for DisplayItem {
|
||||||
extend_mode);
|
extend_mode);
|
||||||
builder.push_radial_gradient(&self.prim_info(),
|
builder.push_radial_gradient(&self.prim_info(),
|
||||||
gradient,
|
gradient,
|
||||||
rect.size.to_sizef(),
|
item.tile.to_sizef(),
|
||||||
webrender_api::LayoutSize::zero());
|
webrender_api::LayoutSize::zero());
|
||||||
}
|
}
|
||||||
DisplayItem::Line(ref item) => {
|
DisplayItem::Line(ref item) => {
|
||||||
|
|
|
@ -112809,6 +112809,30 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"css/css-images/tiled-gradients.html": [
|
||||||
|
[
|
||||||
|
"/css/css-images/tiled-gradients.html",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/css/css-images/tiled-gradients-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"css/css-images/tiled-radial-gradients.html": [
|
||||||
|
[
|
||||||
|
"/css/css-images/tiled-radial-gradients.html",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"/css/css-images/tiled-radial-gradients-ref.html",
|
||||||
|
"=="
|
||||||
|
]
|
||||||
|
],
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"css/css-logical/cascading-001.html": [
|
"css/css-logical/cascading-001.html": [
|
||||||
[
|
[
|
||||||
"/css/css-logical/cascading-001.html",
|
"/css/css-logical/cascading-001.html",
|
||||||
|
@ -239776,6 +239800,16 @@
|
||||||
{}
|
{}
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"css/css-images/tiled-gradients-ref.html": [
|
||||||
|
[
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"css/css-images/tiled-radial-gradients-ref.html": [
|
||||||
|
[
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
],
|
||||||
"css/css-lists/OWNERS": [
|
"css/css-lists/OWNERS": [
|
||||||
[
|
[
|
||||||
{}
|
{}
|
||||||
|
@ -481858,6 +481892,22 @@
|
||||||
"078e1dd6dd61d36cec239ed75d02051f61fe60a5",
|
"078e1dd6dd61d36cec239ed75d02051f61fe60a5",
|
||||||
"support"
|
"support"
|
||||||
],
|
],
|
||||||
|
"css/css-images/tiled-gradients-ref.html": [
|
||||||
|
"47f9512fa5139fd9cdd66f0d191e8f71ad04317a",
|
||||||
|
"support"
|
||||||
|
],
|
||||||
|
"css/css-images/tiled-gradients.html": [
|
||||||
|
"fcc12e47fba2a938fca012e90fcfc6aa1877185e",
|
||||||
|
"reftest"
|
||||||
|
],
|
||||||
|
"css/css-images/tiled-radial-gradients-ref.html": [
|
||||||
|
"9033e28e4607cbcee67e37d97c2611a8ce5f19c4",
|
||||||
|
"support"
|
||||||
|
],
|
||||||
|
"css/css-images/tiled-radial-gradients.html": [
|
||||||
|
"4b4b4756c2f605ab4dca092775cc39b0705efda9",
|
||||||
|
"reftest"
|
||||||
|
],
|
||||||
"css/css-lists/OWNERS": [
|
"css/css-lists/OWNERS": [
|
||||||
"d9c8054b356c9273a054a83abeb9be0626c23921",
|
"d9c8054b356c9273a054a83abeb9be0626c23921",
|
||||||
"support"
|
"support"
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[vars-background-shorthand-001.html]
|
|
||||||
type: reftest
|
|
||||||
expected: FAIL
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
.bar {
|
||||||
|
width: 400px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.box {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border: 0px;
|
||||||
|
background-image: linear-gradient(to bottom left, red 50%, transparent 50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bar">
|
||||||
|
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
|
||||||
|
</div>
|
||||||
|
<div class="bar">
|
||||||
|
<div class="box"></div><div class="box"></div><div class="box"></div><div class="box"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Eight Red Triangles on White Ground (with gradients)</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background-size">
|
||||||
|
<meta name="assert" content="Gradients are correctly repeated.">
|
||||||
|
<link rel="match" href="tiled-gradients-ref.html">
|
||||||
|
<style>
|
||||||
|
#gradient {
|
||||||
|
width: 400px;
|
||||||
|
height: 200px;
|
||||||
|
background-size: 25% 50%;
|
||||||
|
background-image: linear-gradient(to bottom left, red 50%, transparent 50%);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="gradient"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer {
|
||||||
|
position: absolute;
|
||||||
|
width: 600px;
|
||||||
|
height: 200px;
|
||||||
|
background-color: aquamarine;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left, #right {
|
||||||
|
position: absolute;
|
||||||
|
width: 300px;
|
||||||
|
height: 200px;
|
||||||
|
background-image: radial-gradient(closest-side, red 40%, transparent 40%)
|
||||||
|
|
||||||
|
}
|
||||||
|
#left {
|
||||||
|
left: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right {
|
||||||
|
left: 380px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="outer">
|
||||||
|
<div id="left"></div>
|
||||||
|
<div id="right"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Two Ellipses with Custom Placement (with gradients)</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#propdef-background-size">
|
||||||
|
<meta name="assert" content="Gradients are correctly repeated.">
|
||||||
|
<link rel="match" href="tiled-radial-gradients-ref.html">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
#gradient {
|
||||||
|
position: absolute;
|
||||||
|
width: 600px;
|
||||||
|
height: 200px;
|
||||||
|
left: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
background-color: aquamarine;
|
||||||
|
background-image: radial-gradient(closest-side, red 40%, transparent 40%);
|
||||||
|
background-size: 300px 200px;
|
||||||
|
background-position: 80px 0px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="gradient"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue