Bug 1272549 - Part 3: Calculate the percent value of translation and the factor of scale. draft
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 03 Oct 2016 14:35:45 +0800
changeset 423544 edf27167285497acbebfc1dfdf16feb9db119e9a
parent 423543 910117d349a5fabede864fd160beca79372389a2
child 423545 daddb95a9627f5e7e39da9167997066e8e6b4029
child 424034 078272d201cc707c8b144534181a320be28e730f
push id31939
push userbmo:boris.chiou@gmail.com
push dateTue, 11 Oct 2016 11:28:54 +0000
bugs1272549
milestone52.0a1
Bug 1272549 - Part 3: Calculate the percent value of translation and the factor of scale. Add one more argument, nsIFrame, in ComputeDistance, so we can get the size of transform reference box. MozReview-Commit-ID: CMx4sbFzhk9
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/KeyframeUtils.cpp
dom/animation/KeyframeUtils.h
dom/base/nsDOMWindowUtils.cpp
dom/smil/nsSMILCSSValueType.cpp
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -260,16 +260,17 @@ KeyframeEffectReadOnly::UpdateProperties
     nsTArray<ComputedKeyframeValues> computedValues =
       KeyframeUtils::GetComputedKeyframeValues(keyframesCopy,
                                                mTarget->mElement,
                                                aStyleContext);
 
     if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
       KeyframeUtils::ApplySpacing(keyframesCopy, SpacingMode::paced,
                                   mEffectOptions.mPacedProperty,
+                                  mTarget->mElement->GetPrimaryFrame(),
                                   computedValues);
     }
 
     properties =
       KeyframeUtils::GetAnimationPropertiesFromKeyframes(keyframesCopy,
                                                          computedValues,
                                                          aStyleContext);
 
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -411,17 +411,18 @@ static void
 DistributeRange(const Range<Keyframe>& aSpacingRange);
 
 static void
 PaceRange(const Range<Keyframe>& aKeyframes,
           const Range<double>& aCumulativeDistances);
 
 static nsTArray<double>
 GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
-                       nsCSSPropertyID aProperty);
+                       nsCSSPropertyID aProperty,
+                       nsIFrame* aFrame);
 
 // ------------------------------------------------------------------
 //
 // Public API
 //
 // ------------------------------------------------------------------
 
 /* static */ nsTArray<Keyframe>
@@ -475,28 +476,30 @@ KeyframeUtils::GetKeyframesFromObject(JS
 
   return keyframes;
 }
 
 /* static */ void
 KeyframeUtils::ApplySpacing(nsTArray<Keyframe>& aKeyframes,
                             SpacingMode aSpacingMode,
                             nsCSSPropertyID aProperty,
+                            nsIFrame* aFrame,
                             nsTArray<ComputedKeyframeValues>& aComputedValues)
 {
   if (aKeyframes.IsEmpty()) {
     return;
   }
 
   nsTArray<double> cumulativeDistances;
   if (aSpacingMode == SpacingMode::paced) {
     MOZ_ASSERT(IsAnimatableProperty(aProperty),
                "Paced property should be animatable");
 
-    cumulativeDistances = GetCumulativeDistances(aComputedValues, aProperty);
+    cumulativeDistances = GetCumulativeDistances(aComputedValues, aProperty,
+                                                 aFrame);
     // Reset the computed offsets if using paced spacing.
     for (Keyframe& keyframe : aKeyframes) {
       keyframe.mComputedOffset = Keyframe::kComputedOffsetNotSet;
     }
   }
 
   // If the first keyframe has an unspecified offset, fill it in with 0%.
   // If there is only a single keyframe, then it gets 100%.
@@ -577,17 +580,17 @@ KeyframeUtils::ApplySpacing(nsTArray<Key
   }
 }
 
 /* static */ void
 KeyframeUtils::ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes)
 {
   nsTArray<ComputedKeyframeValues> emptyArray;
   ApplySpacing(aKeyframes, SpacingMode::distribute, eCSSProperty_UNKNOWN,
-               emptyArray);
+               nullptr, emptyArray);
 }
 
 /* static */ nsTArray<ComputedKeyframeValues>
 KeyframeUtils::GetComputedKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
                                          dom::Element* aElement,
                                          nsStyleContext* aStyleContext)
 {
   MOZ_ASSERT(aStyleContext);
@@ -1558,22 +1561,24 @@ PaceRange(const Range<Keyframe>& aKeyfra
   }
 }
 
 /**
  * Get cumulative distances for the paced property.
  *
  * @param aValues The computed values returned by GetComputedKeyframeValues.
  * @param aPacedProperty The paced property.
+ * @param aFrame The frame used to calculate the spacing on transform property.
  * @return The cumulative distances for the paced property. The length will be
  *   the same as aValues.
  */
 static nsTArray<double>
 GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
