diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs index 3f1110ecd34a..3f125b133114 100644 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ b/components/style/gecko_bindings/sugar/ns_css_value.rs @@ -4,11 +4,19 @@ //! Little helpers for `nsCSSValue`. +use app_units::Au; use gecko_bindings::bindings::Gecko_CSSValue_Drop; +use gecko_bindings::bindings::Gecko_CSSValue_GetAbsoluteLength; +use gecko_bindings::bindings::Gecko_CSSValue_GetCalc; +use gecko_bindings::bindings::Gecko_CSSValue_GetPercentage; +use gecko_bindings::bindings::Gecko_CSSValue_SetAbsoluteLength; +use gecko_bindings::bindings::Gecko_CSSValue_SetCalc; +use gecko_bindings::bindings::Gecko_CSSValue_SetPercentage; use gecko_bindings::structs::{nsCSSValue, nsCSSUnit, nsCSSValue_Array}; use std::mem; use std::ops::Index; use std::slice; +use values::computed::LengthOrPercentage; impl nsCSSValue { /// Create a CSSValue with null unit, useful to be used as a return value. @@ -42,6 +50,37 @@ impl nsCSSValue { debug_assert!(!array.is_null()); &*array } + + /// Sets LengthOrPercentage value to this nsCSSValue. + pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) { + match lop { + LengthOrPercentage::Length(au) => { + Gecko_CSSValue_SetAbsoluteLength(self, au.0) + } + LengthOrPercentage::Percentage(pc) => { + Gecko_CSSValue_SetPercentage(self, pc) + } + LengthOrPercentage::Calc(calc) => { + Gecko_CSSValue_SetCalc(self, calc.into()) + } + } + } + + /// Returns LengthOrPercentage value. + pub unsafe fn get_lop(&self) -> LengthOrPercentage { + match self.mUnit { + nsCSSUnit::eCSSUnit_Pixel => { + LengthOrPercentage::Length(Au(Gecko_CSSValue_GetAbsoluteLength(self))) + }, + nsCSSUnit::eCSSUnit_Percent => { + LengthOrPercentage::Percentage(Gecko_CSSValue_GetPercentage(self)) + }, + nsCSSUnit::eCSSUnit_Calc => { + LengthOrPercentage::Calc(Gecko_CSSValue_GetCalc(self).into()) + }, + x => panic!("The unit should not be {:?}", x), + } + } } impl Drop for nsCSSValue { diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 0c80a294d78a..7524d7fa6ebf 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1317,7 +1317,7 @@ fn static_assert() { css_value_setters = { "length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)", "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)", - "lop" : "set_lop(%s, %s)", + "lop" : "%s.set_lop(%s)", "angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.0)", "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)", } @@ -1341,21 +1341,6 @@ fn static_assert() { use gecko_bindings::sugar::refptr::RefPtr; use properties::longhands::transform::computed_value::ComputedMatrix; use properties::longhands::transform::computed_value::ComputedOperation; - use values::computed::LengthOrPercentage; - - unsafe fn set_lop(value: &mut structs::nsCSSValue, lop: LengthOrPercentage) { - match lop { - LengthOrPercentage::Length(au) => { - bindings::Gecko_CSSValue_SetAbsoluteLength(value, au.0) - } - LengthOrPercentage::Percentage(pc) => { - bindings::Gecko_CSSValue_SetPercentage(value, pc) - } - LengthOrPercentage::Calc(calc) => { - bindings::Gecko_CSSValue_SetCalc(value, calc.into()) - } - } - } let vec = if let Some(v) = other.0 { v @@ -1396,6 +1381,71 @@ fn static_assert() { unsafe { self.gecko.mSpecifiedTransform.set(&other.gecko.mSpecifiedTransform); } } + <%def name="computed_operation_arm(name, keyword, items)"> + <% + # %s is substituted with the call to GetArrayItem. + css_value_getters = { + "length" : "Au(bindings::Gecko_CSSValue_GetAbsoluteLength(%s))", + "lop" : "%s.get_lop()", + "angle" : "Angle(bindings::Gecko_CSSValue_GetAngle(%s))", + "number" : "bindings::Gecko_CSSValue_GetNumber(%s)", + } + %> + eCSSKeyword_${keyword} => { + ComputedOperation::${name.title()}( + % if name == "matrix": + ComputedMatrix { + % endif + % for index, item in enumerate(items): + % if name == "matrix": + m${index / 4 + 1}${index % 4 + 1}: + % endif + ${css_value_getters[item] % ( + "bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d)" % (index + 1) + )}, + % endfor + % if name == "matrix": + } + % endif + ) + }, + + pub fn clone_transform(&self) -> longhands::transform::computed_value::T { + use app_units::Au; + use gecko_bindings::structs::nsCSSKeyword::*; + use properties::longhands::transform::computed_value; + use properties::longhands::transform::computed_value::ComputedMatrix; + use properties::longhands::transform::computed_value::ComputedOperation; + use values::computed::Angle; + + if self.gecko.mSpecifiedTransform.mRawPtr.is_null() { + return computed_value::T(None); + } + + let mut result = vec![]; + let mut cur = unsafe { (*self.gecko.mSpecifiedTransform.to_safe().get()).mHead }; + while !cur.is_null() { + let gecko_value = unsafe { &(*cur).mValue }; + let transform_function = unsafe { + bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0)) + }; + let servo = unsafe { + match transform_function { + ${computed_operation_arm("matrix", "matrix3d", ["number"] * 16)} + ${computed_operation_arm("skew", "skew", ["angle"] * 2)} + ${computed_operation_arm("translate", "translate3d", ["lop", "lop", "length"])} + ${computed_operation_arm("scale", "scale3d", ["number"] * 3)} + ${computed_operation_arm("rotate", "rotate3d", ["number"] * 3 + ["angle"])} + ${computed_operation_arm("perspective", "perspective", ["length"])} + _ => panic!("We shouldn't set any other transform function types"), + } + }; + result.push(servo); + unsafe { cur = (&*cur).mNext }; + } + computed_value::T(Some(result)) + } + pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) { use nsstring::nsCString; unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };