Index: third_party/WebKit/Source/core/css/StylePropertySerializer.cpp |
diff --git a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp |
index d04a3026d7c39a09a847650f02a0101ac516ba64..101a5d7ce4788e31ff88a0f5cfd86382704fda06 100644 |
--- a/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp |
+++ b/third_party/WebKit/Source/core/css/StylePropertySerializer.cpp |
@@ -224,8 +224,10 @@ String StylePropertySerializer::asText() const |
{ |
StringBuilder result; |
- std::bitset<numCSSProperties> shorthandPropertyUsed; |
- std::bitset<numCSSProperties> shorthandPropertyAppeared; |
+ std::bitset<numCSSProperties> longhandSerialized; |
+ std::bitset<numCSSProperties> shorthandAppeared; |
+ |
+ bool backgroundLonghandSeen = false; |
unsigned size = m_propertySet.propertyCount(); |
unsigned numDecls = 0; |
@@ -237,144 +239,11 @@ String StylePropertySerializer::asText() const |
CSSPropertyID propertyID = property.id(); |
// Only enabled properties should be part of the style. |
ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID)); |
- CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; |
- CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; |
- String value; |
// Shorthands with variable references are not expanded at parse time |
// and hence may still be observed during serialization. |
ASSERT(!isShorthandProperty(propertyID) || property.value()->isVariableReferenceValue()); |
switch (propertyID) { |
- case CSSPropertyBackgroundAttachment: |
- case CSSPropertyBackgroundClip: |
- case CSSPropertyBackgroundColor: |
- case CSSPropertyBackgroundImage: |
- case CSSPropertyBackgroundOrigin: |
- case CSSPropertyBackgroundPositionX: |
- case CSSPropertyBackgroundPositionY: |
- case CSSPropertyBackgroundSize: |
- case CSSPropertyBackgroundRepeatX: |
- case CSSPropertyBackgroundRepeatY: |
- shorthandPropertyAppeared.set(CSSPropertyBackground - firstCSSProperty); |
- continue; |
- case CSSPropertyBorderTopWidth: |
- case CSSPropertyBorderRightWidth: |
- case CSSPropertyBorderBottomWidth: |
- case CSSPropertyBorderLeftWidth: |
- if (!borderFallbackShorthandProperty) |
- borderFallbackShorthandProperty = CSSPropertyBorderWidth; |
- case CSSPropertyBorderTopStyle: |
- case CSSPropertyBorderRightStyle: |
- case CSSPropertyBorderBottomStyle: |
- case CSSPropertyBorderLeftStyle: |
- if (!borderFallbackShorthandProperty) |
- borderFallbackShorthandProperty = CSSPropertyBorderStyle; |
- case CSSPropertyBorderTopColor: |
- case CSSPropertyBorderRightColor: |
- case CSSPropertyBorderBottomColor: |
- case CSSPropertyBorderLeftColor: |
- if (!borderFallbackShorthandProperty) |
- borderFallbackShorthandProperty = CSSPropertyBorderColor; |
- |
- // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified. |
- if (!shorthandPropertyAppeared.test(CSSPropertyBorder - firstCSSProperty)) { |
- value = borderPropertyValue(); |
- if (value.isNull()) |
- shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty); |
- else |
- shorthandPropertyID = CSSPropertyBorder; |
- } else if (shorthandPropertyUsed.test(CSSPropertyBorder - firstCSSProperty)) { |
- shorthandPropertyID = CSSPropertyBorder; |
- } |
- if (!shorthandPropertyID) |
- shorthandPropertyID = borderFallbackShorthandProperty; |
- break; |
- case CSSPropertyBorderTopLeftRadius: |
- case CSSPropertyBorderTopRightRadius: |
- case CSSPropertyBorderBottomLeftRadius: |
- case CSSPropertyBorderBottomRightRadius: |
- shorthandPropertyID = CSSPropertyBorderRadius; |
- break; |
- case CSSPropertyWebkitBorderHorizontalSpacing: |
- case CSSPropertyWebkitBorderVerticalSpacing: |
- shorthandPropertyID = CSSPropertyBorderSpacing; |
- break; |
- case CSSPropertyFontFamily: |
- case CSSPropertyLineHeight: |
- case CSSPropertyFontSize: |
- case CSSPropertyFontStretch: |
- case CSSPropertyFontStyle: |
- case CSSPropertyFontVariant: |
- case CSSPropertyFontWeight: |
- // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing. |
- break; |
- case CSSPropertyListStyleType: |
- case CSSPropertyListStylePosition: |
- case CSSPropertyListStyleImage: |
- shorthandPropertyID = CSSPropertyListStyle; |
- break; |
- case CSSPropertyMarginTop: |
- case CSSPropertyMarginRight: |
- case CSSPropertyMarginBottom: |
- case CSSPropertyMarginLeft: |
- shorthandPropertyID = CSSPropertyMargin; |
- break; |
- case CSSPropertyMotionPath: |
- case CSSPropertyMotionOffset: |
- case CSSPropertyMotionRotation: |
- shorthandPropertyID = CSSPropertyMotion; |
- break; |
- case CSSPropertyOutlineWidth: |
- case CSSPropertyOutlineStyle: |
- case CSSPropertyOutlineColor: |
- shorthandPropertyID = CSSPropertyOutline; |
- break; |
- case CSSPropertyOverflowX: |
- case CSSPropertyOverflowY: |
- shorthandPropertyID = CSSPropertyOverflow; |
- break; |
- case CSSPropertyPaddingTop: |
- case CSSPropertyPaddingRight: |
- case CSSPropertyPaddingBottom: |
- case CSSPropertyPaddingLeft: |
- shorthandPropertyID = CSSPropertyPadding; |
- break; |
- case CSSPropertyTransitionProperty: |
- case CSSPropertyTransitionDuration: |
- case CSSPropertyTransitionTimingFunction: |
- case CSSPropertyTransitionDelay: |
- shorthandPropertyID = CSSPropertyTransition; |
- break; |
- case CSSPropertyAnimationName: |
- case CSSPropertyAnimationDuration: |
- case CSSPropertyAnimationTimingFunction: |
- case CSSPropertyAnimationDelay: |
- case CSSPropertyAnimationIterationCount: |
- case CSSPropertyAnimationDirection: |
- case CSSPropertyAnimationFillMode: |
- case CSSPropertyAnimationPlayState: |
- shorthandPropertyID = CSSPropertyAnimation; |
- break; |
- case CSSPropertyFlexDirection: |
- case CSSPropertyFlexWrap: |
- shorthandPropertyID = CSSPropertyFlexFlow; |
- break; |
- case CSSPropertyFlexBasis: |
- case CSSPropertyFlexGrow: |
- case CSSPropertyFlexShrink: |
- shorthandPropertyID = CSSPropertyFlex; |
- break; |
- case CSSPropertyWebkitMaskPositionX: |
- case CSSPropertyWebkitMaskPositionY: |
- case CSSPropertyWebkitMaskRepeatX: |
- case CSSPropertyWebkitMaskRepeatY: |
- case CSSPropertyWebkitMaskImage: |
- case CSSPropertyWebkitMaskRepeat: |
- case CSSPropertyWebkitMaskPosition: |
- case CSSPropertyWebkitMaskClip: |
- case CSSPropertyWebkitMaskOrigin: |
- shorthandPropertyID = CSSPropertyWebkitMask; |
- break; |
case CSSPropertyVariable: |
result.append(getCustomPropertyText(property, numDecls++)); |
continue; |
@@ -387,33 +256,68 @@ String StylePropertySerializer::asText() const |
default: |
break; |
} |
+ if (longhandSerialized.test(propertyID - firstCSSProperty)) |
+ continue; |
- unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty; |
- if (shorthandPropertyID) { |
- if (shorthandPropertyUsed.test(shortPropertyIndex)) |
+ Vector<StylePropertyShorthand, 4> shorthands; |
+ getMatchingShorthandsForLonghand(propertyID, &shorthands); |
+ bool serializedAsShorthand = false; |
+ for (const StylePropertyShorthand& shorthand : shorthands) { |
+ // Some aliases are implemented as a shorthand, in which case |
+ // we prefer to not use the shorthand. |
+ if (shorthand.length() == 1) |
+ continue; |
+ |
+ CSSPropertyID shorthandProperty = shorthand.id(); |
+ int shorthandPropertyIndex = shorthandProperty - firstCSSProperty; |
+ // TODO(timloh): Do we actually need this check? A previous comment |
+ // said "old UAs can't recognize them but are important for editing" |
+ // but Firefox doesn't do this. |
+ if (shorthandProperty == CSSPropertyFont) |
+ continue; |
+ // TODO(timloh): Why is background special? |
+ if (shorthandProperty == CSSPropertyBackground) { |
+ serializedAsShorthand = true; |
+ backgroundLonghandSeen = true; |
+ break; |
+ } |
+ // We already tried serializing as this shorthand |
+ if (shorthandAppeared.test(shorthandPropertyIndex)) |
continue; |
- if (!shorthandPropertyAppeared.test(shortPropertyIndex) && value.isNull()) |
- value = m_propertySet.getPropertyValue(shorthandPropertyID); |
- shorthandPropertyAppeared.set(shortPropertyIndex); |
- } |
- if (!value.isNull()) { |
- if (shorthandPropertyID) { |
- propertyID = shorthandPropertyID; |
- shorthandPropertyUsed.set(shortPropertyIndex); |
+ shorthandAppeared.set(shorthandPropertyIndex); |
+ bool serializedOtherLonghand = false; |
+ for (unsigned i = 0; i < shorthand.length(); i++) { |
+ if (longhandSerialized.test(shorthand.properties()[i] - firstCSSProperty)) { |
+ serializedOtherLonghand = true; |
+ break; |
+ } |
} |
- } else { |
- // We should not show "initial" when the "initial" is implicit. |
- // If explicit "initial", we need to show. |
- if (property.value()->isImplicitInitialValue()) |
+ if (serializedOtherLonghand) |
continue; |
- value = property.value()->cssText(); |
+ |
+ String shorthandResult = StylePropertySerializer::getPropertyValue(shorthandProperty); |
+ if (shorthandResult.isEmpty()) |
+ continue; |
+ |
+ result.append(getPropertyText(shorthandProperty, shorthandResult, property.isImportant(), numDecls++)); |
+ serializedAsShorthand = true; |
+ for (unsigned i = 0; i < shorthand.length(); i++) |
+ longhandSerialized.set(shorthand.properties()[i] - firstCSSProperty); |
+ break; |
} |
- result.append(getPropertyText(propertyID, value, property.isImportant(), numDecls++)); |
+ if (serializedAsShorthand) |
+ continue; |
+ |
+ // TODO(timloh): This is wrong and makes declarations not round-trip. |
+ if (property.value()->isImplicitInitialValue()) |
+ continue; |
+ |
+ result.append(getPropertyText(propertyID, property.value()->cssText(), property.isImportant(), numDecls++)); |
} |
- if (shorthandPropertyAppeared.test(CSSPropertyBackground - firstCSSProperty)) |
+ if (backgroundLonghandSeen) |
appendBackgroundPropertyAsText(result, numDecls); |
ASSERT(!numDecls ^ !result.isEmpty()); |