diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index 987a95edb22..598e7d3cb87 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -190,6 +190,7 @@ partial interface CSSStyleDeclaration { [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backfaceVisibility; [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString backface-visibility; [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString rotate; + [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString translate; [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString direction; [CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString unicodeBidi; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a4de0ed7b5d..0c75b67afd7 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3061,7 +3061,7 @@ fn static_assert() { 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""" %> + shape-outside contain touch-action translate""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> // We manually-implement the |display| property until we get general @@ -3487,6 +3487,7 @@ fn static_assert() { } ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')} + ${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')} pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) { use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange}; diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index f42a0861724..454461a9bf6 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -398,6 +398,14 @@ ${helpers.predefined_type("rotate", "Rotate", gecko_pref="layout.css.individual-transform.enabled", spec="https://drafts.csswg.org/css-transforms-2/#individual-transforms")} +${helpers.predefined_type("translate", "Translate", + "generics::transform::Translate::None", + animation_value_type="ComputedValue", + boxed=True, + 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", diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 75ea1586719..4bbd73e8f35 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -73,7 +73,7 @@ pub use self::svg::MozContextProperties; 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}; +pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate}; pub use self::ui::MozForceBrokenImageIcon; #[cfg(feature = "gecko")] diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 8f5d1a645d1..a3ea8b46daf 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -15,6 +15,7 @@ use values::generics::transform::{Transform as GenericTransform, TransformOperat use values::generics::transform::Rotate as GenericRotate; use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TransformOrigin as GenericTransformOrigin; +use values::generics::transform::Translate as GenericTranslate; /// A single operation in a computed CSS `transform` pub type TransformOperation = GenericTransformOperation< @@ -318,3 +319,28 @@ impl Rotate { } } } + +/// A computed CSS `translate` +pub type Translate = GenericTranslate; + +impl Translate { + /// Convert TransformOperation to Translate. + pub fn to_transform_operation(&self) -> Option { + match *self { + GenericTranslate::None => None, + GenericTranslate::TranslateX(tx) => Some(GenericTransformOperation::TranslateX(tx)), + GenericTranslate::Translate(tx, ty) => Some(GenericTransformOperation::Translate(tx, Some(ty))), + GenericTranslate::Translate3D(tx, ty, tz) => Some(GenericTransformOperation::Translate3D(tx, ty, tz)), + } + } + + /// Convert Translate to TransformOperation. + pub fn from_transform_operation(operation: &TransformOperation) -> Translate { + match *operation { + GenericTransformOperation::TranslateX(tx) => GenericTranslate::TranslateX(tx), + GenericTransformOperation::Translate(tx, Some(ty)) => GenericTranslate::Translate(tx, ty), + GenericTransformOperation::Translate3D(tx, ty, tz) => GenericTranslate::Translate3D(tx, ty, tz), + _ => unreachable!("Found unexpected value for translate"), + } + } +} diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index e1fc8c01fa2..d7a5bfb7bc5 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -682,3 +682,19 @@ pub enum Rotate { /// '{3} ' Rotate3D(Number, Number, Number, Angle), } + +#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] +/// A value of the `Translate` property +/// +/// +pub enum Translate { + /// 'none' + None, + /// '' + TranslateX(LengthOrPercentage), + /// ' ' + Translate(LengthOrPercentage, LengthOrPercentage), + /// ' ' + Translate3D(LengthOrPercentage, LengthOrPercentage, Length), +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index a19ed04b753..6feadb33288 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -69,7 +69,7 @@ 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}; +pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate}; pub use self::ui::MozForceBrokenImageIcon; pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index 3f766a086c6..b731dfb17f6 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -16,6 +16,7 @@ use values::generics::transform::{StepPosition, TimingFunction as GenericTimingF use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin}; use values::generics::transform::Rotate as GenericRotate; use values::generics::transform::TransformOperation as GenericTransformOperation; +use values::generics::transform::Translate as GenericTranslate; use values::specified::{self, Angle, Number, Length, Integer}; use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber}; use values::specified::position::{Side, X, Y}; @@ -536,3 +537,30 @@ impl Parse for Rotate { } } +/// A specified CSS `translate` +pub type Translate = GenericTranslate; + +impl Parse for Translate { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't> + ) -> Result> { + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(GenericTranslate::None); + } + + let tx = specified::LengthOrPercentage::parse(context, input)?; + if let Ok(ty) = input.try(|i| specified::LengthOrPercentage::parse(context, i)) { + if let Ok(tz) = input.try(|i| specified::Length::parse(context, i)) { + // 'translate: ' + return Ok(GenericTranslate::Translate3D(tx, ty, tz)); + } + + // translate: ' + return Ok(GenericTranslate::Translate(tx, ty)); + } + + // 'translate: ' + Ok(GenericTranslate::TranslateX(tx)) + } +} diff --git a/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-invalid.html.ini b/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-invalid.html.ini deleted file mode 100644 index 80f4ba1cb59..00000000000 --- a/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-invalid.html.ini +++ /dev/null @@ -1,10 +0,0 @@ -[translate-parsing-invalid.html] - [e.style['translate'\] = "100deg" should not set the property value] - expected: FAIL - - [e.style['translate'\] = "100px 200px 300%" should not set the property value] - expected: FAIL - - [e.style['translate'\] = "100px 200px calc(30px + 30%)" should not set the property value] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-valid.html.ini b/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-valid.html.ini index c0a7ed07667..3d698e879cd 100644 --- a/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-valid.html.ini +++ b/tests/wpt/metadata/css/css-transforms/parsing/translate-parsing-valid.html.ini @@ -5,9 +5,3 @@ [Serialization should round-trip after setting e.style['translate'\] = "1px 2px 0"] expected: FAIL - [e.style['translate'\] = "0" should set the property value] - expected: FAIL - - [e.style['translate'\] = "1px 2px 0" should set the property value] - expected: FAIL -