mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Fix gradient math and positioning. Formatting.
Start adding repeating gradients.
This commit is contained in:
parent
6768614fdd
commit
803bc0395c
3 changed files with 175 additions and 179 deletions
|
@ -890,6 +890,9 @@ pub struct Gradient {
|
||||||
|
|
||||||
/// A list of color stops.
|
/// A list of color stops.
|
||||||
pub stops: Vec<GradientStop>,
|
pub stops: Vec<GradientStop>,
|
||||||
|
|
||||||
|
/// True if gradient repeats infinitly.
|
||||||
|
pub repeating: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||||
|
@ -912,6 +915,9 @@ pub struct RadialGradient {
|
||||||
|
|
||||||
/// A list of color stops.
|
/// A list of color stops.
|
||||||
pub stops: Vec<GradientStop>,
|
pub stops: Vec<GradientStop>,
|
||||||
|
|
||||||
|
/// True if gradient repeats infinitly.
|
||||||
|
pub repeating: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||||
|
@ -923,7 +929,6 @@ pub struct RadialGradientDisplayItem {
|
||||||
pub gradient: RadialGradient,
|
pub gradient: RadialGradient,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A normal border, supporting CSS border styles.
|
/// A normal border, supporting CSS border styles.
|
||||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||||
pub struct NormalBorder {
|
pub struct NormalBorder {
|
||||||
|
|
|
@ -59,7 +59,7 @@ use style::properties::style_structs;
|
||||||
use style::servo::restyle_damage::REPAINT;
|
use style::servo::restyle_damage::REPAINT;
|
||||||
use style::values::{Either, RGBA, computed};
|
use style::values::{Either, RGBA, computed};
|
||||||
use style::values::computed::{AngleOrCorner, Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
use style::values::computed::{AngleOrCorner, Gradient, GradientKind, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||||
use style::values::computed::{LengthOrKeyword, LengthOrPercentageOrKeyword, NumberOrPercentage};
|
use style::values::computed::{LengthOrKeyword, LengthOrPercentageOrKeyword, NumberOrPercentage, Position};
|
||||||
use style::values::computed::image::{ColorStop, EndingShape, SizeKeyword};
|
use style::values::computed::image::{ColorStop, EndingShape, SizeKeyword};
|
||||||
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
use style::values::specified::{HorizontalDirection, VerticalDirection};
|
||||||
use style_traits::CSSPixel;
|
use style_traits::CSSPixel;
|
||||||
|
@ -386,16 +386,22 @@ pub trait FragmentDisplayListBuilding {
|
||||||
image_url: &ServoUrl,
|
image_url: &ServoUrl,
|
||||||
background_index: usize);
|
background_index: usize);
|
||||||
|
|
||||||
fn convert_gradient(&self,
|
fn convert_linear_gradient(&self,
|
||||||
absolute_bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
gradient: &Gradient,
|
stops: &[ColorStop],
|
||||||
style: &ServoComputedValues)
|
angle_or_corner: &AngleOrCorner,
|
||||||
-> Option<display_list::Gradient>;
|
repeating: bool,
|
||||||
|
style: &ServoComputedValues)
|
||||||
|
-> display_list::Gradient;
|
||||||
|
|
||||||
fn convert_radial_gradient(&self,
|
fn convert_radial_gradient(&self,
|
||||||
gradient: &Gradient,
|
bounds: &Rect<Au>,
|
||||||
style: &ServoComputedValues)
|
stops: &[ColorStop],
|
||||||
-> Option<display_list::RadialGradient>;
|
shape: &EndingShape,
|
||||||
|
center: &Position,
|
||||||
|
repeating: bool,
|
||||||
|
style: &ServoComputedValues)
|
||||||
|
-> 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.
|
||||||
|
@ -667,78 +673,66 @@ fn convert_gradient_stops(gradient_stops: &[ColorStop],
|
||||||
|
|
||||||
/// Returns the the distance to the nearest or farthest corner depending on the comperator.
|
/// Returns the the distance to the nearest or farthest corner depending on the comperator.
|
||||||
fn get_distance_to_corner<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Au
|
fn get_distance_to_corner<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Au
|
||||||
where F: Fn(f32, f32) -> f32 {
|
where F: Fn(Au, Au) -> Au
|
||||||
let top_left = center.x.to_f32_px().hypot(center.y.to_f32_px());
|
{
|
||||||
let top_right = (size.width.to_f32_px() - center.x.to_f32_px()).hypot(center.y.to_f32_px());
|
let dist = get_distance_to_sides(size, center, cmp);
|
||||||
let bottom_right = (size.width.to_f32_px() - center.x.to_f32_px())
|
Au::from_f32_px(dist.width.to_f32_px().hypot(dist.height.to_f32_px()))
|
||||||
.hypot(size.height.to_f32_px() - center.y.to_f32_px());
|
|
||||||
let bottom_left = center.x.to_f32_px().hypot(size.height.to_f32_px() - center.y.to_f32_px());
|
|
||||||
Au::from_f32_px(cmp(cmp(top_left, top_right), cmp(bottom_right, bottom_left)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the distance to the nearest or farthest sides depending on the comparator.
|
/// Returns the distance to the nearest or farthest sides depending on the comparator.
|
||||||
///
|
///
|
||||||
/// The first return value is horizontal distance the second vertical distance.
|
/// The first return value is horizontal distance the second vertical distance.
|
||||||
fn get_distance_to_sides<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> (Au, Au)
|
fn get_distance_to_sides<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Size2D<Au>
|
||||||
where F: Fn(Au, Au) -> Au {
|
where F: Fn(Au, Au) -> Au
|
||||||
|
{
|
||||||
let top_side = center.y;
|
let top_side = center.y;
|
||||||
let right_side = size.width - center.x;
|
let right_side = size.width - center.x;
|
||||||
let bottom_side = size.height - center.y;
|
let bottom_side = size.height - center.y;
|
||||||
let left_side = center.x;
|
let left_side = center.x;
|
||||||
(cmp(left_side, right_side), cmp(top_side, bottom_side))
|
Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the radius for an ellipse with the same ratio as if it was matched to the sides.
|
/// Returns the radius for an ellipse with the same ratio as if it was matched to the sides.
|
||||||
fn get_scaled_radius<F>(radius: Au, size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Size2D<Au>
|
fn get_ellipse_radius<F>(size: &Size2D<Au>, center: &Point2D<Au>, cmp: F) -> Size2D<Au>
|
||||||
where F: Fn(Au, Au) -> Au {
|
where F: Fn(Au, Au) -> Au
|
||||||
let (horizontal, vertical) = get_distance_to_sides(size, center, cmp);
|
{
|
||||||
let factor = horizontal.to_f32_px() / vertical.to_f32_px();
|
let dist = get_distance_to_sides(size, center, cmp);
|
||||||
Size2D::new(radius.scale_by(factor), radius.scale_by(factor.recip()))
|
Size2D::new(dist.width.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0),
|
||||||
|
dist.height.scale_by(::std::f32::consts::FRAC_1_SQRT_2 * 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the radius of a radial gradient if it was not explicitly provided.
|
/// Determines the radius of a circle if it was not explictly provided.
|
||||||
///
|
|
||||||
/// https://drafts.csswg.org/css-images-3/#typedef-size
|
/// https://drafts.csswg.org/css-images-3/#typedef-size
|
||||||
fn convert_size_keyword(keyword: SizeKeyword,
|
fn convert_circle_size_keyword(keyword: SizeKeyword,
|
||||||
circle: bool,
|
size: &Size2D<Au>,
|
||||||
size: &Size2D<Au>,
|
center: &Point2D<Au>) -> Size2D<Au> {
|
||||||
center: &Point2D<Au>) -> Size2D<Au> {
|
use style::values::computed::image::SizeKeyword::*;
|
||||||
|
let radius = match keyword {
|
||||||
|
ClosestSide => {
|
||||||
|
let dist = get_distance_to_sides(size, center, ::std::cmp::min);
|
||||||
|
::std::cmp::min(dist.width, dist.height)
|
||||||
|
}
|
||||||
|
FarthestSide => {
|
||||||
|
let dist = get_distance_to_sides(size, center, ::std::cmp::max);
|
||||||
|
::std::cmp::max(dist.width, dist.height)
|
||||||
|
}
|
||||||
|
ClosestCorner => get_distance_to_corner(size, center, ::std::cmp::min),
|
||||||
|
FarthestCorner => get_distance_to_corner(size, center, ::std::cmp::max),
|
||||||
|
};
|
||||||
|
Size2D::new(radius, radius)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Determines the radius of an ellipse if it was not explictly provided.
|
||||||
|
/// https://drafts.csswg.org/css-images-3/#typedef-size
|
||||||
|
fn convert_ellipse_size_keyword(keyword: SizeKeyword,
|
||||||
|
size: &Size2D<Au>,
|
||||||
|
center: &Point2D<Au>) -> Size2D<Au> {
|
||||||
use style::values::computed::image::SizeKeyword::*;
|
use style::values::computed::image::SizeKeyword::*;
|
||||||
match keyword {
|
match keyword {
|
||||||
ClosestSide => {
|
ClosestSide => get_distance_to_sides(size, center, ::std::cmp::min),
|
||||||
let (horizontal, vertical) = get_distance_to_sides(size, center, ::std::cmp::min);
|
FarthestSide => get_distance_to_sides(size, center, ::std::cmp::max),
|
||||||
if circle {
|
ClosestCorner => get_ellipse_radius(size, center, ::std::cmp::min),
|
||||||
let radius = ::std::cmp::min(vertical, horizontal);
|
FarthestCorner => get_ellipse_radius(size, center, ::std::cmp::max),
|
||||||
Size2D::new(radius, radius)
|
|
||||||
} else {
|
|
||||||
Size2D::new(horizontal, vertical)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
FarthestSide => {
|
|
||||||
let (horizontal, vertical) = get_distance_to_sides(size, center, ::std::cmp::max);
|
|
||||||
if circle {
|
|
||||||
let radius = ::std::cmp::max(vertical, horizontal);
|
|
||||||
Size2D::new(radius, radius)
|
|
||||||
} else {
|
|
||||||
Size2D::new(horizontal, vertical)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ClosestCorner => {
|
|
||||||
let radius = get_distance_to_corner(size, center, f32::min);
|
|
||||||
if circle {
|
|
||||||
Size2D::new(radius, radius)
|
|
||||||
} else {
|
|
||||||
get_scaled_radius(radius, size, center, ::std::cmp::min)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FarthestCorner => {
|
|
||||||
let radius = get_distance_to_corner(size, center, f32::max);
|
|
||||||
if circle {
|
|
||||||
Size2D::new(radius, radius)
|
|
||||||
} else {
|
|
||||||
get_scaled_radius(radius, size, center, ::std::cmp::max)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1044,45 +1038,40 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_gradient(&self,
|
fn convert_linear_gradient(&self,
|
||||||
absolute_bounds: &Rect<Au>,
|
bounds: &Rect<Au>,
|
||||||
gradient: &Gradient,
|
stops: &[ColorStop],
|
||||||
style: &ServoComputedValues) -> Option<display_list::Gradient> {
|
angle_or_corner: &AngleOrCorner,
|
||||||
// FIXME: Repeating gradients aren't implemented yet.
|
repeating: bool,
|
||||||
if gradient.repeating {
|
style: &ServoComputedValues)
|
||||||
return None;
|
-> display_list::Gradient {
|
||||||
}
|
let angle = match *angle_or_corner {
|
||||||
let angle = if let GradientKind::Linear(angle_or_corner) = gradient.gradient_kind {
|
AngleOrCorner::Angle(angle) => angle.radians(),
|
||||||
match angle_or_corner {
|
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||||
AngleOrCorner::Angle(angle) => angle.radians(),
|
// This the angle for one of the diagonals of the box. Our angle
|
||||||
AngleOrCorner::Corner(horizontal, vertical) => {
|
// will either be this one, this one + PI, or one of the other
|
||||||
// This the angle for one of the diagonals of the box. Our angle
|
// two perpendicular angles.
|
||||||
// will either be this one, this one + PI, or one of the other
|
let atan = (bounds.size.height.to_f32_px() /
|
||||||
// two perpendicular angles.
|
bounds.size.width.to_f32_px()).atan();
|
||||||
let atan = (absolute_bounds.size.height.to_f32_px() /
|
match (horizontal, vertical) {
|
||||||
absolute_bounds.size.width.to_f32_px()).atan();
|
(HorizontalDirection::Right, VerticalDirection::Bottom)
|
||||||
match (horizontal, vertical) {
|
=> f32::consts::PI - atan,
|
||||||
(HorizontalDirection::Right, VerticalDirection::Bottom)
|
(HorizontalDirection::Left, VerticalDirection::Bottom)
|
||||||
=> f32::consts::PI - atan,
|
=> f32::consts::PI + atan,
|
||||||
(HorizontalDirection::Left, VerticalDirection::Bottom)
|
(HorizontalDirection::Right, VerticalDirection::Top)
|
||||||
=> f32::consts::PI + atan,
|
=> atan,
|
||||||
(HorizontalDirection::Right, VerticalDirection::Top)
|
(HorizontalDirection::Left, VerticalDirection::Top)
|
||||||
=> atan,
|
=> -atan,
|
||||||
(HorizontalDirection::Left, VerticalDirection::Top)
|
|
||||||
=> -atan,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get correct gradient line length, based on:
|
// Get correct gradient line length, based on:
|
||||||
// https://drafts.csswg.org/css-images-3/#linear-gradients
|
// https://drafts.csswg.org/css-images-3/#linear-gradients
|
||||||
let dir = Point2D::new(angle.sin(), -angle.cos());
|
let dir = Point2D::new(angle.sin(), -angle.cos());
|
||||||
|
|
||||||
let line_length = (dir.x * absolute_bounds.size.width.to_f32_px()).abs() +
|
let line_length = (dir.x * bounds.size.width.to_f32_px()).abs() +
|
||||||
(dir.y * absolute_bounds.size.height.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();
|
let inv_dir_length = 1.0 / (dir.x * dir.x + dir.y * dir.y).sqrt();
|
||||||
|
|
||||||
|
@ -1095,58 +1084,47 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let length = Au::from_f32_px(
|
let length = Au::from_f32_px(
|
||||||
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
|
(delta.x.to_f32_px() * 2.0).hypot(delta.y.to_f32_px() * 2.0));
|
||||||
|
|
||||||
let stops = convert_gradient_stops(&gradient.stops[..],
|
let stops = convert_gradient_stops(stops, length, style);
|
||||||
length,
|
|
||||||
style);
|
|
||||||
|
|
||||||
let center = Point2D::new(absolute_bounds.size.width / 2,
|
let center = Point2D::new(bounds.size.width / 2, bounds.size.height / 2);
|
||||||
absolute_bounds.size.height / 2);
|
|
||||||
|
|
||||||
Some(display_list::Gradient {
|
display_list::Gradient {
|
||||||
start_point: center - delta,
|
start_point: center - delta,
|
||||||
end_point: center + delta,
|
end_point: center + delta,
|
||||||
stops: stops,
|
stops: stops,
|
||||||
})
|
repeating: repeating,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_radial_gradient(&self,
|
fn convert_radial_gradient(&self,
|
||||||
gradient: &Gradient,
|
bounds: &Rect<Au>,
|
||||||
style: &ServoComputedValues) -> Option<display_list::RadialGradient> {
|
stops: &[ColorStop],
|
||||||
// FIXME: Repeating gradients aren't implemented yet.
|
shape: &EndingShape,
|
||||||
if gradient.repeating {
|
center: &Position,
|
||||||
return None;
|
repeating: bool,
|
||||||
}
|
style: &ServoComputedValues)
|
||||||
// FIXME(pcwalton, #2795): Get the real container size.
|
-> display_list::RadialGradient {
|
||||||
let container_size = Size2D::zero();
|
let center = Point2D::new(specified(center.horizontal, bounds.size.width),
|
||||||
let content_box = self.content_box().to_physical(style.writing_mode, container_size);
|
specified(center.vertical, bounds.size.height));
|
||||||
let origin = content_box.origin;
|
let radius = match *shape {
|
||||||
let size = content_box.size;
|
EndingShape::Circle(LengthOrKeyword::Length(length))
|
||||||
if let GradientKind::Radial(ref shape, ref center) = gradient.gradient_kind {
|
=> Size2D::new(length, length),
|
||||||
let center = Point2D::new(specified(center.horizontal, size.width),
|
EndingShape::Circle(LengthOrKeyword::Keyword(word))
|
||||||
specified(center.vertical, size.height));
|
=> convert_circle_size_keyword(word, &bounds.size, ¢er),
|
||||||
let radius = match *shape {
|
EndingShape::Ellipse(LengthOrPercentageOrKeyword::LengthOrPercentage(horizontal,
|
||||||
EndingShape::Circle(LengthOrKeyword::Length(length))
|
vertical))
|
||||||
=> Size2D::new(length, length),
|
=> Size2D::new(specified(horizontal, bounds.size.width),
|
||||||
EndingShape::Circle(LengthOrKeyword::Keyword(word))
|
specified(vertical, bounds.size.height)),
|
||||||
=> convert_size_keyword(word, true, &size, ¢er),
|
EndingShape::Ellipse(LengthOrPercentageOrKeyword::Keyword(word))
|
||||||
EndingShape::Ellipse(LengthOrPercentageOrKeyword::LengthOrPercentage(horizontal,
|
=> convert_ellipse_size_keyword(word, &bounds.size, ¢er),
|
||||||
vertical))
|
};
|
||||||
=> Size2D::new(specified(horizontal, size.width),
|
let length = Au::from_f32_px(radius.width.to_f32_px().hypot(radius.height.to_f32_px()));
|
||||||
specified(vertical, size.height)),
|
let stops = convert_gradient_stops(stops, length, style);
|
||||||
EndingShape::Ellipse(LengthOrPercentageOrKeyword::Keyword(word))
|
display_list::RadialGradient {
|
||||||
=> convert_size_keyword(word, false, &size, ¢er),
|
center: center,
|
||||||
};
|
radius: radius,
|
||||||
let length = Au::from_f32_px(radius.width.to_f32_px().hypot(radius.height.to_f32_px()));
|
stops: stops,
|
||||||
let stops = convert_gradient_stops(&gradient.stops[..],
|
repeating: repeating,
|
||||||
length,
|
|
||||||
style);
|
|
||||||
Some(display_list::RadialGradient {
|
|
||||||
center: origin + center,
|
|
||||||
radius: radius,
|
|
||||||
stops: stops,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1160,33 +1138,45 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
let mut clip = clip.clone();
|
let mut clip = clip.clone();
|
||||||
clip.intersect_rect(absolute_bounds);
|
clip.intersect_rect(absolute_bounds);
|
||||||
|
|
||||||
if let Some(x) = self.convert_gradient(absolute_bounds, gradient, style) {
|
let border = style.logical_border_width().to_physical(style.writing_mode);
|
||||||
let base = state.create_base_display_item(absolute_bounds,
|
let mut bounds = *absolute_bounds;
|
||||||
&clip,
|
bounds.origin.x += border.left;
|
||||||
self.node,
|
bounds.origin.y += border.top;
|
||||||
style.get_cursor(Cursor::Default),
|
bounds.size.width -= border.horizontal();
|
||||||
display_list_section);
|
bounds.size.height -= border.vertical();
|
||||||
|
|
||||||
let gradient_display_item = DisplayItem::Gradient(box GradientDisplayItem {
|
let base = state.create_base_display_item(&bounds,
|
||||||
base: base,
|
&clip,
|
||||||
gradient: x,
|
self.node,
|
||||||
});
|
style.get_cursor(Cursor::Default),
|
||||||
|
display_list_section);
|
||||||
|
|
||||||
state.add_display_item(gradient_display_item);
|
let display_item = match gradient.gradient_kind {
|
||||||
} else if let Some(x) = self.convert_radial_gradient(gradient, style) {
|
GradientKind::Linear(ref angle_or_corner) => {
|
||||||
let base = state.create_base_display_item(absolute_bounds,
|
let gradient = self.convert_linear_gradient(&bounds,
|
||||||
&clip,
|
&gradient.stops[..],
|
||||||
self.node,
|
angle_or_corner,
|
||||||
style.get_cursor(Cursor::Default),
|
gradient.repeating,
|
||||||
display_list_section);
|
style);
|
||||||
|
DisplayItem::Gradient(box GradientDisplayItem {
|
||||||
let gradient_display_item = DisplayItem::RadialGradient(box RadialGradientDisplayItem {
|
base: base,
|
||||||
base: base,
|
gradient: gradient,
|
||||||
gradient: x,
|
})
|
||||||
});
|
}
|
||||||
|
GradientKind::Radial(ref shape, ref center) => {
|
||||||
state.add_display_item(gradient_display_item);
|
let gradient = self.convert_radial_gradient(&bounds,
|
||||||
}
|
&gradient.stops[..],
|
||||||
|
shape,
|
||||||
|
center,
|
||||||
|
gradient.repeating,
|
||||||
|
style);
|
||||||
|
DisplayItem::RadialGradient(box RadialGradientDisplayItem {
|
||||||
|
base: base,
|
||||||
|
gradient: gradient,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
state.add_display_item(display_item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_for_box_shadow_if_applicable(&self,
|
fn build_display_list_for_box_shadow_if_applicable(&self,
|
||||||
|
@ -1299,21 +1289,23 @@ impl FragmentDisplayListBuilding for Fragment {
|
||||||
}
|
}
|
||||||
Some(computed::Image::Gradient(ref gradient)) => {
|
Some(computed::Image::Gradient(ref gradient)) => {
|
||||||
match gradient.gradient_kind {
|
match gradient.gradient_kind {
|
||||||
GradientKind::Linear(_) => {
|
GradientKind::Linear(angle_or_corner) => {
|
||||||
let grad = self.convert_gradient(&bounds, gradient, style);
|
let grad = self.convert_linear_gradient(&bounds,
|
||||||
|
&gradient.stops[..],
|
||||||
|
&angle_or_corner,
|
||||||
|
gradient.repeating,
|
||||||
|
style);
|
||||||
|
|
||||||
if let Some(x) = grad {
|
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
||||||
state.add_display_item(DisplayItem::Border(box BorderDisplayItem {
|
base: base,
|
||||||
base: base,
|
border_widths: border.to_physical(style.writing_mode),
|
||||||
border_widths: border.to_physical(style.writing_mode),
|
details: BorderDetails::Gradient(display_list::GradientBorder {
|
||||||
details: BorderDetails::Gradient(display_list::GradientBorder {
|
gradient: grad,
|
||||||
gradient: x,
|
|
||||||
|
|
||||||
// TODO(gw): Support border-image-outset
|
// TODO(gw): Support border-image-outset
|
||||||
outset: SideOffsets2D::zero(),
|
outset: SideOffsets2D::zero(),
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
GradientKind::Radial(_, _) => {
|
GradientKind::Radial(_, _) => {
|
||||||
// TODO(gw): Handle border-image with radial gradient.
|
// TODO(gw): Handle border-image with radial gradient.
|
||||||
|
|
|
@ -20,7 +20,6 @@ use values::specified::url::SpecifiedUrl;
|
||||||
|
|
||||||
pub use values::specified::SizeKeyword;
|
pub use values::specified::SizeKeyword;
|
||||||
|
|
||||||
|
|
||||||
impl ToComputedValue for specified::Image {
|
impl ToComputedValue for specified::Image {
|
||||||
type ComputedValue = Image;
|
type ComputedValue = Image;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue