Bug 1501117 - Part 2: Serialize timing function from web animation api with servo. r=emilio,birtles
authorBoris Chiou <boris.chiou@gmail.com>
Thu, 01 Nov 2018 21:33:56 +0000
changeset 500460 806c9d31d1c6e94ca3e23a24e51753145e1079c5
parent 500459 4356d79217909c08308311a861bc253adc848ecb
child 500461 7afff3818ad7a259f88a0ec3965c46a73b42faef
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio, birtles
bugs1501117
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1501117 - Part 2: Serialize timing function from web animation api with servo. r=emilio,birtles It's worth to serialize the timing function from web animation api with servo, too. However, we need an FFI to do that, so this patch also add a new FFI. Depends on D10443 Differential Revision: https://phabricator.services.mozilla.com/D10444
dom/animation/ComputedTimingFunction.cpp
dom/animation/test/mozilla/test_cubic_bezier_limits.html
layout/style/ServoBindings.h
layout/style/nsCSSKeywordList.h
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
layout/style/nsStyleUtil.cpp
layout/style/nsStyleUtil.h
servo/ports/geckolib/glue.rs
--- a/dom/animation/ComputedTimingFunction.cpp
+++ b/dom/animation/ComputedTimingFunction.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ComputedTimingFunction.h"
+#include "mozilla/ServoBindings.h"
 #include "nsAlgorithm.h" // For clamped()
