Bug 1245748 - Split PropertyPriorityComparator into a separate (reusable) class; r=heycam draft
authorBrian Birtles <birtles@gmail.com>
Tue, 22 Mar 2016 16:33:11 +0900
changeset 344233 9696424d5432adb4d99c52cbf5d37be4ebd044ee
parent 344232 740bdb5da4a8d232c68c43561bb8787237ce91fa
child 344234 4e8faf1740a5f145cd565c23223758639320ba23
push id13778
push userbbirtles@mozilla.com
push dateThu, 24 Mar 2016 03:27:42 +0000
reviewersheycam
bugs1245748
milestone48.0a1
Bug 1245748 - Split PropertyPriorityComparator into a separate (reusable) class; r=heycam MozReview-Commit-ID: Gq5VylZoS2q
dom/animation/KeyframeUtils.cpp
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -34,96 +34,132 @@ namespace mozilla {
 //
 // ------------------------------------------------------------------
 
 // For the aAllowList parameter of AppendStringOrStringSequence and
 // GetPropertyValuesPairs.
 enum class ListAllowance { eDisallow, eAllow };
 
 /**
+ * A comparator to sort nsCSSProperty values such that longhands are sorted
+ * before shorthands, and shorthands with less components are sorted before
+ * shorthands with more components.
+ *
+ * Using this allows us to prioritize values specified by longhands (or smaller
+ * shorthand subsets) when longhands and shorthands are both specified
+ * on the one keyframe.
+ *
+ * Example orderings that result from this:
+ *
+ *   margin-left, margin
+ *
+ * and:
+ *
+ *   border-top-color, border-color, border-top, border
+ */
+class PropertyPriorityComparator
+{
+public:
+  PropertyPriorityComparator()
+    : mSubpropertyCountInitialized(false) {}
+
+  bool Equals(nsCSSProperty aLhs, nsCSSProperty aRhs) const
+  {
+    return aLhs == aRhs;
+  }
+
+  bool LessThan(nsCSSProperty aLhs,
+                nsCSSProperty aRhs) const
+  {
+    bool isShorthandLhs = nsCSSProps::IsShorthand(aLhs);
+    bool isShorthandRhs = nsCSSProps::IsShorthand(aRhs);
+
+    if (isShorthandLhs) {
+      if (isShorthandRhs) {
+        // First, sort shorthands by the number of longhands they have.
+        uint32_t subpropCountLhs = SubpropertyCount(aLhs);
+        uint32_t subpropCountRhs = SubpropertyCount(aRhs);
+        if (subpropCountLhs != subpropCountRhs) {
+          return subpropCountLhs < subpropCountRhs;
+        }
+        // Otherwise, sort by IDL name below.
+      } else {
+        // Put longhands before shorthands.
+        return false;
+      }
+    } else {
+      if (isShorthandRhs) {
+        // Put longhands before shorthands.
+        return true;
+      }
+    }
+    // For two longhand properties, or two shorthand with the same number
+    // of longhand components, sort by IDL name.
+    return nsCSSProps::PropertyIDLNameSortPosition(aLhs) <
+           nsCSSProps::PropertyIDLNameSortPosition(aRhs);
+  }
+
+  uint32_t SubpropertyCount(nsCSSProperty aProperty) const
+  {
+    if (!mSubpropertyCountInitialized) {
+      PodZero(&mSubpropertyCount);
+      mSubpropertyCountInitialized = true;
+    }
+    if (mSubpropertyCount[aProperty] == 0) {
+      uint32_t count = 0;
+      CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
+          p, aProperty, nsCSSProps::eEnabledForAllContent) {
+        ++count;
+      }
+      mSubpropertyCount[aProperty] = count;
+    }
+    return mSubpropertyCount[aProperty];
+  }
+
+private:
+  // Cache of shorthand subproperty counts.
+  mutable RangedArray<
+    uint32_t,
+    eCSSProperty_COUNT_no_shorthands,
+    eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands> mSubpropertyCount;
+  mutable bool mSubpropertyCountInitialized;
+};
+
+/**
+ * Adaptor for PropertyPriorityComparator to sort objects which have
+ * a mProperty member.
+ */
+template <typename T>
+class TPropertyPriorityComparator : PropertyPriorityComparator
+{
+public:
+  bool Equals(const T& aLhs, const T& aRhs) const
+  {
+    return PropertyPriorityComparator::Equals(aLhs.mProperty, aRhs.mProperty);
+  }
+  bool LessThan(const T& aLhs, const T& aRhs) const
+  {
+    return PropertyPriorityComparator::LessThan(aLhs.mProperty, aRhs.mProperty);
+  }
+};
+
+/**
  * A property-values pair obtained from the open-ended properties
  * discovered on a regular keyframe or property-indexed keyframe object.
  *
  * Single values (as required by a regular keyframe, and as also supported
  * on property-indexed keyframes) are stored as the only element in
  * mValues.
  */
 struct PropertyValuesPair
 {
   nsCSSProperty mProperty;
   nsTArray<nsString> mValues;
 
-  class PropertyPriorityComparator
-  {
-  public:
-    PropertyPriorityComparator()
-      : mSubpropertyCountInitialized(false) {}
-
-    bool Equals(const PropertyValuesPair& aLhs,
-                const PropertyValuesPair& aRhs) const
-    {
-      return aLhs.mProperty == aRhs.mProperty;
-    }
-
-    bool LessThan(const PropertyValuesPair& aLhs,
-                  const PropertyValuesPair& aRhs) const
-    {
-      bool isShorthandLhs = nsCSSProps::IsShorthand(aLhs.mProperty);
-      bool isShorthandRhs = nsCSSProps::IsShorthand(aRhs.mProperty);
-
-      if (isShorthandLhs) {
-        if (isShorthandRhs) {
-          // First, sort shorthands by the number of longhands they have.
-          uint32_t subpropCountLhs = SubpropertyCount(aLhs.mProperty);
-          uint32_t subpropCountRhs = SubpropertyCount(aRhs.mProperty);
-          if (subpropCountLhs != subpropCountRhs) {
-            return subpropCountLhs < subpropCountRhs;
-          }
-          // Otherwise, sort by IDL name below.
-        } else {
-          // Put longhands before shorthands.
-          return false;
-        }
-      } else {
-        if (isShorthandRhs) {
-          // Put longhands before shorthands.
-          return true;
-        }
-      }
-      // For two longhand properties, or two shorthand with the same number
-      // of longhand components, sort by IDL name.
-      return nsCSSProps::PropertyIDLNameSortPosition(aLhs.mProperty) <
-             nsCSSProps::PropertyIDLNameSortPosition(aRhs.mProperty);
-    }
-
-    uint32_t SubpropertyCount(nsCSSProperty aProperty) const
-    {
-      if (!mSubpropertyCountInitialized) {
-        PodZero(&mSubpropertyCount);
-        mSubpropertyCountInitialized = true;
-      }
-      if (mSubpropertyCount[aProperty] == 0) {
-        uint32_t count = 0;
-        CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
-            p, aProperty, nsCSSProps::eEnabledForAllContent) {
-          ++count;
-        }
-        mSubpropertyCount[aProperty] = count;
-      }
-      return mSubpropertyCount[aProperty];
-    }
-
-  private:
-    // Cache of shorthand subproperty counts.
-    mutable RangedArray<
-      uint32_t,
-      eCSSProperty_COUNT_no_shorthands,
-      eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands> mSubpropertyCount;
-    mutable bool mSubpropertyCountInitialized;
-  };
+  typedef TPropertyPriorityComparator<PropertyValuesPair> Comparator;
 };
 
 /**
  * The result of parsing a JS object as a BaseKeyframe dictionary
  * and getting its property-value pairs from its open-ended
  * properties.
  */
 struct OffsetIndexedKeyframe
