diff options
author | Xidorn Quan <me@upsuper.org> | 2017-11-07 15:40:42 -0800 |
---|---|---|
committer | Xidorn Quan <me@upsuper.org> | 2017-11-12 10:59:54 -0800 |
commit | dfbf632fd67c05edef94bd15426a68852a9ac79b (patch) | |
tree | 05e7d2fd6e67dd36dc1dcdae2d4c1d9b92b9bda5 | |
parent | 8b9bbfea75c4b2494d4dee2069029e58e5490871 (diff) | |
download | servo-dfbf632fd67c05edef94bd15426a68852a9ac79b.tar.gz servo-dfbf632fd67c05edef94bd15426a68852a9ac79b.zip |
Add general impl in gecko_properties for Transform value and add -moz-window-transform.
-rw-r--r-- | components/style/properties/gecko.mako.rs | 672 | ||||
-rw-r--r-- | components/style/properties/longhand/box.mako.rs | 1 | ||||
-rw-r--r-- | components/style/properties/longhand/ui.mako.rs | 7 | ||||
-rw-r--r-- | ports/geckolib/glue.rs | 6 |
4 files changed, 358 insertions, 328 deletions
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index bcc4b79fc98..406ec3df7cc 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -979,6 +979,351 @@ def set_gecko_property(ffi_name, expr): } </%def> +<% +transform_functions = [ + ("Matrix3D", "matrix3d", ["number"] * 16), + ("PrefixedMatrix3D", "matrix3d", ["number"] * 12 + ["lopon"] * 2 + + ["lon"] + ["number"]), + ("Matrix", "matrix", ["number"] * 6), + ("PrefixedMatrix", "matrix", ["number"] * 4 + ["lopon"] * 2), + ("Translate", "translate", ["lop", "optional_lop"]), + ("Translate3D", "translate3d", ["lop", "lop", "length"]), + ("TranslateX", "translatex", ["lop"]), + ("TranslateY", "translatey", ["lop"]), + ("TranslateZ", "translatez", ["length"]), + ("Scale3D", "scale3d", ["number"] * 3), + ("Scale", "scale", ["number", "optional_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", "optional_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)"> + <% + has_optional = items[-1].startswith("optional_") + 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)", + "lop" : "%s.set_lop(%s)", + "lopon" : "set_lopon(%s, %s)", + "lon" : "set_lon(%s, %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));", + } + %> + ::values::generics::transform::TransformOperation::${name}${pattern} => { + % if has_optional: + let optional_present = ${items[-1] + str(len(items))}.is_some(); + let len = if optional_present { + ${len(items) + 1} + } else { + ${len(items)} + }; + % else: + let len = ${len(items) + 1}; + % endif + 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): + <% replaced_item = item.replace("optional_", "") %> + % if item.startswith("optional"): + if let Some(${replaced_item + str(index + 1)}) = ${item + str(index + 1)} { + % endif + % if item == "list": + debug_assert!(!${item}${index + 1}.0.is_empty()); + % endif + ${css_value_setters[replaced_item] % ( + "bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1), + replaced_item + str(index + 1) + )}; + % if item.startswith("optional"): + } + % endif + % endfor + } +</%def> + +<%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))", + "lop" : "%s.get_lop()", + "lopon" : "Either::Second(%s.get_lop())", + "lon" : "Either::First(%s.get_length())", + "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"] + + %> + <% + + guard = "" + if name == "Matrix3D" or name == "Matrix": + guard = "if !needs_prefix " + elif name == "PrefixedMatrix3D" or name == "PrefixedMatrix": + guard = "if needs_prefix " + + %> + structs::nsCSSKeyword::eCSSKeyword_${keyword} ${guard}=> { + ::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.replace("optional_", "")] % ( + "bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1) + ) + %> + % if item.startswith("optional_"): + if (**gecko_value.mValue.mArray.as_ref()).mCount == ${index + 1} { + None + } else { + Some(${getter}) + } + % else: + ${getter} + % endif +, + % endfor + ${post_symbols} + }, +</%def> + +fn set_single_transform_function( + servo_value: &values::computed::TransformOperation, + gecko_value: &mut structs::nsCSSValue /* output */ +) { + use values::computed::{Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber}; + use values::computed::TransformOperation; + use 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 fn set_lopon(css: &mut structs::nsCSSValue, lopon: LengthOrPercentageOrNumber) { + let lop = match lopon { + Either::First(number) => LengthOrPercentage::Length(Length::new(number)), + Either::Second(lop) => lop, + }; + css.set_lop(lop); + } + + unsafe fn set_lon(css: &mut structs::nsCSSValue, lopon: LengthOrNumber) { + let length = match lopon { + Either::Second(number) => Length::new(number), + Either::First(l) => l, + }; + bindings::Gecko_CSSValue_SetPixelLength(css, length.px()) + } + + 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<structs::root::nsCSSValueSharedList> +) { + use 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); + } + } + unsafe { output.set_move(list) }; +} + +fn clone_single_transform_function( + gecko_value: &structs::nsCSSValue +) -> values::computed::TransformOperation { + use values::computed::{Length, Percentage, TransformOperation}; + use values::generics::transform::{Matrix, Matrix3D}; + use values::generics::transform::Transform; + + let convert_shared_list_to_operations = |value: &structs::nsCSSValue| + -> Vec<TransformOperation> { + debug_assert!(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)) + }; + + let needs_prefix = if transform_function == structs::nsCSSKeyword::eCSSKeyword_matrix3d { + unsafe { + bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 13).mUnit + != structs::nsCSSUnit::eCSSUnit_Number || + bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 14).mUnit + != structs::nsCSSUnit::eCSSUnit_Number || + bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 15).mUnit + != structs::nsCSSUnit::eCSSUnit_Number + } + } else { + false + }; + + unsafe { + match transform_function { + % for servo, gecko, format in transform_functions: + ${computed_operation_arm(servo, gecko, format)} + % endfor + _ => panic!("{:?} is not an acceptable transform function", transform_function), + } + } +} + +pub fn clone_transform_from_list( + list: Option< &structs::root::nsCSSValueList> +) -> values::computed::Transform { + use 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<_>>() + }, + _ => 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 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 gecko_properties::clone_transform_from_list; + use 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> + <%def name="impl_logical(name, **kwargs)"> ${helpers.logical_setter(name)} </%def> @@ -1131,6 +1476,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "SVGOpacity": impl_svg_opacity, "SVGPaint": impl_svg_paint, "SVGWidth": impl_svg_length, + "Transform": impl_transform, "UrlOrNone": impl_css_url, } @@ -2699,7 +3045,7 @@ fn static_assert() { transition-duration transition-delay transition-timing-function transition-property page-break-before page-break-after - scroll-snap-points-x scroll-snap-points-y transform + scroll-snap-points-x scroll-snap-points-y scroll-snap-type-x scroll-snap-type-y scroll-snap-coordinate perspective-origin transform-origin -moz-binding will-change shape-outside contain touch-action""" %> @@ -2894,330 +3240,6 @@ fn static_assert() { } ${impl_css_url('_moz_binding', 'mBinding.mPtr')} - <% - transform_functions = [ - ("Matrix3D", "matrix3d", ["number"] * 16), - ("PrefixedMatrix3D", "matrix3d", ["number"] * 12 + ["lopon"] * 2 - + ["lon"] + ["number"]), - ("Matrix", "matrix", ["number"] * 6), - ("PrefixedMatrix", "matrix", ["number"] * 4 + ["lopon"] * 2), - ("Translate", "translate", ["lop", "optional_lop"]), - ("Translate3D", "translate3d", ["lop", "lop", "length"]), - ("TranslateX", "translatex", ["lop"]), - ("TranslateY", "translatey", ["lop"]), - ("TranslateZ", "translatez", ["length"]), - ("Scale3D", "scale3d", ["number"] * 3), - ("Scale", "scale", ["number", "optional_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", "optional_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)"> - <% - has_optional = items[-1].startswith("optional_") - 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)", - "lop" : "%s.set_lop(%s)", - "lopon" : "set_lopon(%s, %s)", - "lon" : "set_lon(%s, %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));", - } - %> - ::values::generics::transform::TransformOperation::${name}${pattern} => { - % if has_optional: - let optional_present = ${items[-1] + str(len(items))}.is_some(); - let len = if optional_present { - ${len(items) + 1} - } else { - ${len(items)} - }; - % else: - let len = ${len(items) + 1}; - % endif - 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): - <% replaced_item = item.replace("optional_", "") %> - % if item.startswith("optional"): - if let Some(${replaced_item + str(index + 1)}) = ${item + str(index + 1)} { - % endif - % if item == "list": - debug_assert!(!${item}${index + 1}.0.is_empty()); - % endif - ${css_value_setters[replaced_item] % ( - "bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d)" % (index + 1), - replaced_item + str(index + 1) - )}; - % if item.startswith("optional"): - } - % endif - % endfor - } - </%def> - fn set_single_transform_function(servo_value: &values::computed::TransformOperation, - gecko_value: &mut structs::nsCSSValue /* output */) { - use values::computed::{Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber}; - use values::computed::TransformOperation; - use values::generics::transform::{Matrix, Matrix3D}; - - let convert_to_ns_css_value = |item: &TransformOperation| -> structs::nsCSSValue { - let mut value = structs::nsCSSValue::null(); - Self::set_single_transform_function(item, &mut value); - value - }; - - unsafe fn set_lopon(css: &mut structs::nsCSSValue, lopon: LengthOrPercentageOrNumber) { - let lop = match lopon { - Either::First(number) => LengthOrPercentage::Length(Length::new(number)), - Either::Second(lop) => lop, - }; - css.set_lop(lop); - } - - unsafe fn set_lon(css: &mut structs::nsCSSValue, lopon: LengthOrNumber) { - let length = match lopon { - Either::Second(number) => Length::new(number), - Either::First(l) => l, - }; - bindings::Gecko_CSSValue_SetPixelLength(css, length.px()) - } - - 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<structs::root::nsCSSValueSharedList>) { - use 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()) { - Self::set_single_transform_function(servo, gecko); - } - } - unsafe { output.set_move(list) }; - } - - pub fn set_transform(&mut self, other: longhands::transform::computed_value::T) { - if other.0.is_empty() { - unsafe { - self.gecko.mSpecifiedTransform.clear(); - } - return; - }; - Self::convert_transform(&other.0, &mut self.gecko.mSpecifiedTransform); - } - - pub fn copy_transform_from(&mut self, other: &Self) { - unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); } - } - - pub fn reset_transform(&mut self, other: &Self) { - self.copy_transform_from(other) - } - - <%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))", - "lop" : "%s.get_lop()", - "lopon" : "Either::Second(%s.get_lop())", - "lon" : "Either::First(%s.get_length())", - "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"] - - %> - <% - - guard = "" - if name == "Matrix3D" or name == "Matrix": - guard = "if !needs_prefix " - elif name == "PrefixedMatrix3D" or name == "PrefixedMatrix": - guard = "if needs_prefix " - - %> - structs::nsCSSKeyword::eCSSKeyword_${keyword} ${guard}=> { - ::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.replace("optional_", "")] % ( - "bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1) - ) - %> - % if item.startswith("optional_"): - if (**gecko_value.mValue.mArray.as_ref()).mCount == ${index + 1} { - None - } else { - Some(${getter}) - } - % else: - ${getter} - % endif -, - % endfor - ${post_symbols} - }, - </%def> - fn clone_single_transform_function(gecko_value: &structs::nsCSSValue) - -> values::computed::TransformOperation { - use values::computed::{Length, Percentage, TransformOperation}; - use values::generics::transform::{Matrix, Matrix3D}; - use values::generics::transform::Transform; - - let convert_shared_list_to_operations = |value: &structs::nsCSSValue| - -> Vec<TransformOperation> { - debug_assert!(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| Self::clone_single_transform_function(item)) - .collect() - }; - - let transform_function = unsafe { - bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0)) - }; - - let needs_prefix = if transform_function == structs::nsCSSKeyword::eCSSKeyword_matrix3d { - unsafe { - bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 13).mUnit - != structs::nsCSSUnit::eCSSUnit_Number || - bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 14).mUnit - != structs::nsCSSUnit::eCSSUnit_Number || - bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 15).mUnit - != structs::nsCSSUnit::eCSSUnit_Number - } - } else { - false - }; - - unsafe { - match transform_function { - % for servo, gecko, format in transform_functions: - ${computed_operation_arm(servo, gecko, format)} - % endfor - _ => panic!("{:?} is not an acceptable transform function", transform_function), - } - } - } - pub fn clone_transform(&self) -> longhands::transform::computed_value::T { - use values::generics::transform::Transform; - - if self.gecko.mSpecifiedTransform.mRawPtr.is_null() { - return Transform(vec!()); - } - let list = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead.as_ref() }; - Self::clone_transform_from_list(list) - } - pub fn clone_transform_from_list(list: Option< &structs::root::nsCSSValueList>) - -> longhands::transform::computed_value::T { - use 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(Self::clone_single_transform_function(value)) - } - }) - .collect::<Vec<_>>() - }, - _ => vec![], - }; - Transform(result) - } ${impl_transition_time_value('delay', 'Delay')} ${impl_transition_time_value('duration', 'Duration')} diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 105db8ec1a2..9d0ddf1cdf0 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -571,6 +571,7 @@ ${helpers.predefined_type("transform", "Transform", "generics::transform::Transform::none()", extra_prefixes="webkit", animation_value_type="ComputedValue", + gecko_ffi_name="mSpecifiedTransform", flags="CREATES_STACKING_CONTEXT FIXPOS_CB", spec="https://drafts.csswg.org/css-transforms/#propdef-transform")} diff --git a/components/style/properties/longhand/ui.mako.rs b/components/style/properties/longhand/ui.mako.rs index 6152411155a..46412047e3e 100644 --- a/components/style/properties/longhand/ui.mako.rs +++ b/components/style/properties/longhand/ui.mako.rs @@ -46,6 +46,13 @@ ${helpers.predefined_type("-moz-window-opacity", "Opacity", "1.0", products="gec internal=True, spec="None (Nonstandard internal property)")} +${helpers.predefined_type("-moz-window-transform", "Transform", + "generics::transform::Transform::none()", + products="gecko", gecko_ffi_name="mSpecifiedWindowTransform", + animation_value_type="ComputedValue", + internal=True, + spec="None (Nonstandard internal property)")} + <%helpers:longhand name="-moz-force-broken-image-icon" products="gecko" animation_value_type="discrete" diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 07d05379628..04ff917fa1e 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -111,7 +111,7 @@ use style::gecko_bindings::structs::nsresult; use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasFFI, HasArcFFI}; use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong}; use style::gecko_bindings::sugar::refptr::RefPtr; -use style::gecko_properties::style_structs; +use style::gecko_properties; use style::invalidation::element::restyle_hints; use style::media_queries::{Device, MediaList, parse_media_query_list}; use style::parser::{Parse, ParserContext, self}; @@ -721,7 +721,7 @@ pub extern "C" fn Servo_AnimationValue_GetTransform( list.set_move(RefPtr::from_addrefed(Gecko_NewNoneTransform())); } } else { - style_structs::Box::convert_transform(&servo_list.0, list); + gecko_properties::convert_transform(&servo_list.0, list); } } else { panic!("The AnimationValue should be transform"); @@ -733,7 +733,7 @@ pub extern "C" fn Servo_AnimationValue_Transform( list: *const nsCSSValueSharedList ) -> RawServoAnimationValueStrong { let list = unsafe { (&*list).mHead.as_ref() }; - let transform = style_structs::Box::clone_transform_from_list(list); + let transform = gecko_properties::clone_transform_from_list(list); Arc::new(AnimationValue::Transform(transform)).into_strong() } |