-                       nsCSSPropertyID aPacedProperty)
+                       nsCSSPropertyID aPacedProperty,
+                       nsIFrame* aFrame)
 {
   // a) If aPacedProperty is a shorthand property, get its components.
   //    Otherwise, just add the longhand property into the set.
   size_t pacedPropertyCount = 0;
   nsCSSPropertyIDSet pacedPropertySet;
   bool isShorthand = nsCSSProps::IsShorthand(aPacedProperty);
   if (isShorthand) {
     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPacedProperty,
@@ -1631,29 +1636,31 @@ GetCumulativeDistances(const nsTArray<Co
           MOZ_ASSERT(pacedValues[propIdx].mProperty == prop,
                      "Property mismatch");
 
           double componentDistance = 0.0;
           if (StyleAnimationValue::ComputeDistance(
                 prop,
                 prevPacedValues[propIdx].mValue,
                 pacedValues[propIdx].mValue,
+                aFrame,
                 componentDistance)) {
             dist += componentDistance * componentDistance;
           }
         }
         dist = sqrt(dist);
       } else {
         // If the property is longhand, we just use the 1st value.
         // If ComputeDistance() fails, |dist| will remain zero so there will be
         // no distance between the previous paced value and this value.
         Unused <<
           StyleAnimationValue::ComputeDistance(aPacedProperty,
                                                prevPacedValues[0].mValue,
                                                pacedValues[0].mValue,
+                                               aFrame,
                                                dist);
       }
       cumulativeDistances[i] = cumulativeDistances[preIdx] + dist;
     }
     prevPacedValues.SwapElements(pacedValues);
     preIdx = i;
   }
   return cumulativeDistances;
--- a/dom/animation/KeyframeUtils.h
+++ b/dom/animation/KeyframeUtils.h
@@ -89,24 +89,27 @@ public:
    *
    * https://w3c.github.io/web-animations/#spacing-keyframes
    *
    * @param aKeyframes The set of keyframes to adjust.
    * @param aSpacingMode The spacing mode to apply.
    * @param aProperty The paced property. Only used when |aSpacingMode| is
    *   SpacingMode::paced. In all other cases it is ignored and hence may be
    *   any value, e.g. eCSSProperty_UNKNOWN.
+   * @param aFrame The primary frame of the current target for calculating paced
+   *               animation on transform property.
    * @param aComputedValues The set of computed keyframe values as returned by
    *   GetComputedKeyframeValues. Only used when |aSpacingMode| is
    *   SpacingMode::paced. In all other cases this parameter is unused and may
    *   be any value including an empty array.
    */
   static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
                            SpacingMode aSpacingMode,
                            nsCSSPropertyID aProperty,
