Refactor Gradient

In a similar way to Position, now specified and computed gradients share
a common Gradient type defined in style::values::generics::image.

This allows us to reuse most code for many style traits like ToCss,
HasViewportPercentage and ToComputedValue.

The test changes are the fallout of the disappearance of AngleOrCorner::None,
which align our code to the spec for serialisation, where components that can
be omitted should be omitted.
This commit is contained in:
Anthony Ramine 2017-05-12 17:28:05 +02:00
parent f2aaba685b
commit abef5da9d8
10 changed files with 742 additions and 888 deletions

View file

@ -192,9 +192,8 @@ impl nsStyleImage {
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE, NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE};
use gecko_bindings::structs::{NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER, NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE};
use gecko_bindings::structs::nsStyleCoord;
use values::computed::{AngleOrCorner, GradientKind, GradientShape, LengthOrKeyword};
use values::computed::LengthOrPercentageOrKeyword;
use values::specified::SizeKeyword;
use values::computed::image::LineDirection;
use values::generics::image::{Circle, Ellipse, EndingShape, GradientKind, ShapeExtent};
use values::specified::position::{X, Y};
let stop_count = gradient.items.len();
@ -204,7 +203,7 @@ impl nsStyleImage {
}
let gecko_gradient = match gradient.kind {
GradientKind::Linear(angle_or_corner) => {
GradientKind::Linear(direction) => {
let gecko_gradient = unsafe {
Gecko_CreateGradient(NS_STYLE_GRADIENT_SHAPE_LINEAR as u8,
NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER as u8,
@ -213,15 +212,15 @@ impl nsStyleImage {
stop_count as u32)
};
match angle_or_corner {
AngleOrCorner::Angle(angle) => {
match direction {
LineDirection::Angle(angle) => {
unsafe {
(*gecko_gradient).mAngle.set(angle);
(*gecko_gradient).mBgPosX.set_value(CoordDataValue::None);
(*gecko_gradient).mBgPosY.set_value(CoordDataValue::None);
}
},
AngleOrCorner::Corner(horiz, vert) => {
LineDirection::Corner(horiz, vert) => {
let percent_x = match horiz {
X::Left => 0.0,
X::Right => 1.0,
@ -245,28 +244,28 @@ impl nsStyleImage {
GradientKind::Radial(shape, position) => {
let keyword_to_gecko_size = |keyword| {
match keyword {
SizeKeyword::ClosestSide => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
SizeKeyword::FarthestSide => NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE,
SizeKeyword::ClosestCorner => NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER,
SizeKeyword::FarthestCorner => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
SizeKeyword::Contain => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
SizeKeyword::Cover => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
ShapeExtent::ClosestSide => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
ShapeExtent::FarthestSide => NS_STYLE_GRADIENT_SIZE_FARTHEST_SIDE,
ShapeExtent::ClosestCorner => NS_STYLE_GRADIENT_SIZE_CLOSEST_CORNER,
ShapeExtent::FarthestCorner => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
ShapeExtent::Contain => NS_STYLE_GRADIENT_SIZE_CLOSEST_SIDE,
ShapeExtent::Cover => NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER,
}
};
let (gecko_shape, gecko_size) = match shape {
GradientShape::Circle(ref length) => {
let size = match *length {
LengthOrKeyword::Keyword(keyword) => {
keyword_to_gecko_size(keyword)
EndingShape::Circle(ref circle) => {
let size = match *circle {
Circle::Extent(extent) => {
keyword_to_gecko_size(extent)
},
_ => NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE,
};
(NS_STYLE_GRADIENT_SHAPE_CIRCULAR as u8, size as u8)
},
GradientShape::Ellipse(ref length) => {
let size = match *length {
LengthOrPercentageOrKeyword::Keyword(keyword) => {
keyword_to_gecko_size(keyword)
EndingShape::Ellipse(ref ellipse) => {
let size = match *ellipse {
Ellipse::Extent(extent) => {
keyword_to_gecko_size(extent)
},
_ => NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE,
};
@ -291,22 +290,19 @@ impl nsStyleImage {
// Setting radius values depending shape
match shape {
GradientShape::Circle(length) => {
if let LengthOrKeyword::Length(len) = length {
unsafe {
(*gecko_gradient).mRadiusX.set_value(CoordDataValue::Coord(len.0));
(*gecko_gradient).mRadiusY.set_value(CoordDataValue::Coord(len.0));
}
EndingShape::Circle(Circle::Radius(length)) => {
unsafe {
(*gecko_gradient).mRadiusX.set_value(CoordDataValue::Coord(length.0));
(*gecko_gradient).mRadiusY.set_value(CoordDataValue::Coord(length.0));
}
},
GradientShape::Ellipse(length) => {
if let LengthOrPercentageOrKeyword::LengthOrPercentage(first_len, second_len) = length {
unsafe {
(*gecko_gradient).mRadiusX.set(first_len);
(*gecko_gradient).mRadiusY.set(second_len);
}
EndingShape::Ellipse(Ellipse::Radii(x, y)) => {
unsafe {
(*gecko_gradient).mRadiusX.set(x);
(*gecko_gradient).mRadiusY.set(y);
}
},
_ => {},
}
unsafe {
(*gecko_gradient).mBgPosX.set(position.horizontal);