Skip to content

Commit

Permalink
Implement serialization of linear-gradient the same ways as in Gecko
Browse files Browse the repository at this point in the history
  • Loading branch information
ferjm committed Jul 13, 2017
1 parent 9d74ae8 commit 6ae4bf6
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 49 deletions.
14 changes: 13 additions & 1 deletion components/layout/display_list_builder.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
43 changes: 29 additions & 14 deletions components/style/gecko/conversions.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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) => {
Expand All @@ -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
Expand All @@ -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);
}
}
},
Expand Down Expand Up @@ -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
Expand Down
73 changes: 39 additions & 34 deletions components/style/values/computed/image.rs
Expand Up @@ -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.
Expand All @@ -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,
}
}

Expand All @@ -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 ")?;
Expand Down Expand Up @@ -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)
Expand All @@ -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)
},
Expand All @@ -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
Expand All @@ -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),
Expand All @@ -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))
Expand Down

0 comments on commit 6ae4bf6

Please sign in to comment.