Bug 1207734 - Part 7.c. (stylo) Implement scale property styling. draft
authorcku <cku@mozilla.com>
Wed, 06 Dec 2017 22:35:48 +0800
changeset 720524 8558501a4507949da1b1d3327a8c377f88f3b185
parent 720523 4ece494bab3a9c12068024efbdea2bd93bc91063
child 720525 bb07dfcf187e740672a2eb1099665125159a2337
push id95569
push userbmo:cku@mozilla.com
push dateMon, 15 Jan 2018 18:29:35 +0000
bugs1207734
milestone59.0a1
Bug 1207734 - Part 7.c. (stylo) Implement scale property styling. MozReview-Commit-ID: 6yIhT78Skh6
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/computed/transform.rs
servo/components/style/values/generics/transform.rs
servo/components/style/values/specified/mod.rs
servo/components/style/values/specified/transform.rs
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -3127,17 +3127,18 @@ fn static_assert() {
                           transition-timing-function transition-property
                           page-break-before page-break-after rotate
                           scroll-snap-points-x scroll-snap-points-y
                           scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate
                           perspective-origin -moz-binding will-change
                           overscroll-behavior-x overscroll-behavior-y
                           overflow-clip-box-inline overflow-clip-box-block
                           perspective-origin -moz-binding will-change
-                          shape-outside contain touch-action translate""" %>
+                          shape-outside contain touch-action translate
+                          scale""" %>
 <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
 
     // We manually-implement the |display| property until we get general
     // infrastructure for preffing certain values.
     <% display_keyword = Keyword("display", "inline block inline-block table inline-table table-row-group " +
                                             "table-header-group table-footer-group table-row table-column-group " +
                                             "table-column table-cell table-caption list-item flex none " +
                                             "inline-flex grid inline-grid ruby ruby-base ruby-base-container " +
@@ -3554,16 +3555,17 @@ fn static_assert() {
                 .expect("Expected length or percentage for horizontal value of perspective-origin"),
             vertical: LengthOrPercentage::from_gecko_style_coord(&self.gecko.mPerspectiveOrigin[1])
                 .expect("Expected length or percentage for vertical value of perspective-origin"),
         }
     }
 
     ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
     ${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')}
+    ${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')}
 
     pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
         use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
         use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_OPACITY;
         use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_SCROLL;
         use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_TRANSFORM;
         use properties::PropertyId;
         use properties::longhands::will_change::computed_value::T;
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -401,16 +401,23 @@
 
 ${helpers.predefined_type("translate", "Translate",
                           "generics::transform::Translate::None",
                           animation_value_type="ComputedValue",
                           flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
                           gecko_pref="layout.css.individual-transform.enabled",
                           spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
 
+${helpers.predefined_type("scale", "Scale",
+                          "generics::transform::Scale::None",
+                          animation_value_type="ComputedValue",
+                          flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
+                          gecko_pref="layout.css.individual-transform.enabled",
+                          spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")}
+
 // CSSOM View Module
 // https://www.w3.org/TR/cssom-view-1/
 ${helpers.single_keyword("scroll-behavior",
                          "auto smooth",
                          gecko_pref="layout.css.scroll-behavior.property-enabled",
                          products="gecko",
                          spec="https://drafts.csswg.org/cssom-view/#propdef-scroll-behavior",
                          animation_value_type="discrete")}
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -60,17 +60,17 @@ pub use self::list::ListStyleType;
 pub use self::outline::OutlineStyle;
 pub use self::percentage::Percentage;
 pub use self::position::{Position, GridAutoFlow, GridTemplateAreas};
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
 pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
 pub use self::table::XSpan;
 pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing};
 pub use self::time::Time;
-pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate};
+pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate, Scale};
 pub use self::ui::MozForceBrokenImageIcon;
 
 #[cfg(feature = "gecko")]
 pub mod align;
 pub mod angle;
 pub mod background;
 pub mod basic_shape;
 pub mod border;
--- a/servo/components/style/values/computed/transform.rs
+++ b/servo/components/style/values/computed/transform.rs
@@ -11,16 +11,17 @@ use values::animated::ToAnimatedZero;
 use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Percentage};
 use values::computed::{LengthOrNumber, LengthOrPercentageOrNumber};
 use values::generics::transform::{self, Matrix as GenericMatrix, Matrix3D as GenericMatrix3D};
 use values::generics::transform::{Transform as GenericTransform, TransformOperation as GenericTransformOperation};
 use values::generics::transform::TimingFunction as GenericTimingFunction;
 use values::generics::transform::TransformOrigin as GenericTransformOrigin;
 use values::generics::transform::Rotate as GenericRotate;
 use values::generics::transform::Translate as GenericTranslate;
+use values::generics::transform::Scale as GenericScale;
 
 /// A single operation in a computed CSS `transform`
 pub type TransformOperation = GenericTransformOperation<
     Angle,
     Number,
     Length,
     Integer,
     LengthOrNumber,
@@ -347,9 +348,40 @@ impl Translate {
                 GenericTranslate::Translate(tx, ty)
             },
             GenericTransformOperation::Translate3D(tx, ty, tz) => {
                 GenericTranslate::Translate3D(tx, ty, tz)
             },
             ref x => unreachable!("Found unexpected value for translate: {:?}", x),
         }
     }
-}
\ No newline at end of file
+}
+
+/// A computed CSS `scale`
+pub type Scale = GenericScale<Number>;
+
+impl Scale {
+    /// Convert TransformOperation to Scale.
+    pub fn to_transform_operation(&self) -> Option<TransformOperation> {
+        match *self {
+            GenericScale::None => None,
+            GenericScale::ScaleX(sx) => Some(GenericTransformOperation::ScaleX(sx)),
+            GenericScale::Scale(sx, sy) => Some(GenericTransformOperation::Scale(sx, Some(sy))),
+            GenericScale::Scale3D(sx, sy, sz) => Some(GenericTransformOperation::Scale3D(sx, sy, sz)),
+        }
+    }
+
+    /// Convert Scale to TransformOperation.
+    pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
+        match *operation {
+            GenericTransformOperation::ScaleX(sx) => {
+                GenericScale::ScaleX(sx)
+            },
+            GenericTransformOperation::Scale(sx, Some(sy)) => {
+                GenericScale::Scale(sx, sy)
+            },
+            GenericTransformOperation::Scale3D(sx, sy, sz) => {
+                GenericScale::Scale3D(sx, sy, sz)
+            },
+            ref x => unreachable!("Found unexpected value for scale: {:?}", x),
+        }
+    }
+}
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -779,9 +779,25 @@ pub enum Translate<LengthOrPercentage, L
     /// 'none'
     None,
     /// '<length-percentage>'
     TranslateX(LengthOrPercentage),
     /// '<length-percentage> <length-percentage>'
     Translate(LengthOrPercentage, LengthOrPercentage),
     /// '<length-percentage> <length-percentage> <length>'
     Translate3D(LengthOrPercentage, LengthOrPercentage, Length),
