From 3034d66eefe18a069a3da52ec9c9886b65b33928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:25:10 +0000 Subject: [PATCH] style: Use cbindgen to back CSS transforms. This avoids the expensive conversion, and cleans up a bunch. Further cleanup is possible, just not done yet to avoid growing the patch even more. Differential Revision: https://phabricator.services.mozilla.com/D30748 --- .../gecko_bindings/sugar/ns_css_value.rs | 23 -- .../style/gecko_bindings/sugar/refptr.rs | 5 - components/style/properties/cascade.rs | 4 - components/style/properties/gecko.mako.rs | 294 +----------------- .../style/properties/longhands/box.mako.rs | 1 - .../style/properties/longhands/ui.mako.rs | 1 - components/style/values/animated/transform.rs | 16 +- components/style/values/computed/angle.rs | 1 + components/style/values/computed/transform.rs | 12 +- components/style/values/generics/transform.rs | 54 +++- .../style/values/specified/transform.rs | 4 +- 11 files changed, 59 insertions(+), 356 deletions(-) diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs index b59732bcc8e..96b48061c8a 100644 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ b/components/style/gecko_bindings/sugar/ns_css_value.rs @@ -276,29 +276,6 @@ impl nsCSSValue { } debug_assert!(values.next().is_none(), "Values should have been exhausted"); } - - /// Set a shared list - pub fn set_shared_list(&mut self, values: I) - where - I: ExactSizeIterator, - { - debug_assert!(values.len() > 0, "Empty list is not supported"); - unsafe { bindings::Gecko_CSSValue_InitSharedList(self, values.len() as u32) }; - debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_SharedList); - let list = unsafe { - self.mValue - .mSharedList - .as_ref() - .as_mut() - .expect("List pointer should be non-null") - .mHead - .as_mut() - }; - debug_assert!(list.is_some(), "New created shared list shouldn't be null"); - for (item, new_value) in list.unwrap().into_iter().zip(values) { - *item = new_value; - } - } } impl Drop for nsCSSValue { diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index 1ad71afa6bc..90cc5284bc4 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -289,11 +289,6 @@ impl_threadsafe_refcount!( bindings::Gecko_AddRefURLExtraDataArbitraryThread, bindings::Gecko_ReleaseURLExtraDataArbitraryThread ); -impl_threadsafe_refcount!( - structs::nsCSSValueSharedList, - bindings::Gecko_AddRefCSSValueSharedListArbitraryThread, - bindings::Gecko_ReleaseCSSValueSharedListArbitraryThread -); impl_threadsafe_refcount!( structs::mozilla::css::URLValue, bindings::Gecko_AddRefCSSURLValueArbitraryThread, diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 1b76aefdd74..9b1cfb8ec04 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -628,10 +628,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { #[cfg(feature = "gecko")] { - if let Some(display) = builder.get_box_if_mutated() { - display.generate_combined_transform(); - } - if let Some(bg) = builder.get_background_if_mutated() { bg.fill_arrays(); } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 13b30b53b1b..cffc1e50de7 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -811,281 +811,6 @@ def set_gecko_property(ffi_name, expr): } -<% -transform_functions = [ - ("Matrix3D", "matrix3d", ["number"] * 16), - ("Matrix", "matrix", ["number"] * 6), - ("Translate", "translate", ["lp", "lp"]), - ("Translate3D", "translate3d", ["lp", "lp", "length"]), - ("TranslateX", "translatex", ["lp"]), - ("TranslateY", "translatey", ["lp"]), - ("TranslateZ", "translatez", ["length"]), - ("Scale3D", "scale3d", ["number"] * 3), - ("Scale", "scale", ["number", "number"]), - ("ScaleX", "scalex", ["number"]), - ("ScaleY", "scaley", ["number"]), - ("ScaleZ", "scalez", ["number"]), - ("Rotate", "rotate", ["angle"]), - ("Rotate3D", "rotate3d", ["number"] * 3 + ["angle"]), - ("RotateX", "rotatex", ["angle"]), - ("RotateY", "rotatey", ["angle"]), - ("RotateZ", "rotatez", ["angle"]), - ("Skew", "skew", ["angle", "angle"]), - ("SkewX", "skewx", ["angle"]), - ("SkewY", "skewy", ["angle"]), - ("Perspective", "perspective", ["length"]), - ("InterpolateMatrix", "interpolatematrix", ["list"] * 2 + ["percentage"]), - ("AccumulateMatrix", "accumulatematrix", ["list"] * 2 + ["integer_to_percentage"]) -] -%> - -<%def name="transform_function_arm(name, keyword, items)"> - <% - pattern = None - if keyword == "matrix3d": - # m11: number1, m12: number2, .. - single_patterns = ["m%s: %s" % (str(a / 4 + 1) + str(a % 4 + 1), b + str(a + 1)) for (a, b) - in enumerate(items)] - pattern = "(Matrix3D { %s })" % ", ".join(single_patterns) - elif keyword == "matrix": - # a: number1, b: number2, .. - single_patterns = ["%s: %s" % (chr(ord('a') + a), b + str(a + 1)) for (a, b) - in enumerate(items)] - pattern = "(Matrix { %s })" % ", ".join(single_patterns) - elif keyword == "interpolatematrix": - pattern = " { from_list: ref list1, to_list: ref list2, progress: percentage3 }" - elif keyword == "accumulatematrix": - pattern = " { from_list: ref list1, to_list: ref list2, count: integer_to_percentage3 }" - else: - # Generate contents of pattern from items - pattern = "(%s)" % ", ".join([b + str(a+1) for (a,b) in enumerate(items)]) - - # First %s substituted with the call to GetArrayItem, the second - # %s substituted with the corresponding variable - css_value_setters = { - "length" : "bindings::Gecko_CSSValue_SetPixelLength(%s, %s.px())", - "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s.0)", - # Note: This is an integer type, but we use it as a percentage value in Gecko, so - # need to cast it to f32. - "integer_to_percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s as f32)", - "lp" : "%s.set_length_percentage(%s)", - "angle" : "%s.set_angle(%s)", - "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)", - # Note: We use nsCSSValueSharedList here, instead of nsCSSValueList_heap - # because this function is not called on the main thread and - # nsCSSValueList_heap is not thread safe. - "list" : "%s.set_shared_list(%s.0.iter().map(&convert_to_ns_css_value));", - } - %> - crate::values::generics::transform::TransformOperation::${name}${pattern} => { - let len = ${len(items) + 1}; - bindings::Gecko_CSSValue_SetFunction(gecko_value, len); - bindings::Gecko_CSSValue_SetKeyword( - bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0), - structs::nsCSSKeyword::eCSSKeyword_${keyword} - ); - % for index, item in enumerate(items): - % if item == "list": - debug_assert!(!${item}${index + 1}.0.is_empty()); - % endif - ${css_value_setters[item] % ( - "(&mut *bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d))" % (index + 1), - item + str(index + 1) - )}; - % endfor - } - - -<%def name="computed_operation_arm(name, keyword, items)"> - <% - # %s is substituted with the call to GetArrayItem. - css_value_getters = { - "length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))", - "lp" : "%s.get_length_percentage()", - "angle" : "%s.get_angle()", - "number" : "bindings::Gecko_CSSValue_GetNumber(%s)", - "percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))", - "integer_to_percentage" : "bindings::Gecko_CSSValue_GetPercentage(%s) as i32", - "list" : "Transform(convert_shared_list_to_operations(%s))", - } - pre_symbols = "(" - post_symbols = ")" - if keyword == "interpolatematrix" or keyword == "accumulatematrix": - # We generate this like: "TransformOperation::InterpolateMatrix {", so the space is - # between "InterpolateMatrix"/"AccumulateMatrix" and '{' - pre_symbols = " {" - post_symbols = "}" - elif keyword == "matrix3d": - pre_symbols = "(Matrix3D {" - post_symbols = "})" - elif keyword == "matrix": - pre_symbols = "(Matrix {" - post_symbols = "})" - field_names = None - if keyword == "interpolatematrix": - field_names = ["from_list", "to_list", "progress"] - elif keyword == "accumulatematrix": - field_names = ["from_list", "to_list", "count"] - - %> - structs::nsCSSKeyword::eCSSKeyword_${keyword} => { - crate::values::generics::transform::TransformOperation::${name}${pre_symbols} - % for index, item in enumerate(items): - % if keyword == "matrix3d": - m${index / 4 + 1}${index % 4 + 1}: - % elif keyword == "matrix": - ${chr(ord('a') + index)}: - % elif keyword == "interpolatematrix" or keyword == "accumulatematrix": - ${field_names[index]}: - % endif - <% - getter = css_value_getters[item] % ( - "(&*bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d))" % (index + 1) - ) - %> - ${getter}, - % endfor - ${post_symbols} - }, - - -#[allow(unused_parens)] -fn set_single_transform_function( - servo_value: &values::computed::TransformOperation, - gecko_value: &mut structs::nsCSSValue /* output */ -) { - use crate::values::computed::TransformOperation; - use crate::values::generics::transform::{Matrix, Matrix3D}; - - let convert_to_ns_css_value = |item: &TransformOperation| -> structs::nsCSSValue { - let mut value = structs::nsCSSValue::null(); - set_single_transform_function(item, &mut value); - value - }; - - unsafe { - match *servo_value { - % for servo, gecko, format in transform_functions: - ${transform_function_arm(servo, gecko, format)} - % endfor - } - } -} - -pub fn convert_transform( - input: &[values::computed::TransformOperation], - output: &mut structs::root::RefPtr -) { - use crate::gecko_bindings::sugar::refptr::RefPtr; - - unsafe { output.clear() }; - - let list = unsafe { - RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32)) - }; - let value_list = unsafe { list.mHead.as_mut() }; - if let Some(value_list) = value_list { - for (gecko, servo) in value_list.into_iter().zip(input.into_iter()) { - set_single_transform_function(servo, gecko); - } - } - output.set_move(list); -} - -#[allow(unused_parens)] -fn clone_single_transform_function( - gecko_value: &structs::nsCSSValue -) -> values::computed::TransformOperation { - use crate::values::computed::{Length, Percentage, TransformOperation}; - use crate::values::generics::transform::{Matrix, Matrix3D}; - use crate::values::generics::transform::Transform; - - let convert_shared_list_to_operations = |value: &structs::nsCSSValue| - -> Vec { - debug_assert_eq!(value.mUnit, structs::nsCSSUnit::eCSSUnit_SharedList); - let value_list = unsafe { - value.mValue.mSharedList.as_ref() - .as_mut().expect("List pointer should be non-null").mHead.as_ref() - }; - debug_assert!(value_list.is_some(), "An empty shared list is not allowed"); - value_list.unwrap().into_iter() - .map(|item| clone_single_transform_function(item)) - .collect() - }; - - let transform_function = unsafe { - bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0)) - }; - - unsafe { - match transform_function { - % for servo, gecko, format in transform_functions: - ${computed_operation_arm(servo, gecko, format)} - % endfor - _ => panic!("unacceptable transform function"), - } - } -} - -pub fn clone_transform_from_list( - list: Option< &structs::root::nsCSSValueList> -) -> values::computed::Transform { - use crate::values::generics::transform::Transform; - - let result = match list { - Some(list) => { - list.into_iter() - .filter_map(|value| { - // Handle none transform. - if value.is_none() { - None - } else { - Some(clone_single_transform_function(value)) - } - }) - .collect::>() - }, - _ => vec![], - }; - Transform(result) -} - -<%def name="impl_transform(ident, gecko_ffi_name)"> - #[allow(non_snake_case)] - pub fn set_${ident}(&mut self, other: values::computed::Transform) { - use crate::gecko_properties::convert_transform; - if other.0.is_empty() { - unsafe { - self.gecko.${gecko_ffi_name}.clear(); - } - return; - }; - convert_transform(&other.0, &mut self.gecko.${gecko_ffi_name}); - } - - #[allow(non_snake_case)] - pub fn copy_${ident}_from(&mut self, other: &Self) { - unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); } - } - - #[allow(non_snake_case)] - pub fn reset_${ident}(&mut self, other: &Self) { - self.copy_${ident}_from(other) - } - - #[allow(non_snake_case)] - pub fn clone_${ident}(&self) -> values::computed::Transform { - use crate::gecko_properties::clone_transform_from_list; - use crate::values::generics::transform::Transform; - - if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() { - return Transform(vec!()); - } - let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() }; - clone_transform_from_list(list) - } - - <%def name="impl_logical(name, **kwargs)"> ${helpers.logical_setter(name)} @@ -1191,7 +916,6 @@ impl Clone for ${style_struct.gecko_struct_name} { "SVGOpacity": impl_svg_opacity, "SVGPaint": impl_svg_paint, "SVGWidth": impl_svg_length, - "Transform": impl_transform, "url::UrlOrNone": impl_css_url, } @@ -2511,17 +2235,11 @@ fn static_assert() { animation-iteration-count animation-timing-function clear transition-duration transition-delay transition-timing-function transition-property - transform-style - rotate scroll-snap-points-x scroll-snap-points-y - scroll-snap-coordinate -moz-binding - offset-path shape-outside - translate scale -webkit-line-clamp""" %> + transform-style scroll-snap-points-x + scroll-snap-points-y scroll-snap-coordinate + -moz-binding offset-path shape-outside + -webkit-line-clamp""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> - #[inline] - pub fn generate_combined_transform(&mut self) { - unsafe { bindings::Gecko_StyleDisplay_GenerateCombinedTransform(&mut *self.gecko) }; - } - #[inline] pub fn set_display(&mut self, v: longhands::display::computed_value::T) { self.gecko.mDisplay = v; @@ -2825,10 +2543,6 @@ fn static_assert() { ${impl_animation_timing_function()} - ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')} - ${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')} - ${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')} - <% impl_shape_source("shape_outside", "mShapeOutside") %> pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) { diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 6d754964ecc..0324062740f 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -352,7 +352,6 @@ ${helpers.predefined_type( "generics::transform::Transform::none()", extra_prefixes=transform_extra_prefixes, animation_value_type="ComputedValue", - gecko_ffi_name="mSpecifiedTransform", flags="CREATES_STACKING_CONTEXT FIXPOS_CB \ GETCS_NEEDS_LAYOUT_FLUSH CAN_ANIMATE_ON_COMPOSITOR", spec="https://drafts.csswg.org/css-transforms/#propdef-transform", diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs index c54582e2584..6d525825762 100644 --- a/components/style/properties/longhands/ui.mako.rs +++ b/components/style/properties/longhands/ui.mako.rs @@ -81,7 +81,6 @@ ${helpers.predefined_type( "Transform", "generics::transform::Transform::none()", products="gecko", - gecko_ffi_name="mSpecifiedWindowTransform", flags="GETCS_NEEDS_LAYOUT_FLUSH", animation_value_type="ComputedValue", spec="None (Nonstandard internal property)", diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index 0c322d8fccc..9ac64c3f2a7 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -861,7 +861,7 @@ impl Animate for ComputedTransform { // animation procedures so we treat it separately here rather than // handling it in TransformOperation. if procedure == Procedure::Add { - let result = self.0.iter().chain(&other.0).cloned().collect::>(); + let result = self.0.iter().chain(&*other.0).cloned().collect(); return Ok(Transform(result)); } @@ -898,15 +898,15 @@ impl Animate for ComputedTransform { }, Procedure::Interpolate { progress } => { result.push(TransformOperation::InterpolateMatrix { - from_list: Transform(this_remainder.to_vec()), - to_list: Transform(other_remainder.to_vec()), + from_list: Transform(this_remainder.to_vec().into()), + to_list: Transform(other_remainder.to_vec().into()), progress: Percentage(progress as f32), }); }, Procedure::Accumulate { count } => { result.push(TransformOperation::AccumulateMatrix { - from_list: Transform(this_remainder.to_vec()), - to_list: Transform(other_remainder.to_vec()), + from_list: Transform(this_remainder.to_vec().into()), + to_list: Transform(other_remainder.to_vec().into()), count: cmp::min(count, i32::max_value() as u64) as i32, }); }, @@ -927,8 +927,8 @@ impl Animate for ComputedTransform { // matrix. Instead we need to wrap it in another ___Matrix type. TransformOperation::AccumulateMatrix { .. } | TransformOperation::InterpolateMatrix { .. } => { - let transform_list = Transform(vec![transform.clone()]); - let identity_list = Transform(vec![identity]); + let transform_list = Transform(vec![transform.clone()].into()); + let identity_list = Transform(vec![identity].into()); let (from_list, to_list) = if fill_right { (transform_list, identity_list) } else { @@ -970,7 +970,7 @@ impl Animate for ComputedTransform { (None, None) => {}, } - Ok(Transform(result)) + Ok(Transform(result.into())) } } diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs index cdbc0006941..d8cdefb5263 100644 --- a/components/style/values/computed/angle.rs +++ b/components/style/values/computed/angle.rs @@ -26,6 +26,7 @@ use style_traits::{CssWriter, ToCss}; ToAnimatedZero, ToResolvedValue, )] +#[repr(C)] pub struct Angle(CSSFloat); impl ToCss for Angle { diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index e23ec1524ff..baa5cbfd5d2 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -16,9 +16,9 @@ pub use crate::values::generics::transform::TransformStyle; /// A single operation in a computed CSS `transform` pub type TransformOperation = - generic::TransformOperation; + generic::GenericTransformOperation; /// A computed CSS `transform` -pub type Transform = generic::Transform; +pub type Transform = generic::GenericTransform; /// The computed value of a CSS `` pub type TransformOrigin = @@ -540,13 +540,13 @@ impl ToAnimatedZero for Transform { self.0 .iter() .map(|op| op.to_animated_zero()) - .collect::, _>>()?, + .collect::, _>>()?, )) } } /// A computed CSS `rotate` -pub type Rotate = generic::Rotate; +pub type Rotate = generic::GenericRotate; impl Rotate { /// Convert TransformOperation to Rotate. @@ -573,7 +573,7 @@ impl Rotate { } /// A computed CSS `translate` -pub type Translate = generic::Translate; +pub type Translate = generic::GenericTranslate; impl Translate { /// Convert TransformOperation to Translate. @@ -602,7 +602,7 @@ impl Translate { } /// A computed CSS `scale` -pub type Scale = generic::Scale; +pub type Scale = generic::GenericScale; impl Scale { /// Convert TransformOperation to Scale. diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 6c6374db941..87f4403057f 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -30,8 +30,9 @@ use style_traits::{CssWriter, ToCss}; ToResolvedValue, ToShmem, )] -#[css(comma, function)] -pub struct Matrix { +#[css(comma, function = "matrix")] +#[repr(C)] +pub struct GenericMatrix { pub a: T, pub b: T, pub c: T, @@ -40,6 +41,8 @@ pub struct Matrix { pub f: T, } +pub use self::GenericMatrix as Matrix; + #[allow(missing_docs)] #[cfg_attr(rustfmt, rustfmt_skip)] #[css(comma, function = "matrix3d")] @@ -55,13 +58,16 @@ pub struct Matrix { ToResolvedValue, ToShmem, )] -pub struct Matrix3D { +#[repr(C)] +pub struct GenericMatrix3D { pub m11: T, pub m12: T, pub m13: T, pub m14: T, pub m21: T, pub m22: T, pub m23: T, pub m24: T, pub m31: T, pub m32: T, pub m33: T, pub m34: T, pub m41: T, pub m42: T, pub m43: T, pub m44: T, } +pub use self::GenericMatrix3D as Matrix3D; + #[cfg_attr(rustfmt, rustfmt_skip)] impl> From> for Transform3D { #[inline] @@ -142,17 +148,19 @@ fn is_same(x: &N, y: &N) -> bool { ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A single operation in the list of a `transform` value -pub enum TransformOperation +/// cbindgen:derive-tagged-enum-copy-constructor=true +pub enum GenericTransformOperation where Angle: Zero, LengthPercentage: Zero, Number: PartialEq, { /// Represents a 2D 2x3 matrix. - Matrix(Matrix), + Matrix(GenericMatrix), /// Represents a 3D 4x4 matrix. - Matrix3D(Matrix3D), + Matrix3D(GenericMatrix3D), /// A 2D skew. /// /// If the second angle is not provided it is assumed zero. @@ -232,20 +240,22 @@ where #[allow(missing_docs)] #[css(comma, function = "interpolatematrix")] InterpolateMatrix { - from_list: Transform>, - to_list: Transform>, + from_list: GenericTransform>, + to_list: GenericTransform>, progress: computed::Percentage, }, /// A intermediate type for accumulation of mismatched transform lists. #[allow(missing_docs)] #[css(comma, function = "accumulatematrix")] AccumulateMatrix { - from_list: Transform>, - to_list: Transform>, + from_list: GenericTransform>, + to_list: GenericTransform>, count: Integer, }, } +pub use self::GenericTransformOperation as TransformOperation; + #[derive( Clone, Debug, @@ -257,8 +267,11 @@ where ToResolvedValue, ToShmem, )] +#[repr(C)] /// A value of the `transform` property -pub struct Transform(#[css(if_empty = "none", iterable)] pub Vec); +pub struct GenericTransform(#[css(if_empty = "none", iterable)] pub crate::OwnedSlice); + +pub use self::GenericTransform as Transform; impl TransformOperation @@ -497,7 +510,7 @@ where impl Transform { /// `none` pub fn none() -> Self { - Transform(vec![]) + Transform(Default::default()) } } @@ -529,7 +542,7 @@ impl Transform { let mut transform = Transform3D::::identity(); let mut contain_3d = false; - for operation in &self.0 { + for operation in &*self.0 { let matrix = operation.to_3d_matrix(reference_box)?; contain_3d |= operation.is_3d(); transform = transform.pre_mul(&matrix); @@ -589,10 +602,11 @@ pub fn get_normalized_vector_and_angle( ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `Rotate` property /// /// -pub enum Rotate { +pub enum GenericRotate { /// 'none' None, /// '' @@ -601,6 +615,8 @@ pub enum Rotate { Rotate3D(Number, Number, Number, Angle), } +pub use self::GenericRotate as Rotate; + /// A trait to check if the current 3D vector is parallel to the DirectionVector. /// This is especially for serialization on Rotate. pub trait IsParallelTo { @@ -660,10 +676,11 @@ where ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `Scale` property /// /// -pub enum Scale { +pub enum GenericScale { /// 'none' None, /// '{1,2}' @@ -672,6 +689,8 @@ pub enum Scale { Scale3D(Number, Number, Number), } +pub use self::GenericScale as Scale; + impl ToCss for Scale { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where @@ -710,6 +729,7 @@ impl ToCss for Scale { ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `translate` property /// /// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization: @@ -724,7 +744,7 @@ impl ToCss for Scale { /// related spec issue is https://github.com/w3c/csswg-drafts/issues/3305 /// /// -pub enum Translate +pub enum GenericTranslate where LengthPercentage: Zero, { @@ -739,6 +759,8 @@ where Translate3D(LengthPercentage, LengthPercentage, Length), } +pub use self::GenericTranslate as Translate; + #[allow(missing_docs)] #[derive( Clone, diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index a4dc87d3217..4c083e896a2 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -42,7 +42,7 @@ impl Transform { .try(|input| input.expect_ident_matching("none")) .is_ok() { - return Ok(generic::Transform(Vec::new())); + return Ok(generic::Transform::none()); } Ok(generic::Transform(Space::parse(input, |input| { @@ -218,7 +218,7 @@ impl Transform { .new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone())) }) }) - })?)) + })?.into())) } }