@@ -961,29 +997,18 @@ GenerateValueEntries(Element* aTarget,
 
     // keyframe.mPropertyValuePairs is currently sorted by CSS property IDL
     // name, since that was the order we read the properties from the JS
     // object.  Re-sort the list so that longhand properties appear before
     // shorthands, and with shorthands all appearing in increasing order of
     // number of components.  For two longhand properties, or two shorthands
     // with the same number of components, sort by IDL name.
     //
-    // Example orderings that result from this:
-    //
-    //   margin-left, margin
-    //
-    // and:
-    //
-    //   border-top-color, border-color, border-top, border
-    //
-    // This allows us to prioritize values specified by longhands (or smaller
-    // shorthand subsets) when longhands and shorthands are both specified
-    // on the one keyframe.
-    keyframe.mPropertyValuePairs.Sort(
-        PropertyValuesPair::PropertyPriorityComparator());
+    // @see PropertyPriorityComparator.
+    keyframe.mPropertyValuePairs.Sort(PropertyValuesPair::Comparator());
 
     nsCSSPropertySet propertiesOnThisKeyframe;
     for (const PropertyValuesPair& pair : keyframe.mPropertyValuePairs) {
       MOZ_ASSERT(pair.mValues.Length() == 1,
                  "ConvertKeyframeSequence should have parsed single "
                  "DOMString values from the property-values pairs");
       // Parse the property's string value and produce a KeyframeValueEntry (or
       // more than one, for shorthands) for it.