-#include "nsStyleUtil.h"
 
 namespace mozilla {
 
 void
 ComputedTimingFunction::Init(const nsTimingFunction &aFunction)
 {
   const StyleComputedTimingFunction& timing = aFunction.mTiming;
   switch (timing.tag) {
@@ -173,34 +173,42 @@ ComputedTimingFunction::Compare(const Co
   }
 
   return 0;
 }
 
 void
 ComputedTimingFunction::AppendToString(nsAString& aResult) const
 {
+  nsTimingFunction timing;
   switch (mType) {
     case Type::CubicBezier:
-      nsStyleUtil::AppendCubicBezierTimingFunction(mTimingFunction.X1(),
-                                                   mTimingFunction.Y1(),
-                                                   mTimingFunction.X2(),
-                                                   mTimingFunction.Y2(),
-                                                   aResult);
+      timing.mTiming = StyleComputedTimingFunction::CubicBezier(
+        mTimingFunction.X1(),
+        mTimingFunction.Y1(),
+        mTimingFunction.X2(),
+        mTimingFunction.Y2());
       break;
     case Type::Step:
-      nsStyleUtil::AppendStepsTimingFunction(mSteps.mSteps,
-                                             mSteps.mPos,
-                                             aResult);
+      timing.mTiming = StyleComputedTimingFunction::Steps(
+        mSteps.mSteps,
+        mSteps.mPos);
+      break;
+    case Type::Linear:
+    case Type::Ease:
+    case Type::EaseIn:
+    case Type::EaseOut:
+    case Type::EaseInOut:
+      timing.mTiming = StyleComputedTimingFunction::Keyword(
+        static_cast<StyleTimingKeyword>(mType));
       break;
     default:
-      nsStyleUtil::AppendCubicBezierKeywordTimingFunction(
-        StyleTimingKeyword(uint8_t(mType)), aResult);
-      break;
+      MOZ_ASSERT_UNREACHABLE("Unsupported timing type");
   }
+  Servo_SerializeEasing(&timing, &aResult);
 }
 
 /* static */ int32_t
 ComputedTimingFunction::Compare(const Maybe<ComputedTimingFunction>& aLhs,
                                 const Maybe<ComputedTimingFunction>& aRhs)
 {
   // We can't use |operator<| for const Maybe<>& here because
   // 'ease' is prior to 'linear' which is represented by Nothing().
--- a/dom/animation/test/mozilla/test_cubic_bezier_limits.html
+++ b/dom/animation/test/mozilla/test_cubic_bezier_limits.html
@@ -14,17 +14,17 @@
 }
 </style>
 <div id="log"></div>
 <script>
 'use strict';
 
 // We clamp +infinity or -inifinity value in floating point to
 // maximum floating point value or -maxinum floating point value.
-const max_float = 3.40282e+38;
+const max_float = '3.40282e38';
 
 test(function(t) {
   var div = addDiv(t);
   var anim = div.animate({ }, 100 * MS_PER_SEC);
 
   anim.effect.updateTiming({ easing: 'cubic-bezier(0, 1e+39, 0, 0)' });
   assert_equals(anim.effect.getComputedTiming().easing,
     'cubic-bezier(0, ' + max_float + ', 0, 0)',
@@ -32,22 +32,22 @@ test(function(t) {
 
   anim.effect.updateTiming({ easing: 'cubic-bezier(0, 0, 0, 1e+39)' });
   assert_equals(anim.effect.getComputedTiming().easing,
     'cubic-bezier(0, 0, 0, ' + max_float + ')',
     'y2 control point for effect easing is out of upper boundary');
 
   anim.effect.updateTiming({ easing: 'cubic-bezier(0, -1e+39, 0, 0)' });
   assert_equals(anim.effect.getComputedTiming().easing,
-    'cubic-bezier(0, ' + -max_float + ', 0, 0)',
+    'cubic-bezier(0, ' + '-' + max_float + ', 0, 0)',
     'y1 control point for effect easing is out of lower boundary');
 
   anim.effect.updateTiming({ easing: 'cubic-bezier(0, 0, 0, -1e+39)' });
   assert_equals(anim.effect.getComputedTiming().easing,
-    'cubic-bezier(0, 0, 0, ' + -max_float + ')',
+    'cubic-bezier(0, 0, 0, ' + '-' + max_float + ')',
     'y2 control point for effect easing is out of lower boundary');
 
 }, 'Clamp y1 and y2 control point out of boundaries for effect easing' );
 
 test(function(t) {
   var div = addDiv(t);
   var anim = div.animate({ }, 100 * MS_PER_SEC);
 
@@ -58,22 +58,22 @@ test(function(t) {
 
   anim.effect.setKeyframes([ { easing: 'cubic-bezier(0, 0, 0, 1e+39)' }]);
   assert_equals(anim.effect.getKeyframes()[0].easing,
     'cubic-bezier(0, 0, 0, ' + max_float + ')',
     'y2 control point for keyframe easing is out of upper boundary');
 
   anim.effect.setKeyframes([ { easing: 'cubic-bezier(0, -1e+39, 0, 0)' }]);
   assert_equals(anim.effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, ' + -max_float + ', 0, 0)',
+    'cubic-bezier(0, ' + '-' + max_float + ', 0, 0)',
     'y1 control point for keyframe easing is out of lower boundary');
 
   anim.effect.setKeyframes([ { easing: 'cubic-bezier(0, 0, 0, -1e+39)' }]);
   assert_equals(anim.effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, 0, 0, ' + -max_float + ')',
+    'cubic-bezier(0, 0, 0, ' + '-' + max_float + ')',
     'y2 control point for keyframe easing is out of lower boundary');
 
 }, 'Clamp y1 and y2 control point out of boundaries for keyframe easing' );
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim 100s cubic-bezier(0, 1e+39, 0, 0)';
@@ -84,22 +84,22 @@ test(function(t) {
 
   div.style.animation = 'anim 100s cubic-bezier(0, 0, 0, 1e+39)';
   assert_equals(div.getAnimations()[0].effect.getKeyframes()[0].easing,
     'cubic-bezier(0, 0, 0, ' + max_float + ')',
     'y2 control point for CSS animation is out of upper boundary');
 
   div.style.animation = 'anim 100s cubic-bezier(0, -1e+39, 0, 0)';
   assert_equals(div.getAnimations()[0].effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, ' + -max_float + ', 0, 0)',
+    'cubic-bezier(0, ' + '-' + max_float + ', 0, 0)',
     'y1 control point for CSS animation is out of lower boundary');
 
   div.style.animation = 'anim 100s cubic-bezier(0, 0, 0, -1e+39)';
   assert_equals(div.getAnimations()[0].effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, 0, 0, ' + -max_float + ')',
+    'cubic-bezier(0, 0, 0, ' + '-' + max_float + ')',
     'y2 control point for CSS animation is out of lower boundary');
 
 }, 'Clamp y1 and y2 control point out of boundaries for CSS animation' );
 
 test(function(t) {
   var div = addDiv(t, {'class': 'transition-div'});
 
   div.style.transition = 'margin-left 100s cubic-bezier(0, 1e+39, 0, 0)';
@@ -119,26 +119,26 @@ test(function(t) {
     'y2 control point for CSS transition on upper boundary');
   div.style.transition = '';
   div.style.marginLeft = '';
 
   div.style.transition = 'margin-left 100s cubic-bezier(0, -1e+39, 0, 0)';
   flushComputedStyle(div);
   div.style.marginLeft = '0px';
   assert_equals(div.getAnimations()[0].effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, ' + -max_float + ', 0, 0)',
+    'cubic-bezier(0, ' + '-' + max_float + ', 0, 0)',
     'y1 control point for CSS transition on lower boundary');
   div.style.transition = '';
   div.style.marginLeft = '';
 
   div.style.transition = 'margin-left 100s cubic-bezier(0, 0, 0, -1e+39)';
   flushComputedStyle(div);
   div.style.marginLeft = '0px';
   assert_equals(div.getAnimations()[0].effect.getKeyframes()[0].easing,
-    'cubic-bezier(0, 0, 0, ' + -max_float + ')',
+    'cubic-bezier(0, 0, 0, ' + '-' + max_float + ')',
     'y2 control point for CSS transition on lower boundary');
 
 }, 'Clamp y1 and y2 control point out of boundaries for CSS transition' );
 
 test(function(t) {
   var div = addDiv(t);
   var anim = div.animate({ }, { duration: 100 * MS_PER_SEC, fill: 'forwards' });
 
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -598,16 +598,20 @@ RawServoDeclarationBlockStrong Servo_Par
   nsCompatibility quirks_mode,
   mozilla::css::Loader* loader);
 
 bool Servo_ParseEasing(
   const nsAString* easing,
   RawGeckoURLExtraData* data,
   nsTimingFunctionBorrowedMut output);
 
+void Servo_SerializeEasing(
+  nsTimingFunctionBorrowed easing,
+  nsAString* output);
+
 void Servo_GetComputedKeyframeValues(
   RawGeckoKeyframeListBorrowed keyframes,
   RawGeckoElementBorrowed element,
   ComputedStyleBorrowed style,
   RawServoStyleSetBorrowed set,
   RawGeckoComputedKeyframeValuesListBorrowedMut result);
 
 RawServoAnimationValueStrong Servo_ComputedValues_ExtractAnimationValue(
--- a/layout/style/nsCSSKeywordList.h
+++ b/layout/style/nsCSSKeywordList.h
@@ -100,20 +100,16 @@ CSS_KEY(dashed, dashed)
 CSS_KEY(dense, dense)
 CSS_KEY(default, default)
 CSS_KEY(dot, dot)
 CSS_KEY(dotted, dotted)
 CSS_KEY(double, double)
 CSS_KEY(double-circle, double_circle)
 CSS_KEY(drop-shadow, drop_shadow)
 CSS_KEY(e-resize, e_resize)
-CSS_KEY(ease, ease)
-CSS_KEY(ease-in, ease_in)
-CSS_KEY(ease-in-out, ease_in_out)
-CSS_KEY(ease-out, ease_out)
 CSS_KEY(ellipse, ellipse)
 CSS_KEY(ellipsis, ellipsis)
 CSS_KEY(end, end)
 CSS_KEY(ew-resize, ew_resize)
 CSS_KEY(farthest-side, farthest_side)
 CSS_KEY(fill, fill)
 CSS_KEY(filled, filled)
 CSS_KEY(flex, flex)
@@ -139,17 +135,16 @@ CSS_KEY(interpolatematrix, interpolatema
 CSS_KEY(accumulatematrix, accumulatematrix)
 CSS_KEY(invert, invert)
 CSS_KEY(justify, justify)
 CSS_KEY(last baseline, last_baseline) // only used for DevTools auto-completion
 CSS_KEY(layout, layout)
 CSS_KEY(left, left)
 CSS_KEY(legacy, legacy)
 CSS_KEY(line-through, line_through)
-CSS_KEY(linear, linear)
 CSS_KEY(list-item, list_item)
 CSS_KEY(mandatory, mandatory)
 CSS_KEY(manipulation, manipulation)
 CSS_KEY(match-parent, match_parent)
 CSS_KEY(matrix, matrix)
 CSS_KEY(matrix3d, matrix3d)
 CSS_KEY(max-content, max_content)
 CSS_KEY(middle, middle)
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -613,25 +613,16 @@ const KTableEntry nsCSSProps::kTouchActi
   { eCSSKeyword_none,         NS_STYLE_TOUCH_ACTION_NONE },
   { eCSSKeyword_auto,         NS_STYLE_TOUCH_ACTION_AUTO },
   { eCSSKeyword_pan_x,        NS_STYLE_TOUCH_ACTION_PAN_X },
   { eCSSKeyword_pan_y,        NS_STYLE_TOUCH_ACTION_PAN_Y },
   { eCSSKeyword_manipulation, NS_STYLE_TOUCH_ACTION_MANIPULATION },
   { eCSSKeyword_UNKNOWN,      -1 }
 };
 
-const KTableEntry nsCSSProps::kTransitionTimingFunctionKTable[] = {
-  { eCSSKeyword_linear,       StyleTimingKeyword::Linear },
-  { eCSSKeyword_ease,         StyleTimingKeyword::Ease },
-  { eCSSKeyword_ease_in,      StyleTimingKeyword::EaseIn },
-  { eCSSKeyword_ease_out,     StyleTimingKeyword::EaseOut },
-  { eCSSKeyword_ease_in_out,  StyleTimingKeyword::EaseInOut },
-  { eCSSKeyword_UNKNOWN, -1 }
-};
-
 const KTableEntry nsCSSProps::kVerticalAlignKTable[] = {
   { eCSSKeyword_baseline, NS_STYLE_VERTICAL_ALIGN_BASELINE },
   { eCSSKeyword_sub, NS_STYLE_VERTICAL_ALIGN_SUB },
   { eCSSKeyword_super, NS_STYLE_VERTICAL_ALIGN_SUPER },
   { eCSSKeyword_top, NS_STYLE_VERTICAL_ALIGN_TOP },
   { eCSSKeyword_text_top, NS_STYLE_VERTICAL_ALIGN_TEXT_TOP },
   { eCSSKeyword_middle, NS_STYLE_VERTICAL_ALIGN_MIDDLE },
   { eCSSKeyword__moz_middle_with_baseline, NS_STYLE_VERTICAL_ALIGN_MIDDLE_WITH_BASELINE },
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -346,15 +346,14 @@ public:
   static const KTableEntry kOverscrollBehaviorKTable[];
   static const KTableEntry kScrollSnapTypeKTable[];
   static const KTableEntry kTextAlignKTable[];
   static const KTableEntry kTextDecorationLineKTable[];
   static const KTableEntry kTextDecorationStyleKTable[];
   static const KTableEntry kTextEmphasisStyleShapeKTable[];
   static const KTableEntry kTextOverflowKTable[];
   static const KTableEntry kTouchActionKTable[];
-  static const KTableEntry kTransitionTimingFunctionKTable[];
   static const KTableEntry kVerticalAlignKTable[];
   static const KTableEntry kWidthKTable[]; // also min-width, max-width
   static const KTableEntry kFlexBasisKTable[];
 };
 
 #endif /* nsCSSProps_h___ */
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -269,87 +269,16 @@ nsStyleUtil::AppendPaintOrderValue(uint8
 
       default:
         MOZ_ASSERT_UNREACHABLE("unexpected paint-order component value");
     }
     aValue >>= NS_STYLE_PAINT_ORDER_BITWIDTH;
   }
 }
 
-/* static */ void
-nsStyleUtil::AppendStepsTimingFunction(uint32_t aStepNumber,
-                                       mozilla::StyleStepPosition aStepPos,
-                                       nsAString& aResult)
-{
-  aResult.AppendLiteral("steps(");
-  aResult.AppendInt(aStepNumber);
-  switch (aStepPos) {
-    case StyleStepPosition::JumpStart:
-      aResult.AppendLiteral(", jump-start)");
-      break;
-    case StyleStepPosition::JumpNone:
-      aResult.AppendLiteral(", jump-none)");
-      break;
-    case StyleStepPosition::JumpBoth:
-      aResult.AppendLiteral(", jump-both)");
-      break;
-    case StyleStepPosition::Start:
-      aResult.AppendLiteral(", start)");
-      break;
-    case StyleStepPosition::JumpEnd:
-    case StyleStepPosition::End:
-      aResult.AppendLiteral(")");
-      break;
-    default:
-      MOZ_ASSERT_UNREACHABLE("Unsupported timing function");
-  }
-}
-
-/* static */ void
-nsStyleUtil::AppendCubicBezierTimingFunction(float aX1, float aY1,
-                                             float aX2, float aY2,
-                                             nsAString& aResult)
-{
-  // set the value from the cubic-bezier control points
-  // (We could try to regenerate the keywords if we want.)
-  aResult.AppendLiteral("cubic-bezier(");
-  aResult.AppendFloat(aX1);
-  aResult.AppendLiteral(", ");
-  aResult.AppendFloat(aY1);
-  aResult.AppendLiteral(", ");
-  aResult.AppendFloat(aX2);
-  aResult.AppendLiteral(", ");
-  aResult.AppendFloat(aY2);
-  aResult.Append(')');
-}
-
-/* static */ void
-nsStyleUtil::AppendCubicBezierKeywordTimingFunction(
-    StyleTimingKeyword aType,
-    nsAString& aResult)
-{
-  switch (aType) {
-    case StyleTimingKeyword::Linear:
-    case StyleTimingKeyword::Ease:
-    case StyleTimingKeyword::EaseIn:
-    case StyleTimingKeyword::EaseOut:
-    case StyleTimingKeyword::EaseInOut: {
-      nsCSSKeyword keyword = nsCSSProps::ValueToKeywordEnum(
-          static_cast<int32_t>(aType),
-          nsCSSProps::kTransitionTimingFunctionKTable);
-      AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(keyword),
-                         aResult);
-      break;
-    }
-    default:
-      MOZ_ASSERT_UNREACHABLE("unexpected aType");
-      break;
-  }
-}
-
 /* static */ float
 nsStyleUtil::ColorComponentToFloat(uint8_t aAlpha)
 {
   // Alpha values are expressed as decimals, so we should convert
   // back, using as few decimal places as possible for
   // round-tripping.
   // First try two decimal places:
   float rounded = NS_roundf(float(aAlpha) * 100.0f / 255.0f) / 100.0f;
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -71,26 +71,16 @@ public:
 
   static void AppendPaintOrderValue(uint8_t aValue, nsAString& aResult);
 
   static void AppendCSSNumber(float aNumber, nsAString& aResult)
   {
     aResult.AppendFloat(aNumber);
   }
 
-  static void AppendStepsTimingFunction(uint32_t aStepNumber,
-                                        mozilla::StyleStepPosition aStepPos,
-                                        nsAString& aResult);
-  static void AppendCubicBezierTimingFunction(float aX1, float aY1,
-                                              float aX2, float aY2,
-                                              nsAString& aResult);
-  static void AppendCubicBezierKeywordTimingFunction(
-      mozilla::StyleTimingKeyword aType,
-      nsAString& aResult);
-
   /*
    * Convert an author-provided floating point number to an integer (0
    * ... 255) appropriate for use in the alpha component of a color.
    */
   static uint8_t FloatToColorComponent(float aAlpha)
   {
     NS_ASSERTION(0.0 <= aAlpha && aAlpha <= 1.0, "out of range");
     return NSToIntRound(aAlpha * 255);
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3463,16 +3463,24 @@ pub extern "C" fn Servo_ParseEasing(
             (*output).mTiming = parsed_easing.to_computed_value_without_context();
             true
         },
         Err(_) => false
     }
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn Servo_SerializeEasing(
+    easing: nsTimingFunctionBorrowed,
+    output: *mut nsAString,
+) {
+    easing.mTiming.to_css(&mut CssWriter::new(&mut *output)).unwrap();
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_GetProperties_Overriding_Animation(
     element: RawGeckoElementBorrowed,
     list: RawGeckoCSSPropertyIDListBorrowed,
     set: nsCSSPropertyIDSetBorrowedMut,
 ) {
     let element = GeckoElement(element);
     let element_data = match element.borrow_data() {
         Some(data) => data,