+                           nsIFrame* aFrame,
                            nsTArray<ComputedKeyframeValues>& aComputedValues);
 
   /**
    * Wrapper for ApplySpacing to simplify using distribute spacing.
    *
    * @param aKeyframes The set of keyframes to adjust.
    */
   static void ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes);
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -2704,17 +2704,18 @@ nsDOMWindowUtils::ComputeAnimationDistan
 
   StyleAnimationValue v1, v2;
   if (property == eCSSProperty_UNKNOWN ||
       !ComputeAnimationValue(property, content->AsElement(), aValue1, v1) ||
       !ComputeAnimationValue(property, content->AsElement(), aValue2, v2)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
-  if (!StyleAnimationValue::ComputeDistance(property, v1, v2, *aResult)) {
+  if (!StyleAnimationValue::ComputeDistance(property, v1, v2, nullptr,
+        *aResult)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -273,16 +273,17 @@ nsSMILCSSValueType::ComputeDistance(cons
     &fromWrapper->mCSSValue : nullptr;
   const StyleAnimationValue* toCSSValue = &toWrapper->mCSSValue;
   if (!FinalizeStyleAnimationValues(fromCSSValue, toCSSValue)) {
     return NS_ERROR_FAILURE;
   }
 
   return StyleAnimationValue::ComputeDistance(toWrapper->mPropID,
                                               *fromCSSValue, *toCSSValue,
+                                              nullptr,
                                               aDistance) ?
     NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal,
                                 const nsSMILValue& aEndVal,
                                 double aUnitDistance,
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -715,17 +715,18 @@ StyleAnimationValue::ComputeColorDistanc
   double diffR = startR - endR;
   double diffG = startG - endG;
   double diffB = startB - endB;
   return sqrt(diffA * diffA + diffR * diffR + diffG * diffG + diffB * diffB);
 }
 
 static double
 ComputeTransformDistance(nsCSSValue::Array* aArray1,
-                         nsCSSValue::Array* aArray2)
+                         nsCSSValue::Array* aArray2,
+                         nsIFrame* aFrame)
 {
   if (!aArray1 || !aArray2) {
     return 0.0;
   }
 
   RefPtr<nsCSSValue::Array> a1 = ToPrimitive(aArray1),
                             a2 = ToPrimitive(aArray2);
   nsCSSKeyword tfunc = nsStyleTransformMatrix::TransformFunctionOf(a1);
@@ -736,21 +737,38 @@ ComputeTransformDistance(nsCSSValue::Arr
     case eCSSKeyword_translate3d: {
       MOZ_ASSERT(a1->Count() == 4, "unexpected count");
       MOZ_ASSERT(a2->Count() == 4, "unexpected count");
 
       nsCSSValue x, y, z;
       AddTransformTranslate(1.0, a2->Item(1), -1.0, a1->Item(1), x);
       AddTransformTranslate(1.0, a2->Item(2), -1.0, a1->Item(2), y);
       AddTransformTranslate(1.0, a2->Item(3), -1.0, a1->Item(3), z);
-      // TODO: Calculate the percent part. This will be fixed in the next patch.
-      // Drop percent part because we cannot calculate it now.
+
+      // Initialize them without percent part.
       double c1 = ExtractCalcValue(x).mLength;
       double c2 = ExtractCalcValue(y).mLength;
       double c3 = z.GetFloatValue();
+      if (aFrame) {
+        using namespace nsStyleTransformMatrix;
+        TransformReferenceBox refBox(aFrame);
+        RuleNodeCacheConditions dontCare;
+        c1 = ProcessTranslatePart(x,
+                                  aFrame->StyleContext(),
+                                  aFrame->PresContext(),
+                                  dontCare,
+                                  &refBox,
+                                  &TransformReferenceBox::Width);
+        c2 = ProcessTranslatePart(y,
+                                  aFrame->StyleContext(),
+                                  aFrame->PresContext(),
+                                  dontCare,
+                                  &refBox,
+                                  &TransformReferenceBox::Height);
+      }
       distance = c1 * c1 + c2 * c2 + c3 * c3;
       break;
     }
     case eCSSKeyword_scale3d: {
       MOZ_ASSERT(a1->Count() == 4, "unexpected count");
       MOZ_ASSERT(a2->Count() == 4, "unexpected count");
 
       auto ComputeScaleDiff = [](const nsCSSValue& aValue1,
@@ -835,32 +853,35 @@ ComputeTransformDistance(nsCSSValue::Arr
       MOZ_ASSERT_UNREACHABLE("Unsupported transform function");
       break;
   }
   return distance;
 }
 
 static double
 ComputeTransformListDistance(const nsCSSValueList* aList1,
-                             const nsCSSValueList* aList2)
+                             const nsCSSValueList* aList2,
+                             nsIFrame* aFrame)
 {
   double distance = 0.0;
   do {
     distance += ComputeTransformDistance(aList1->mValue.GetArrayValue(),
-                                         aList2->mValue.GetArrayValue());
+                                         aList2->mValue.GetArrayValue(),
+                                         aFrame);
     aList1 = aList1->mNext;
     aList2 = aList2->mNext;
   } while (aList1);
   return sqrt(distance);
 }
 
 bool
 StyleAnimationValue::ComputeDistance(nsCSSPropertyID aProperty,
                                      const StyleAnimationValue& aStartValue,
                                      const StyleAnimationValue& aEndValue,
+                                     nsIFrame* aFrame,
                                      double& aDistance)
 {
   Unit commonUnit =
     GetCommonUnit(aProperty, aStartValue.GetUnit(), aEndValue.GetUnit());
 
   switch (commonUnit) {
     case eUnit_Null:
     case eUnit_Auto:
@@ -1271,17 +1292,17 @@ StyleAnimationValue::ComputeDistance(nsC
         if (item1 || item2) {
           // Either |break| above or length mismatch.
 
           // TODO: Implement this for mismatched transform function in the later
           // patch.
           aDistance = 0.0;
           return false;
         } else {
-          aDistance = ComputeTransformListDistance(list1, list2);
+          aDistance = ComputeTransformListDistance(list1, list2, aFrame);
         }
       }
       return true;
     }
     case eUnit_BackgroundPositionCoord: {
       const nsCSSValueList *position1 = aStartValue.GetCSSValueListValue();
       const nsCSSValueList *position2 = aEndValue.GetCSSValueListValue();
 
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -89,16 +89,17 @@ public:
    *                    should be calculated.
    * @param aDistance   The result of the calculation.
    * @return true on success, false on failure.
    */
   static MOZ_MUST_USE bool
   ComputeDistance(nsCSSPropertyID aProperty,
                   const StyleAnimationValue& aStartValue,
                   const StyleAnimationValue& aEndValue,
+                  nsIFrame* aFrame,
                   double& aDistance);
 
   /**
    * Calculates an interpolated value that is the specified |aPortion| between
    * the two given values.
    *
    * This really just does the following calculation:
    *   aResultValue = (1.0 - aPortion) * aStartValue + aPortion * aEndValue