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
--- 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)