Bug 1377541 - Reorder shadow array when serializing. r?birtles draft
authorMantaroh Yoshinaga <mantaroh@gmail.com>
Tue, 01 Aug 2017 23:22:05 +0900
changeset 619071 2be914dac57cdeda15734ac4bc7db47e5b0cbff1
parent 619070 23115d650d6085b94801e465f260fece7e8b07dd
child 640287 863db58f3e1c6fccce3d53f3b7d2f2797c1e8a2d
push id71562
push usermantaroh@gmail.com
push dateTue, 01 Aug 2017 14:30:59 +0000
reviewersbirtles
bugs1377541
milestone56.0a1
Bug 1377541 - Reorder shadow array when serializing. r?birtles CSSparserImpl::ParserShadowItem stores shadow items in a different order that does not match the order we use when serializing computed shadow items. The items order of storing by parser: <length> <length> <length> <length> <color> <inset> The items order of serializing: <color> <length> <length> <length> <length> <inset> Spec of this serialized order is as follow: https://github.com/w3c/csswg-drafts/commit/5c46d7810730ac8b7bad2f8194ca24f7e30060b3 This patch will shuffle the order of this items in the shadow array when serializing it. MozReview-Commit-ID: CIawpYKKIRy
layout/style/nsCSSValue.cpp
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -1307,16 +1307,36 @@ nsCSSValue::AppendAlignJustifyValueToStr
   // Don't serialize the 'unsafe' keyword; it's the default.
   if (MOZ_UNLIKELY(overflowPos == NS_STYLE_ALIGN_SAFE)) {
     aResult.Append(' ');
     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(overflowPos, kwtable),
                        aResult);
   }
 }
 
+/**
+ * Returns a re-ordered version of an csCSSValue::Array representing a shadow
+ * item (including a drop-shadow() filter function) suitable for serialization.
+ */
+static already_AddRefed<nsCSSValue::Array>
+GetReorderedShadowArrayForSerialization(const nsCSSValue::Array* aOriginalArray)
+{
+  MOZ_ASSERT(aOriginalArray);
+
+  RefPtr<nsCSSValue::Array> reorderArray = nsCSSValue::Array::Create(6);
+
+  reorderArray->Item(0) = aOriginalArray->Item(4); // Color
+  for (uint8_t i = 0; i < 4; i++) {
+    reorderArray->Item(i + 1) = aOriginalArray->Item(i); // Length
+  }
+  reorderArray->Item(5) = aOriginalArray->Item(5); // Inset
+
+  return reorderArray.forget();
+}
+
 void
 nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
                            Serialization aSerialization) const
 {
   // eCSSProperty_UNKNOWN gets used for some recursive calls below.
   MOZ_ASSERT((0 <= aProperty &&
               aProperty <= eCSSProperty_COUNT_no_shorthands) ||
              aProperty == eCSSProperty_UNKNOWN ||
@@ -1346,16 +1366,29 @@ nsCSSValue::AppendToString(nsCSSProperty
       case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
       case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break;
       case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break;
       case eCSSUnit_Symbols: aResult.AppendLiteral("symbols("); break;
       default: break;
     }
 
     nsCSSValue::Array *array = GetArrayValue();
+
+    // CSSParserImpl::ParseShadowItem stores shadow items in a specific order
+    // that does not match the order we use when serializing computed shadow
+    // items. In order to match the computed value order, we shuffle the items
+    // in the shadow array before serializing it.
+    RefPtr<nsCSSValue::Array> reordered;
+    if (aProperty == eCSSProperty_text_shadow ||
+        aProperty == eCSSProperty_box_shadow ||
+        aProperty == eCSSProperty_filter) {
+      reordered = GetReorderedShadowArrayForSerialization(array);
+      array = reordered.get();
+    }
+
     bool mark = false;
     for (size_t i = 0, i_end = array->Count(); i < i_end; ++i) {
       if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
         if ((unit == eCSSUnit_Array &&
              eCSSProperty_transition_timing_function != aProperty) ||
             unit == eCSSUnit_Symbols)
           aResult.Append(' ');
         else if (unit != eCSSUnit_Steps)