+}
+
+#[derive(ToComputedValue, Animate, ComputeSquaredDistance, ToAnimatedZero)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
+/// A value of the `Scale` property
+///
+/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
+pub enum Scale<Number> {
+    /// 'none'
+    None,
+    /// '<number>'
+    ScaleX(Number),
+    /// '<number>{2}'
+    Scale(Number, Number),
+    /// '<number>{3}'
+    Scale3D(Number, Number, Number),
 }
\ No newline at end of file
--- a/servo/components/style/values/specified/mod.rs
+++ b/servo/components/style/values/specified/mod.rs
@@ -57,17 +57,17 @@ pub use self::rect::LengthOrNumberRect;
 pub use self::percentage::Percentage;
 pub use self::position::{Position, PositionComponent, GridAutoFlow, GridTemplateAreas};
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
 pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
 pub use self::table::XSpan;
 pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine};
 pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing};
 pub use self::time::Time;
-pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate};
+pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate, Scale};
 pub use self::ui::MozForceBrokenImageIcon;
 pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent;
 
 #[cfg(feature = "gecko")]
 pub mod align;
 pub mod angle;
 pub mod background;
 pub mod basic_shape;
--- a/servo/components/style/values/specified/transform.rs
+++ b/servo/components/style/values/specified/transform.rs
@@ -9,16 +9,17 @@ use parser::{Parse, ParserContext};
 use selectors::parser::SelectorParseErrorKind;
 use style_traits::{ParseError, StyleParseErrorKind};
 use values::computed::{Context, LengthOrPercentage as ComputedLengthOrPercentage};
 use values::computed::{Percentage as ComputedPercentage, ToComputedValue};
 use values::computed::transform::TimingFunction as ComputedTimingFunction;
 use values::generics::transform::{Matrix3D, Transform as GenericTransform};
 use values::generics::transform::Rotate as GenericRotate;
 use values::generics::transform::Translate as GenericTranslate;
+use values::generics::transform::Scale as GenericScale;
 use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, Matrix};
 use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin};
 use values::generics::transform::TransformOperation as GenericTransformOperation;
 use values::specified::{self, Angle, Number, Length, Integer};
 use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
 use values::specified::position::{Side, X, Y};
 
 /// A single operation in a specified CSS `transform`
@@ -559,8 +560,36 @@ impl Parse for Translate {
             // translate: <length-percentage> <length-percentage>'
             return Ok(GenericTranslate::Translate(tx, ty));
         }
 
         // 'translate: <length-percentage> '
         Ok(GenericTranslate::TranslateX(tx))
     }
 }
+
+/// A specified CSS `scale`
+pub type Scale = GenericScale<Number>;
+
+impl Parse for Scale {
+    fn parse<'i, 't>(
+        context: &ParserContext,
+        input: &mut Parser<'i, 't>
+    ) -> Result<Self, ParseError<'i>> {
+        if input.try(|i| i.expect_ident_matching("none")).is_ok() {
+            return Ok(GenericScale::None);
+        }
+
+        let sx = Number::parse(context, input)?;
+        if let Some(sy) = input.try(|i| Number::parse(context, i)).ok() {
+            if let Some(sz) = input.try(|i| Number::parse(context, i)).ok() {
+                // 'scale: <length-percentage> <length-percentage> <length>'
+                return Ok(GenericScale::Scale3D(sx, sy, sz));
+            }
+
+            // 'scale: <length-percentage> <length-percentage>'
+            return Ok(GenericScale::Scale(sx, sy));
+        }
+
+        // 'scale: <length-percentage>'
+        Ok(GenericScale::ScaleX(sx))
+    }
+}