diff options
Diffstat (limited to 'Source/WebCore/css/StylePropertySet.cpp')
-rw-r--r-- | Source/WebCore/css/StylePropertySet.cpp | 288 |
1 files changed, 174 insertions, 114 deletions
diff --git a/Source/WebCore/css/StylePropertySet.cpp b/Source/WebCore/css/StylePropertySet.cpp index 5e522af92..110b802c9 100644 --- a/Source/WebCore/css/StylePropertySet.cpp +++ b/Source/WebCore/css/StylePropertySet.cpp @@ -34,6 +34,10 @@ #include <wtf/MemoryInstrumentationVector.h> #include <wtf/text/StringBuilder.h> +#if ENABLE(CSS_VARIABLES) +#include "CSSVariableValue.h" +#endif + #ifndef NDEBUG #include <stdio.h> #include <wtf/ASCIICType.h> @@ -51,14 +55,14 @@ static PropertySetCSSOMWrapperMap& propertySetCSSOMWrapperMap() return propertySetCSSOMWrapperMapInstance; } -static size_t immutableStylePropertySetSize(unsigned count) +static size_t sizeForImmutableStylePropertySetWithPropertyCount(unsigned count) { - return sizeof(ImmutableStylePropertySet) + sizeof(CSSProperty) * count; + return sizeof(ImmutableStylePropertySet) - sizeof(void*) + sizeof(CSSValue*) * count + sizeof(StylePropertyMetadata) * count; } PassRefPtr<StylePropertySet> StylePropertySet::createImmutable(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode) { - void* slot = WTF::fastMalloc(immutableStylePropertySetSize(count)); + void* slot = WTF::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count)); return adoptRef(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode)); } @@ -80,8 +84,20 @@ MutableStylePropertySet::MutableStylePropertySet(const CSSProperty* properties, ImmutableStylePropertySet::ImmutableStylePropertySet(const CSSProperty* properties, unsigned length, CSSParserMode cssParserMode) : StylePropertySet(cssParserMode, length) { - for (unsigned i = 0; i < length; ++i) - new (&reinterpret_cast<CSSProperty*>(&m_propertyArray)[i]) CSSProperty(properties[i]); + StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(immutableMetadataArray()); + CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray()); + for (unsigned i = 0; i < length; ++i) { + metadataArray[i] = properties[i].metadata(); + valueArray[i] = properties[i].value(); + valueArray[i]->ref(); + } +} + +ImmutableStylePropertySet::~ImmutableStylePropertySet() +{ + CSSValue** valueArray = const_cast<CSSValue**>(immutableValueArray()); + for (unsigned i = 0; i < m_arraySize; ++i) + valueArray[i]->deref(); } MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) @@ -92,16 +108,10 @@ MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other) else { m_propertyVector.reserveInitialCapacity(other.propertyCount()); for (unsigned i = 0; i < other.propertyCount(); ++i) - m_propertyVector.uncheckedAppend(other.immutablePropertyArray()[i]); + m_propertyVector.uncheckedAppend(other.propertyAt(i).toCSSProperty()); } } -ImmutableStylePropertySet::~ImmutableStylePropertySet() -{ - for (unsigned i = 0; i < m_arraySize; ++i) - immutablePropertyArray()[i].~CSSProperty(); -} - StylePropertySet::~StylePropertySet() { ASSERT(!m_ownsCSSOMWrapper || propertySetCSSOMWrapperMap().contains(this)); @@ -206,16 +216,17 @@ String StylePropertySet::borderSpacingValue(const StylePropertyShorthand& shorth return horizontalValueCSSText + ' ' + verticalValueCSSText; } -bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyId, StringBuilder& result) const +bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyID, StringBuilder& result) const { - const CSSProperty* property = findPropertyWithId(propertyId); - if (!property) + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) return false; // All longhands must have at least implicit values if "font" is specified. - if (property->isImplicit()) + + if (propertyAt(foundPropertyIndex).isImplicit()) return true; char prefix = '\0'; - switch (propertyId) { + switch (propertyID) { case CSSPropertyFontStyle: break; // No prefix. case CSSPropertyFontFamily: @@ -232,15 +243,19 @@ bool StylePropertySet::appendFontLonghandValueIfExplicit(CSSPropertyID propertyI if (prefix && !result.isEmpty()) result.append(prefix); - result.append(property->value()->cssText()); + result.append(propertyAt(foundPropertyIndex).value()->cssText()); return true; } String StylePropertySet::fontValue() const { - const CSSProperty* fontSizeProperty = findPropertyWithId(CSSPropertyFontSize); - if (!fontSizeProperty || fontSizeProperty->isImplicit()) + int foundPropertyIndex = findPropertyIndex(CSSPropertyFontSize); + if (foundPropertyIndex == -1) + return emptyString(); + + PropertyReference fontSizeProperty = propertyAt(foundPropertyIndex); + if (fontSizeProperty.isImplicit()) return emptyString(); StringBuilder result; @@ -250,7 +265,7 @@ String StylePropertySet::fontValue() const success &= appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result); if (!result.isEmpty()) result.append(' '); - result.append(fontSizeProperty->value()->cssText()); + result.append(fontSizeProperty.value()->cssText()); success &= appendFontLonghandValueIfExplicit(CSSPropertyLineHeight, result); success &= appendFontLonghandValueIfExplicit(CSSPropertyFontFamily, result); if (!success) { @@ -265,36 +280,44 @@ String StylePropertySet::fontValue() const String StylePropertySet::get4Values(const StylePropertyShorthand& shorthand) const { // Assume the properties are in the usual order top, right, bottom, left. - const CSSProperty* top = findPropertyWithId(shorthand.properties()[0]); - const CSSProperty* right = findPropertyWithId(shorthand.properties()[1]); - const CSSProperty* bottom = findPropertyWithId(shorthand.properties()[2]); - const CSSProperty* left = findPropertyWithId(shorthand.properties()[3]); + int topValueIndex = findPropertyIndex(shorthand.properties()[0]); + int rightValueIndex = findPropertyIndex(shorthand.properties()[1]); + int bottomValueIndex = findPropertyIndex(shorthand.properties()[2]); + int leftValueIndex = findPropertyIndex(shorthand.properties()[3]); + + if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 || leftValueIndex == -1) + return String(); + + PropertyReference top = propertyAt(topValueIndex); + PropertyReference right = propertyAt(rightValueIndex); + PropertyReference bottom = propertyAt(bottomValueIndex); + PropertyReference left = propertyAt(leftValueIndex); // All 4 properties must be specified. - if (!top || !top->value() || !right || !right->value() || !bottom || !bottom->value() || !left || !left->value()) + if (!top.value() || !right.value() || !bottom.value() || !left.value()) return String(); - if (top->value()->isInitialValue() || right->value()->isInitialValue() || bottom->value()->isInitialValue() || left->value()->isInitialValue()) + if (top.value()->isInitialValue() || right.value()->isInitialValue() || bottom.value()->isInitialValue() || left.value()->isInitialValue()) return String(); - if (top->isImportant() != right->isImportant() || right->isImportant() != bottom->isImportant() || bottom->isImportant() != left->isImportant()) + if (top.isImportant() != right.isImportant() || right.isImportant() != bottom.isImportant() || bottom.isImportant() != left.isImportant()) return String(); - bool showLeft = right->value()->cssText() != left->value()->cssText(); - bool showBottom = (top->value()->cssText() != bottom->value()->cssText()) || showLeft; - bool showRight = (top->value()->cssText() != right->value()->cssText()) || showBottom; + bool showLeft = right.value()->cssText() != left.value()->cssText(); + bool showBottom = (top.value()->cssText() != bottom.value()->cssText()) || showLeft; + bool showRight = (top.value()->cssText() != right.value()->cssText()) || showBottom; StringBuilder result; - result.append(top->value()->cssText()); + result.append(top.value()->cssText()); if (showRight) { result.append(' '); - result.append(right->value()->cssText()); + result.append(right.value()->cssText()); } if (showBottom) { result.append(' '); - result.append(bottom->value()->cssText()); + result.append(bottom.value()->cssText()); } if (showLeft) { result.append(' '); - result.append(left->value()->cssText()); + result.append(left.value()->cssText()); } return result.toString(); } @@ -480,8 +503,10 @@ String StylePropertySet::borderPropertyValue(CommonValueMode valueMode) const PassRefPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->value() : 0; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return 0; + return propertyAt(foundPropertyIndex).value(); } bool StylePropertySet::removeShorthandProperty(CSSPropertyID propertyID) @@ -503,28 +528,28 @@ bool StylePropertySet::removeProperty(CSSPropertyID propertyID, String* returnTe return true; } - CSSProperty* foundProperty = findPropertyWithId(propertyID); - if (!foundProperty) { + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) { if (returnText) *returnText = ""; return false; } if (returnText) - *returnText = foundProperty->value()->cssText(); + *returnText = propertyAt(foundPropertyIndex).value()->cssText(); // A more efficient removal strategy would involve marking entries as empty // and sweeping them when the vector grows too big. - mutablePropertyVector().remove(foundProperty - mutablePropertyVector().data()); + mutablePropertyVector().remove(foundPropertyIndex); return true; } bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - if (property) - return property->isImportant(); + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex != -1) + return propertyAt(foundPropertyIndex).isImportant(); StylePropertyShorthand shorthand = shorthandForProperty(propertyID); if (!shorthand.length()) @@ -539,14 +564,18 @@ bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const CSSPropertyID StylePropertySet::getPropertyShorthand(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->shorthandID() : CSSPropertyInvalid; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return CSSPropertyInvalid; + return propertyAt(foundPropertyIndex).shorthandID(); } bool StylePropertySet::isPropertyImplicit(CSSPropertyID propertyID) const { - const CSSProperty* property = findPropertyWithId(propertyID); - return property ? property->isImplicit() : false; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return false; + return propertyAt(foundPropertyIndex).isImplicit(); } bool StylePropertySet::setProperty(CSSPropertyID propertyID, const String& value, bool important, StyleSheetContents* contextStyleSheet) @@ -577,20 +606,20 @@ void StylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtr<CSSValue RefPtr<CSSValue> value = prpValue; for (unsigned i = 0; i < shorthand.length(); ++i) - append(CSSProperty(shorthand.properties()[i], value, important)); + mutablePropertyVector().append(CSSProperty(shorthand.properties()[i], value, important)); } void StylePropertySet::setProperty(const CSSProperty& property, CSSProperty* slot) { ASSERT(isMutable()); if (!removeShorthandProperty(property.id())) { - CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id()); + CSSProperty* toReplace = slot ? slot : findMutableCSSPropertyWithID(property.id()); if (toReplace) { *toReplace = property; return; } } - append(property); + mutablePropertyVector().append(property); } bool StylePropertySet::setProperty(CSSPropertyID propertyID, int identifier, bool important) @@ -635,10 +664,10 @@ String StylePropertySet::asText() const { StringBuilder result; - const CSSProperty* positionXProp = 0; - const CSSProperty* positionYProp = 0; - const CSSProperty* repeatXProp = 0; - const CSSProperty* repeatYProp = 0; + int positionXPropertyIndex = -1; + int positionYPropertyIndex = -1; + int repeatXPropertyIndex = -1; + int repeatYPropertyIndex = -1; BitArray<numCSSProperties> shorthandPropertyUsed; BitArray<numCSSProperties> shorthandPropertyAppeared; @@ -646,8 +675,8 @@ String StylePropertySet::asText() const unsigned size = propertyCount(); unsigned numDecls = 0; for (unsigned n = 0; n < size; ++n) { - const CSSProperty& prop = propertyAt(n); - CSSPropertyID propertyID = prop.id(); + PropertyReference property = propertyAt(n); + CSSPropertyID propertyID = property.id(); CSSPropertyID shorthandPropertyID = CSSPropertyInvalid; CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid; String value; @@ -657,20 +686,20 @@ String StylePropertySet::asText() const case CSSPropertyVariable: if (numDecls++) result.append(' '); - result.append(prop.cssText()); + result.append(property.cssText()); continue; #endif case CSSPropertyBackgroundPositionX: - positionXProp = ∝ + positionXPropertyIndex = n; continue; case CSSPropertyBackgroundPositionY: - positionYProp = ∝ + positionYPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatX: - repeatXProp = ∝ + repeatXPropertyIndex = n; continue; case CSSPropertyBackgroundRepeatY: - repeatYProp = ∝ + repeatYPropertyIndex = n; continue; case CSSPropertyBorderTopWidth: case CSSPropertyBorderRightWidth: @@ -806,7 +835,7 @@ String StylePropertySet::asText() const propertyID = shorthandPropertyID; shorthandPropertyUsed.set(shortPropertyIndex); } else - value = prop.value()->cssText(); + value = property.value()->cssText(); if (value == "initial" && !CSSProperty::isInheritedProperty(propertyID)) continue; @@ -816,7 +845,7 @@ String StylePropertySet::asText() const result.append(getPropertyName(propertyID)); result.appendLiteral(": "); result.append(value); - if (prop.isImportant()) + if (property.isImportant()) result.appendLiteral(" !important"); result.append(';'); } @@ -825,58 +854,64 @@ String StylePropertySet::asText() const // It is required because background-position-x/y are non-standard properties and WebKit generated output // would not work in Firefox (<rdar://problem/5143183>) // It would be a better solution if background-position was CSS_PAIR. - if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) { + if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && propertyAt(positionXPropertyIndex).isImportant() == propertyAt(positionYPropertyIndex).isImportant()) { + PropertyReference positionXProperty = propertyAt(positionXPropertyIndex); + PropertyReference positionYProperty = propertyAt(positionYPropertyIndex); + if (numDecls++) result.append(' '); result.appendLiteral("background-position: "); - if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList()) + if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundPositionShorthand())); else { - result.append(positionXProp->value()->cssText()); + result.append(positionXProperty.value()->cssText()); result.append(' '); - result.append(positionYProp->value()->cssText()); + result.append(positionYProperty.value()->cssText()); } - if (positionXProp->isImportant()) + if (positionXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { - if (positionXProp) { + if (positionXPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(positionXProp->cssText()); + result.append(propertyAt(positionXPropertyIndex).cssText()); } - if (positionYProp) { + if (positionYPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(positionYProp->cssText()); + result.append(propertyAt(positionYPropertyIndex).cssText()); } } // FIXME: We need to do the same for background-repeat. - if (repeatXProp && repeatYProp && repeatXProp->isImportant() == repeatYProp->isImportant()) { + if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && propertyAt(repeatXPropertyIndex).isImportant() == propertyAt(repeatYPropertyIndex).isImportant()) { + PropertyReference repeatXProperty = propertyAt(repeatXPropertyIndex); + PropertyReference repeatYProperty = propertyAt(repeatYPropertyIndex); + if (numDecls++) result.append(' '); result.appendLiteral("background-repeat: "); - if (repeatXProp->value()->isValueList() || repeatYProp->value()->isValueList()) + if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList()) result.append(getLayeredShorthandValue(backgroundRepeatShorthand())); else { - result.append(repeatXProp->value()->cssText()); + result.append(repeatXProperty.value()->cssText()); result.append(' '); - result.append(repeatYProp->value()->cssText()); + result.append(repeatYProperty.value()->cssText()); } - if (repeatXProp->isImportant()) + if (repeatXProperty.isImportant()) result.appendLiteral(" !important"); result.append(';'); } else { - if (repeatXProp) { + if (repeatXPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(repeatXProp->cssText()); + result.append(propertyAt(repeatXPropertyIndex).cssText()); } - if (repeatYProp) { + if (repeatYPropertyIndex != -1) { if (numDecls++) result.append(' '); - result.append(repeatYProp->cssText()); + result.append(propertyAt(repeatYPropertyIndex).cssText()); } } @@ -889,12 +924,12 @@ void StylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) ASSERT(isMutable()); unsigned size = other->propertyCount(); for (unsigned n = 0; n < size; ++n) { - const CSSProperty& toMerge = other->propertyAt(n); - CSSProperty* old = findPropertyWithId(toMerge.id()); + PropertyReference toMerge = other->propertyAt(n); + CSSProperty* old = findMutableCSSPropertyWithID(toMerge.id()); if (old) - setProperty(toMerge, old); + setProperty(toMerge.toCSSProperty(), old); else - append(toMerge); + mutablePropertyVector().append(toMerge.toCSSProperty()); } } @@ -943,6 +978,12 @@ static const CSSPropertyID blockProperties[] = { CSSPropertyWidows }; +void StylePropertySet::clear() +{ + ASSERT(isMutable()); + mutablePropertyVector().clear(); +} + const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties); PassRefPtr<StylePropertySet> StylePropertySet::copyBlockProperties() const @@ -985,29 +1026,30 @@ bool StylePropertySet::removePropertiesInSet(const CSSPropertyID* set, unsigned return changed; } -const CSSProperty* StylePropertySet::findPropertyWithId(CSSPropertyID propertyID) const +int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const { for (int n = propertyCount() - 1 ; n >= 0; --n) { if (propertyID == propertyAt(n).id()) - return &propertyAt(n); + return n; } - return 0; + return -1; } -CSSProperty* StylePropertySet::findPropertyWithId(CSSPropertyID propertyID) +CSSProperty* StylePropertySet::findMutableCSSPropertyWithID(CSSPropertyID propertyID) { ASSERT(isMutable()); - for (int n = propertyCount() - 1 ; n >= 0; --n) { - if (propertyID == propertyAt(n).id()) - return &propertyAt(n); - } - return 0; + int foundPropertyIndex = findPropertyIndex(propertyID); + if (foundPropertyIndex == -1) + return 0; + return &mutablePropertyVector().at(foundPropertyIndex); } -bool StylePropertySet::propertyMatches(const CSSProperty* property) const +bool StylePropertySet::propertyMatches(const PropertyReference& property) const { - RefPtr<CSSValue> value = getPropertyCSSValue(property->id()); - return value && value->cssText() == property->value()->cssText(); + int foundPropertyIndex = findPropertyIndex(property.id()); + if (foundPropertyIndex == -1) + return false; + return propertyAt(foundPropertyIndex).value()->cssText() == property.value()->cssText(); } void StylePropertySet::removeEquivalentProperties(const StylePropertySet* style) @@ -1016,8 +1058,8 @@ void StylePropertySet::removeEquivalentProperties(const StylePropertySet* style) Vector<CSSPropertyID> propertiesToRemove; unsigned size = mutablePropertyVector().size(); for (unsigned i = 0; i < size; ++i) { - const CSSProperty& property = mutablePropertyVector().at(i); - if (style->propertyMatches(&property)) + PropertyReference property = propertyAt(i); + if (style->propertyMatches(property)) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. @@ -1031,8 +1073,8 @@ void StylePropertySet::removeEquivalentProperties(const CSSStyleDeclaration* sty Vector<CSSPropertyID> propertiesToRemove; unsigned size = mutablePropertyVector().size(); for (unsigned i = 0; i < size; ++i) { - const CSSProperty& property = mutablePropertyVector().at(i); - if (style->cssPropertyMatches(&property)) + PropertyReference property = propertyAt(i); + if (style->cssPropertyMatches(property)) propertiesToRemove.append(property.id()); } // FIXME: This should use mass removal. @@ -1097,19 +1139,19 @@ void StylePropertySet::clearParentElement(StyledElement* element) unsigned StylePropertySet::averageSizeInBytes() { // Please update this if the storage scheme changes so that this longer reflects the actual size. - return sizeof(StylePropertySet) + sizeof(CSSProperty) * 2; + return sizeForImmutableStylePropertySetWithPropertyCount(2); } void StylePropertySet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const { - size_t actualSize = m_isMutable ? sizeof(StylePropertySet) : immutableStylePropertySetSize(m_arraySize); + size_t actualSize = m_isMutable ? sizeof(StylePropertySet) : sizeForImmutableStylePropertySetWithPropertyCount(m_arraySize); MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS, actualSize); if (m_isMutable) info.addMember(mutablePropertyVector()); - - unsigned count = propertyCount(); - for (unsigned i = 0; i < count; ++i) - info.addMember(propertyAt(i)); + else { + for (unsigned i = 0; i < propertyCount(); ++i) + info.addMember(propertyAt(i).value()); + } } // See the function above if you need to update this. @@ -1125,12 +1167,6 @@ void StylePropertySet::showStyle() } #endif -inline void StylePropertySet::append(const CSSProperty& property) -{ - ASSERT(isMutable()); - mutablePropertyVector().append(property); -} - PassRefPtr<StylePropertySet> StylePropertySet::create(CSSParserMode cssParserMode) { return adoptRef(new MutableStylePropertySet(cssParserMode)); @@ -1141,4 +1177,28 @@ PassRefPtr<StylePropertySet> StylePropertySet::create(const CSSProperty* propert return adoptRef(new MutableStylePropertySet(properties, count)); } +String StylePropertySet::PropertyReference::cssName() const +{ +#if ENABLE(CSS_VARIABLES) + if (id() == CSSPropertyVariable) { + ASSERT(propertyValue()->isVariableValue()); + return "-webkit-var-" + static_cast<const CSSVariableValue*>(propertyValue())->name(); + } +#endif + return getPropertyNameString(id()); +} + +String StylePropertySet::PropertyReference::cssText() const +{ + StringBuilder result; + result.append(cssName()); + result.appendLiteral(": "); + result.append(propertyValue()->cssText()); + if (isImportant()) + result.appendLiteral(" !important"); + result.append(';'); + return result.toString(); +} + + } // namespace WebCore |