From 6ae4bf6ee817b2df642beaf8ed7fafbb7ad4e62e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Thu, 13 Jul 2017 12:20:30 +0200 Subject: [PATCH] Implement serialization of linear-gradient the same ways as in Gecko --- components/layout/display_list_builder.rs | 14 ++++- components/style/gecko/conversions.rs | 43 ++++++++----- components/style/values/computed/image.rs | 73 ++++++++++++----------- 3 files changed, 81 insertions(+), 49 deletions(-) diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index dad561ce2ad3..42fab82567b2 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -56,7 +56,7 @@ use style::properties::longhands::border_image_repeat::computed_value::RepeatKey use style::properties::style_structs; use style::servo::restyle_damage::REPAINT; use style::values::{Either, RGBA}; -use style::values::computed::{Gradient, GradientItem, LengthOrPercentage}; +use style::values::computed::{Angle, Gradient, GradientItem, LengthOrPercentage}; use style::values::computed::{LengthOrPercentageOrAuto, NumberOrPercentage, Position}; use style::values::computed::effects::SimpleShadow; use style::values::computed::image::{EndingShape, LineDirection}; @@ -1214,6 +1214,18 @@ impl FragmentDisplayListBuilding for Fragment { -> display_list::Gradient { let angle = match *direction { LineDirection::Angle(angle) => angle.radians(), + LineDirection::Horizontal(x) => { + match x { + X::Left => Angle::Degree(270.).radians(), + X::Right => Angle::Degree(90.).radians(), + } + }, + LineDirection::Vertical(y) => { + match y { + Y::Top => Angle::Degree(0.).radians(), + Y::Bottom => Angle::Degree(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 diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 6314069cb182..0bc666db0b10 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -15,6 +15,7 @@ use gecko_bindings::bindings::{Gecko_InitializeImageCropRect, Gecko_SetImageElem use gecko_bindings::structs::{nsCSSUnit, nsStyleCoord_CalcValue, nsStyleImage}; use gecko_bindings::structs::{nsresult, SheetType}; use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut}; +use std::f32::consts::PI; use stylesheets::{Origin, RulesMutateError}; use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto}; @@ -215,10 +216,35 @@ impl nsStyleImage { match direction { LineDirection::Angle(angle) => { + // PI radians (180deg) is ignored because it is the default value. + if angle.radians() != PI { + unsafe { + (*gecko_gradient).mAngle.set(angle); + } + } + }, + LineDirection::Horizontal(x) => { + let x = match x { + X::Left => 0.0, + X::Right => 1.0, + }; + unsafe { - (*gecko_gradient).mAngle.set(angle); - (*gecko_gradient).mBgPosX.set_value(CoordDataValue::None); - (*gecko_gradient).mBgPosY.set_value(CoordDataValue::None); + (*gecko_gradient).mBgPosX + .set_value(CoordDataValue::Percent(x)); + (*gecko_gradient).mBgPosY + .set_value(CoordDataValue::Percent(0.5)); + } + }, + LineDirection::Vertical(y) => { + // Y::Bottom (to bottom) is ignored because it is the default value. + if y == Y::Top { + unsafe { + (*gecko_gradient).mBgPosX + .set_value(CoordDataValue::Percent(0.5)); + (*gecko_gradient).mBgPosY + .set_value(CoordDataValue::Percent(0.0)); + } } }, LineDirection::Corner(horiz, vert) => { @@ -232,7 +258,6 @@ impl nsStyleImage { }; unsafe { - (*gecko_gradient).mAngle.set_value(CoordDataValue::None); (*gecko_gradient).mBgPosX .set_value(CoordDataValue::Percent(percent_x)); (*gecko_gradient).mBgPosY @@ -245,14 +270,9 @@ impl nsStyleImage { if let Some(position) = position { (*gecko_gradient).mBgPosX.set(position.horizontal); (*gecko_gradient).mBgPosY.set(position.vertical); - } else { - (*gecko_gradient).mBgPosX.set_value(CoordDataValue::None); - (*gecko_gradient).mBgPosY.set_value(CoordDataValue::None); } if let Some(angle) = angle { (*gecko_gradient).mAngle.set(angle); - } else { - (*gecko_gradient).mAngle.set_value(CoordDataValue::None); } } }, @@ -304,12 +324,7 @@ impl nsStyleImage { unsafe { if let Some(angle) = angle { (*gecko_gradient).mAngle.set(angle); - } else { - (*gecko_gradient).mAngle.set_value(CoordDataValue::None); } - - (*gecko_gradient).mBgPosX.set_value(CoordDataValue::None); - (*gecko_gradient).mBgPosY.set_value(CoordDataValue::None); } // Setting radius values depending shape diff --git a/components/style/values/computed/image.rs b/components/style/values/computed/image.rs index 2037640ef642..dc4a27f205fe 100644 --- a/components/style/values/computed/image.rs +++ b/components/style/values/computed/image.rs @@ -55,6 +55,10 @@ pub type GradientKind = GenericGradientKind< pub enum LineDirection { /// An angle. Angle(Angle), + /// A horizontal direction. + Horizontal(X), + /// A vertical direction. + Vertical(Y), /// A corner. Corner(X, Y), /// A Position and an Angle for legacy `-moz-` prefixed gradient. @@ -78,9 +82,11 @@ impl GenericLineDirection for LineDirection { fn points_downwards(&self) -> bool { match *self { LineDirection::Angle(angle) => angle.radians() == PI, + LineDirection::Vertical(Y::Bottom) => true, LineDirection::Corner(..) => false, #[cfg(feature = "gecko")] LineDirection::MozPosition(_, _) => false, + _ => false, } } @@ -89,6 +95,18 @@ impl GenericLineDirection for LineDirection { { match *self { LineDirection::Angle(ref angle) => angle.to_css(dest), + LineDirection::Horizontal(x) => { + if compat_mode == CompatMode::Modern { + dest.write_str("to ")?; + } + x.to_css(dest) + }, + LineDirection::Vertical(y) => { + if compat_mode == CompatMode::Modern { + dest.write_str("to ")?; + } + y.to_css(dest) + }, LineDirection::Corner(x, y) => { if compat_mode == CompatMode::Modern { dest.write_str("to ")?; @@ -116,38 +134,19 @@ impl GenericLineDirection for LineDirection { } } -impl SpecifiedLineDirection { - /// Takes a modern linear gradient angle and convert it to Gecko's old coordinate for - /// webkit-prefixed version - fn to_gecko_coordinate(modern_angle: f32, _compat_mode: CompatMode) -> f32 { - #[cfg(feature = "gecko")] - { - return match _compat_mode { - CompatMode::WebKit => -modern_angle + 270., - _ => modern_angle, - } - } - #[cfg(feature = "servo")] - modern_angle - } +impl ToComputedValue for SpecifiedLineDirection { + type ComputedValue = LineDirection; - /// Manually derived to_computed_value - fn to_computed_value(&self, context: &Context, compat_mode: CompatMode) -> LineDirection { + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match *self { SpecifiedLineDirection::Angle(ref angle) => { LineDirection::Angle(angle.to_computed_value(context)) }, - SpecifiedLineDirection::Horizontal(X::Left) => { - LineDirection::Angle(Angle::Degree(SpecifiedLineDirection::to_gecko_coordinate(270., compat_mode))) - }, - SpecifiedLineDirection::Horizontal(X::Right) => { - LineDirection::Angle(Angle::Degree(SpecifiedLineDirection::to_gecko_coordinate(90., compat_mode))) + SpecifiedLineDirection::Horizontal(x) => { + LineDirection::Horizontal(x) }, - SpecifiedLineDirection::Vertical(Y::Top) => { - LineDirection::Angle(Angle::Degree(SpecifiedLineDirection::to_gecko_coordinate(0., compat_mode))) - }, - SpecifiedLineDirection::Vertical(Y::Bottom) => { - LineDirection::Angle(Angle::Degree(SpecifiedLineDirection::to_gecko_coordinate(180., compat_mode))) + SpecifiedLineDirection::Vertical(y) => { + LineDirection::Vertical(y) }, SpecifiedLineDirection::Corner(x, y) => { LineDirection::Corner(x, y) @@ -160,11 +159,17 @@ impl SpecifiedLineDirection { } } - fn from_computed_value(computed: &LineDirection) -> Self { + fn from_computed_value(computed: &Self::ComputedValue) -> Self { match *computed { LineDirection::Angle(ref angle) => { SpecifiedLineDirection::Angle(ToComputedValue::from_computed_value(angle)) }, + LineDirection::Horizontal(x) => { + SpecifiedLineDirection::Horizontal(x) + }, + LineDirection::Vertical(y) => { + SpecifiedLineDirection::Vertical(y) + }, LineDirection::Corner(x, y) => { SpecifiedLineDirection::Corner(x, y) }, @@ -182,7 +187,7 @@ impl ToComputedValue for SpecifiedGradient { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { Self::ComputedValue { - kind: self.kind.to_computed_value(context, self.compat_mode), + kind: self.kind.to_computed_value(context), items: self.items.to_computed_value(context), repeating: self.repeating, compat_mode: self.compat_mode @@ -199,12 +204,13 @@ impl ToComputedValue for SpecifiedGradient { } } -impl SpecifiedGradientKind { - /// Manually derived to_computed_value - pub fn to_computed_value(&self, context: &Context, compat_mode: CompatMode) -> GradientKind { +impl ToComputedValue for SpecifiedGradientKind { + type ComputedValue = GradientKind; + + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match self { &GenericGradientKind::Linear(ref line_direction) => { - GenericGradientKind::Linear(line_direction.to_computed_value(context, compat_mode)) + GenericGradientKind::Linear(line_direction.to_computed_value(context)) }, &GenericGradientKind::Radial(ref ending_shape, ref position, ref angle) => { GenericGradientKind::Radial(ending_shape.to_computed_value(context), @@ -214,8 +220,7 @@ impl SpecifiedGradientKind { } } - /// Manually derived from_computed_value - pub fn from_computed_value(computed: &GradientKind) -> SpecifiedGradientKind { + fn from_computed_value(computed: &Self::ComputedValue) -> Self { match *computed { GenericGradientKind::Linear(line_direction) => { GenericGradientKind::Linear(SpecifiedLineDirection::from_computed_value(&line_direction))