aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCJ Ku <cku@mozilla.com>2018-01-25 12:44:20 +0900
committerBrian Birtles <birtles@gmail.com>2018-01-31 22:12:26 +0000
commit62c0c6feee8304eb40d0dcb574b6d1b98249eccc (patch)
tree38d222da8bb21cdb5c853090930d362fdc43284f
parenta8c133d07ed75f1da89d5e24b45d4043bfb79471 (diff)
downloadservo-62c0c6feee8304eb40d0dcb574b6d1b98249eccc.tar.gz
servo-62c0c6feee8304eb40d0dcb574b6d1b98249eccc.zip
Implement rotate property styling
-rw-r--r--components/script/dom/webidls/CSSStyleDeclaration.webidl1
-rw-r--r--components/style/properties/gecko.mako.rs36
-rw-r--r--components/style/properties/longhand/box.mako.rs8
-rw-r--r--components/style/values/computed/mod.rs2
-rw-r--r--components/style/values/computed/transform.rs25
-rw-r--r--components/style/values/generics/transform.rs14
-rw-r--r--components/style/values/specified/mod.rs2
-rw-r--r--components/style/values/specified/transform.rs28
-rw-r--r--tests/wpt/metadata/css/css-transforms/parsing/rotate-parsing-invalid.html.ini13
9 files changed, 113 insertions, 16 deletions
diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl
index a7eb0289b84..987a95edb22 100644
--- a/components/script/dom/webidls/CSSStyleDeclaration.webidl
+++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl
@@ -189,6 +189,7 @@ partial interface CSSStyleDeclaration {
[CEReactions, SetterThrows, TreatNullAs=EmptyString] attribute DOMString transform-style;
[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 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 64a729dad5c..a4de0ed7b5d 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -3016,13 +3016,45 @@ fn static_assert() {
${impl_copy_animation_value(ident, gecko_ffi_name)}
</%def>
+<%def name="impl_individual_transform(ident, type, gecko_ffi_name)">
+ pub fn set_${ident}(&mut self, other: values::computed::${type}) {
+ unsafe { self.gecko.${gecko_ffi_name}.clear() };
+
+ if let Some(operation) = other.to_transform_operation() {
+ convert_transform(&[operation], &mut self.gecko.${gecko_ffi_name})
+ }
+ }
+
+ pub fn copy_${ident}_from(&mut self, other: &Self) {
+ unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); }
+ }
+
+ pub fn reset_${ident}(&mut self, other: &Self) {
+ self.copy_${ident}_from(other)
+ }
+
+ pub fn clone_${ident}(&self) -> values::computed::${type} {
+ use values::generics::transform::${type};
+
+ if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
+ return ${type}::None;
+ }
+
+ let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() };
+
+ let mut transform = clone_transform_from_list(list);
+ debug_assert_eq!(transform.0.len(), 1);
+ ${type}::from_transform_operation(&transform.0.pop().unwrap())
+ }
+</%def>
+
<% skip_box_longhands= """display overflow-y vertical-align
animation-name animation-delay animation-duration
animation-direction animation-fill-mode animation-play-state
animation-iteration-count animation-timing-function
transition-duration transition-delay
transition-timing-function transition-property
- page-break-before page-break-after
+ 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
@@ -3454,6 +3486,8 @@ fn static_assert() {
}
}
+ ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
+
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;
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index d1b26de1154..f42a0861724 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -390,6 +390,14 @@ ${helpers.predefined_type("transform", "Transform",
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
spec="https://drafts.csswg.org/css-transforms/#propdef-transform")}
+${helpers.predefined_type("rotate", "Rotate",
+ "generics::transform::Rotate::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 4156e784c9e..75ea1586719 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};
+pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate};
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 4ad043850c8..8f5d1a645d1 100644
--- a/components/style/values/computed/transform.rs
+++ b/components/style/values/computed/transform.rs
@@ -12,6 +12,7 @@ use values::computed::{Angle, Integer, Length, LengthOrPercentage, Number, Perce
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::Rotate as GenericRotate;
use values::generics::transform::TimingFunction as GenericTimingFunction;
use values::generics::transform::TransformOrigin as GenericTransformOrigin;
@@ -293,3 +294,27 @@ impl ToAnimatedZero for Transform {
.collect::<Result<Vec<_>, _>>()?))
}
}
+
+/// A computed CSS `rotate`
+pub type Rotate = GenericRotate<Number, Angle>;
+
+impl Rotate {
+ /// Convert TransformOperation to Rotate.
+ pub fn to_transform_operation(&self) -> Option<TransformOperation> {
+ match *self {
+ GenericRotate::None => None,
+ GenericRotate::Rotate(angle) => Some(GenericTransformOperation::Rotate(angle)),
+ GenericRotate::Rotate3D(rx, ry, rz, angle) => Some(GenericTransformOperation::Rotate3D(rx, ry, rz, angle)),
+ }
+ }
+
+ /// Convert Rotate to TransformOperation.
+ pub fn from_transform_operation(operation: &TransformOperation) -> Rotate {
+ match *operation {
+ GenericTransformOperation::Rotate(angle) => GenericRotate::Rotate(angle),
+ GenericTransformOperation::Rotate3D(rx, ry, rz, angle) =>
+ GenericRotate::Rotate3D(rx, ry, rz, angle),
+ _ => unreachable!("Found unexpected value for rotate property"),
+ }
+ }
+}
diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs
index 7c2bb57546e..e1fc8c01fa2 100644
--- a/components/style/values/generics/transform.rs
+++ b/components/style/values/generics/transform.rs
@@ -668,3 +668,17 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
(vector.x, vector.y, vector.z, angle)
}
}
+
+#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)]
+#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
+/// A value of the `Rotate` property
+///
+/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
+pub enum Rotate<Number, Angle> {
+ /// 'none'
+ None,
+ /// '<angle>'
+ Rotate(Angle),
+ /// '<number>{3} <angle>'
+ Rotate3D(Number, Number, Number, Angle),
+}
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 877580f799d..a19ed04b753 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};
+pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate};
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 a8437d558cc..3f766a086c6 100644
--- a/components/style/values/specified/transform.rs
+++ b/components/style/values/specified/transform.rs
@@ -14,6 +14,7 @@ use values::computed::transform::TimingFunction as ComputedTimingFunction;
use values::generics::transform::{Matrix3D, Transform as GenericTransform};
use values::generics::transform::{StepPosition, TimingFunction as GenericTimingFunction, Matrix};
use values::generics::transform::{TimingKeyword, TransformOrigin as GenericTransformOrigin};
+use values::generics::transform::Rotate as GenericRotate;
use values::generics::transform::TransformOperation as GenericTransformOperation;
use values::specified::{self, Angle, Number, Length, Integer};
use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber};
@@ -508,3 +509,30 @@ impl ToComputedValue for TimingFunction {
}
}
}
+
+/// A specified CSS `rotate`
+pub type Rotate = GenericRotate<Number, Angle>;
+
+impl Parse for Rotate {
+ 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(GenericRotate::None);
+ }
+
+ if let Some(rx) = input.try(|i| Number::parse(context, i)).ok() {
+ // 'rotate: <number>{3} <angle>'
+ let ry = Number::parse(context, input)?;
+ let rz = Number::parse(context, input)?;
+ let angle = specified::Angle::parse(context, input)?;
+ return Ok(GenericRotate::Rotate3D(rx, ry, rz, angle));
+ }
+
+ // 'rotate: <angle>'
+ let angle = specified::Angle::parse(context, input)?;
+ Ok(GenericRotate::Rotate(angle))
+ }
+}
+
diff --git a/tests/wpt/metadata/css/css-transforms/parsing/rotate-parsing-invalid.html.ini b/tests/wpt/metadata/css/css-transforms/parsing/rotate-parsing-invalid.html.ini
deleted file mode 100644
index b28de4b2e0f..00000000000
--- a/tests/wpt/metadata/css/css-transforms/parsing/rotate-parsing-invalid.html.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[rotate-parsing-invalid.html]
- [e.style['rotate'\] = "100px" should not set the property value]
- expected: FAIL
-
- [e.style['rotate'\] = "100 400deg" should not set the property value]
- expected: FAIL
-
- [e.style['rotate'\] = "100 200 400deg" should not set the property value]
- expected: FAIL
-
- [e.style['rotate'\] = "100 200 300 500 400deg" should not set the property value]
- expected: FAIL
-