CSSMutableStyleDeclaration.cpp [plain text]
#include "config.h"
#include "CSSMutableStyleDeclaration.h"
#include "CSSImageValue.h"
#include "CSSMutableValue.h"
#include "CSSParser.h"
#include "CSSPropertyLonghand.h"
#include "CSSPropertyNames.h"
#include "CSSRule.h"
#include "CSSStyleSheet.h"
#include "CSSValueKeywords.h"
#include "CSSValueList.h"
#include "Document.h"
#include "ExceptionCode.h"
#include "InspectorInstrumentation.h"
#include "StyledElement.h"
#include <wtf/text/WTFString.h>
using namespace std;
namespace WebCore {
CSSMutableStyleDeclaration::CSSMutableStyleDeclaration()
: m_node(0)
, m_strictParsing(false)
#ifndef NDEBUG
, m_iteratorCount(0)
#endif
{
}
CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent)
: CSSStyleDeclaration(parent)
, m_node(0)
, m_strictParsing(!parent || parent->useStrictParsing())
#ifndef NDEBUG
, m_iteratorCount(0)
#endif
{
}
CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const Vector<CSSProperty>& properties)
: CSSStyleDeclaration(parent)
, m_properties(properties)
, m_node(0)
, m_strictParsing(!parent || parent->useStrictParsing())
#ifndef NDEBUG
, m_iteratorCount(0)
#endif
{
m_properties.shrinkToFit();
}
CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CSSProperty* const * properties, int numProperties)
: CSSStyleDeclaration(parent)
, m_node(0)
, m_strictParsing(!parent || parent->useStrictParsing())
#ifndef NDEBUG
, m_iteratorCount(0)
#endif
{
m_properties.reserveInitialCapacity(numProperties);
HashMap<int, bool> candidates;
for (int i = 0; i < numProperties; ++i) {
const CSSProperty *property = properties[i];
ASSERT(property);
bool important = property->isImportant();
if (candidates.contains(property->id())) {
if (!important && candidates.get(property->id()))
continue;
removeProperty(property->id(), false);
}
m_properties.append(*property);
candidates.set(property->id(), important);
}
}
CSSMutableStyleDeclaration::~CSSMutableStyleDeclaration()
{
const CSSMutableStyleDeclarationConstIterator end = this->end();
for (CSSMutableStyleDeclarationConstIterator it = begin(); it != end; ++it) {
CSSValue* value = it->value();
if (!value || !value->isMutableValue())
continue;
static_cast<CSSMutableValue*>(value)->setNode(0);
}
}
CSSMutableStyleDeclaration& CSSMutableStyleDeclaration::operator=(const CSSMutableStyleDeclaration& other)
{
ASSERT(!m_iteratorCount);
m_properties = other.m_properties;
m_strictParsing = other.m_strictParsing;
return *this;
}
String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const
{
RefPtr<CSSValue> value = getPropertyCSSValue(propertyID);
if (value)
return value->cssText();
switch (propertyID) {
case CSSPropertyBorderSpacing: {
const int properties[2] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing };
return borderSpacingValue(properties);
}
case CSSPropertyBackgroundPosition: {
const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
return getLayeredShorthandValue(properties);
}
case CSSPropertyBackgroundRepeat: {
const int properties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY };
return getLayeredShorthandValue(properties);
}
case CSSPropertyBackground: {
const int properties[9] = { CSSPropertyBackgroundColor,
CSSPropertyBackgroundImage,
CSSPropertyBackgroundRepeatX,
CSSPropertyBackgroundRepeatY,
CSSPropertyBackgroundAttachment,
CSSPropertyBackgroundPositionX,
CSSPropertyBackgroundPositionY,
CSSPropertyBackgroundClip,
CSSPropertyBackgroundOrigin };
return getLayeredShorthandValue(properties);
}
case CSSPropertyBorder: {
const int properties[3][4] = {{ CSSPropertyBorderTopWidth,
CSSPropertyBorderRightWidth,
CSSPropertyBorderBottomWidth,
CSSPropertyBorderLeftWidth },
{ CSSPropertyBorderTopStyle,
CSSPropertyBorderRightStyle,
CSSPropertyBorderBottomStyle,
CSSPropertyBorderLeftStyle },
{ CSSPropertyBorderTopColor,
CSSPropertyBorderRightColor,
CSSPropertyBorderBottomColor,
CSSPropertyBorderLeftColor }};
String res;
for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) {
String value = getCommonValue(properties[i]);
if (!value.isNull()) {
if (!res.isNull())
res += " ";
res += value;
}
}
return res;
}
case CSSPropertyBorderTop: {
const int properties[3] = { CSSPropertyBorderTopWidth, CSSPropertyBorderTopStyle,
CSSPropertyBorderTopColor};
return getShorthandValue(properties);
}
case CSSPropertyBorderRight: {
const int properties[3] = { CSSPropertyBorderRightWidth, CSSPropertyBorderRightStyle,
CSSPropertyBorderRightColor};
return getShorthandValue(properties);
}
case CSSPropertyBorderBottom: {
const int properties[3] = { CSSPropertyBorderBottomWidth, CSSPropertyBorderBottomStyle,
CSSPropertyBorderBottomColor};
return getShorthandValue(properties);
}
case CSSPropertyBorderLeft: {
const int properties[3] = { CSSPropertyBorderLeftWidth, CSSPropertyBorderLeftStyle,
CSSPropertyBorderLeftColor};
return getShorthandValue(properties);
}
case CSSPropertyOutline: {
const int properties[3] = { CSSPropertyOutlineWidth, CSSPropertyOutlineStyle,
CSSPropertyOutlineColor };
return getShorthandValue(properties);
}
case CSSPropertyBorderColor: {
const int properties[4] = { CSSPropertyBorderTopColor, CSSPropertyBorderRightColor,
CSSPropertyBorderBottomColor, CSSPropertyBorderLeftColor };
return get4Values(properties);
}
case CSSPropertyBorderWidth: {
const int properties[4] = { CSSPropertyBorderTopWidth, CSSPropertyBorderRightWidth,
CSSPropertyBorderBottomWidth, CSSPropertyBorderLeftWidth };
return get4Values(properties);
}
case CSSPropertyBorderStyle: {
const int properties[4] = { CSSPropertyBorderTopStyle, CSSPropertyBorderRightStyle,
CSSPropertyBorderBottomStyle, CSSPropertyBorderLeftStyle };
return get4Values(properties);
}
case CSSPropertyMargin: {
const int properties[4] = { CSSPropertyMarginTop, CSSPropertyMarginRight,
CSSPropertyMarginBottom, CSSPropertyMarginLeft };
return get4Values(properties);
}
case CSSPropertyOverflow: {
const int properties[2] = { CSSPropertyOverflowX, CSSPropertyOverflowY };
return getCommonValue(properties);
}
case CSSPropertyPadding: {
const int properties[4] = { CSSPropertyPaddingTop, CSSPropertyPaddingRight,
CSSPropertyPaddingBottom, CSSPropertyPaddingLeft };
return get4Values(properties);
}
case CSSPropertyListStyle: {
const int properties[3] = { CSSPropertyListStyleType, CSSPropertyListStylePosition,
CSSPropertyListStyleImage };
return getShorthandValue(properties);
}
case CSSPropertyWebkitMaskPosition: {
const int properties[2] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY };
return getLayeredShorthandValue(properties);
}
case CSSPropertyWebkitMaskRepeat: {
const int properties[2] = { CSSPropertyWebkitMaskRepeatX, CSSPropertyWebkitMaskRepeatY };
return getLayeredShorthandValue(properties);
}
case CSSPropertyWebkitMask: {
const int properties[] = { CSSPropertyWebkitMaskImage, CSSPropertyWebkitMaskRepeat,
CSSPropertyWebkitMaskAttachment, CSSPropertyWebkitMaskPosition, CSSPropertyWebkitMaskClip,
CSSPropertyWebkitMaskOrigin };
return getLayeredShorthandValue(properties);
}
case CSSPropertyWebkitTransformOrigin: {
const int properties[3] = { CSSPropertyWebkitTransformOriginX,
CSSPropertyWebkitTransformOriginY,
CSSPropertyWebkitTransformOriginZ };
return getShorthandValue(properties);
}
case CSSPropertyWebkitTransition: {
const int properties[4] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration,
CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionDelay };
return getLayeredShorthandValue(properties);
}
case CSSPropertyWebkitAnimation: {
const int properties[7] = { CSSPropertyWebkitAnimationName, CSSPropertyWebkitAnimationDuration,
CSSPropertyWebkitAnimationTimingFunction, CSSPropertyWebkitAnimationDelay,
CSSPropertyWebkitAnimationIterationCount, CSSPropertyWebkitAnimationDirection,
CSSPropertyWebkitAnimationFillMode };
return getLayeredShorthandValue(properties);
}
#if ENABLE(SVG)
case CSSPropertyMarker: {
RefPtr<CSSValue> value = getPropertyCSSValue(CSSPropertyMarkerStart);
if (value)
return value->cssText();
}
#endif
}
return String();
}
String CSSMutableStyleDeclaration::borderSpacingValue(const int properties[2]) const
{
RefPtr<CSSValue> horizontalValue = getPropertyCSSValue(properties[0]);
RefPtr<CSSValue> verticalValue = getPropertyCSSValue(properties[1]);
if (!horizontalValue)
return String();
ASSERT(verticalValue);
String horizontalValueCSSText = horizontalValue->cssText();
String verticalValueCSSText = verticalValue->cssText();
if (horizontalValueCSSText == verticalValueCSSText)
return horizontalValueCSSText;
return horizontalValueCSSText + ' ' + verticalValueCSSText;
}
String CSSMutableStyleDeclaration::get4Values(const int* properties) const
{
RefPtr<CSSValue> topValue = getPropertyCSSValue(properties[0]);
RefPtr<CSSValue> rightValue = getPropertyCSSValue(properties[1]);
RefPtr<CSSValue> bottomValue = getPropertyCSSValue(properties[2]);
RefPtr<CSSValue> leftValue = getPropertyCSSValue(properties[3]);
if (!topValue || !rightValue || !bottomValue || !leftValue)
return String();
bool showLeft = rightValue->cssText() != leftValue->cssText();
bool showBottom = (topValue->cssText() != bottomValue->cssText()) || showLeft;
bool showRight = (topValue->cssText() != rightValue->cssText()) || showBottom;
String res = topValue->cssText();
if (showRight)
res += " " + rightValue->cssText();
if (showBottom)
res += " " + bottomValue->cssText();
if (showLeft)
res += " " + leftValue->cssText();
return res;
}
String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, size_t size) const
{
String res;
Vector< RefPtr<CSSValue> > values(size);
size_t numLayers = 0;
for (size_t i = 0; i < size; ++i) {
values[i] = getPropertyCSSValue(properties[i]);
if (values[i]) {
if (values[i]->isValueList()) {
CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get());
numLayers = max(valueList->length(), numLayers);
} else
numLayers = max<size_t>(1U, numLayers);
}
}
for (size_t i = 0; i < numLayers; i++) {
String layerRes;
bool useRepeatXShorthand = false;
bool useRepeatYShorthand = false;
bool useSingleWordShorthand = false;
for (size_t j = 0; j < size; j++) {
RefPtr<CSSValue> value;
if (values[j]) {
if (values[j]->isValueList())
value = static_cast<CSSValueList*>(values[j].get())->item(i);
else {
value = values[j];
if (properties[j] == CSSPropertyBackgroundColor) {
if (i != numLayers - 1)
value = 0;
} else if (i != 0) value = 0;
}
}
if (properties[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(properties[j])) {
if (j < size - 1 && properties[j + 1] == CSSPropertyBackgroundRepeatY && value) {
RefPtr<CSSValue> yValue;
RefPtr<CSSValue> nextValue = values[j + 1];
if (nextValue->isValueList())
yValue = static_cast<CSSValueList*>(nextValue.get())->itemWithoutBoundsCheck(i);
else
yValue = nextValue;
int xId = static_cast<CSSPrimitiveValue*>(value.get())->getIdent();
int yId = static_cast<CSSPrimitiveValue*>(yValue.get())->getIdent();
if (xId != yId) {
if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) {
useRepeatXShorthand = true;
++j;
} else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) {
useRepeatYShorthand = true;
continue;
}
} else {
useSingleWordShorthand = true;
++j;
}
}
}
if (value && !value->isImplicitInitialValue()) {
if (!layerRes.isNull())
layerRes += " ";
if (useRepeatXShorthand) {
useRepeatXShorthand = false;
layerRes += getValueName(CSSValueRepeatX);
} else if (useRepeatYShorthand) {
useRepeatYShorthand = false;
layerRes += getValueName(CSSValueRepeatY);
} else if (useSingleWordShorthand) {
useSingleWordShorthand = false;
layerRes += value->cssText();
} else
layerRes += value->cssText();
}
}
if (!layerRes.isNull()) {
if (!res.isNull())
res += ", ";
res += layerRes;
}
}
return res;
}
String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, size_t size) const
{
String res;
for (size_t i = 0; i < size; ++i) {
if (!isPropertyImplicit(properties[i])) {
RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
if (value) {
if (!res.isNull())
res += " ";
res += value->cssText();
}
}
}
return res;
}
String CSSMutableStyleDeclaration::getCommonValue(const int* properties, size_t size) const
{
String res;
for (size_t i = 0; i < size; ++i) {
RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
if (!value)
return String();
String text = value->cssText();
if (text.isNull())
return String();
if (res.isNull())
res = text;
else if (res != text)
return String();
}
return res;
}
PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propertyID) const
{
const CSSProperty* property = findPropertyWithId(propertyID);
return property ? property->value() : 0;
}
bool CSSMutableStyleDeclaration::removeShorthandProperty(int propertyID, bool notifyChanged)
{
CSSPropertyLonghand longhand = longhandForProperty(propertyID);
if (longhand.length()) {
removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged);
return true;
}
return false;
}
String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText)
{
ASSERT(!m_iteratorCount);
if (removeShorthandProperty(propertyID, notifyChanged)) {
return String();
}
CSSProperty* foundProperty = findPropertyWithId(propertyID);
if (!foundProperty)
return String();
String value = returnText ? foundProperty->value()->cssText() : String();
m_properties.remove(foundProperty - m_properties.data());
if (notifyChanged)
setNeedsStyleRecalc();
return value;
}
bool CSSMutableStyleDeclaration::isInlineStyleDeclaration()
{
return m_node && m_node->isStyledElement() && static_cast<StyledElement*>(m_node)->inlineStyleDecl() == this;
}
void CSSMutableStyleDeclaration::setNeedsStyleRecalc()
{
if (m_node) {
if (isInlineStyleDeclaration()) {
m_node->setNeedsStyleRecalc(InlineStyleChange);
static_cast<StyledElement*>(m_node)->invalidateStyleAttribute();
if (m_node->document())
InspectorInstrumentation::didInvalidateStyleAttr(m_node->document(), m_node);
} else
m_node->setNeedsStyleRecalc(FullStyleChange);
return;
}
StyleBase* root = this;
while (StyleBase* parent = root->parent())
root = parent;
if (root->isCSSStyleSheet()) {
if (Document* document = static_cast<CSSStyleSheet*>(root)->document())
document->styleSelectorChanged(DeferRecalcStyle);
}
}
bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const
{
const CSSProperty* property = findPropertyWithId(propertyID);
return property ? property->isImportant() : false;
}
int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const
{
const CSSProperty* property = findPropertyWithId(propertyID);
return property ? property->shorthandID() : 0;
}
bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const
{
const CSSProperty* property = findPropertyWithId(propertyID);
return property ? property->isImplicit() : false;
}
void CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, ExceptionCode& ec)
{
ec = 0;
setProperty(propertyID, value, important, true);
}
String CSSMutableStyleDeclaration::removeProperty(int propertyID, ExceptionCode& ec)
{
ec = 0;
return removeProperty(propertyID, true, true);
}
bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, bool notifyChanged)
{
ASSERT(!m_iteratorCount);
if (value.isEmpty()) {
removeProperty(propertyID, notifyChanged, false);
return true;
}
bool success = CSSParser::parseValue(this, propertyID, value, important, useStrictParsing());
if (!success) {
} else if (notifyChanged)
setNeedsStyleRecalc();
return success;
}
void CSSMutableStyleDeclaration::setPropertyInternal(const CSSProperty& property, CSSProperty* slot)
{
ASSERT(!m_iteratorCount);
if (!removeShorthandProperty(property.id(), false)) {
CSSProperty* toReplace = slot ? slot : findPropertyWithId(property.id());
if (toReplace) {
*toReplace = property;
return;
}
}
m_properties.append(property);
}
bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged)
{
CSSProperty property(propertyID, CSSPrimitiveValue::createIdentifier(value), important);
setPropertyInternal(property);
if (notifyChanged)
setNeedsStyleRecalc();
return true;
}
bool CSSMutableStyleDeclaration::setProperty(int propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important, bool notifyChanged)
{
CSSProperty property(propertyID, CSSPrimitiveValue::create(value, unit), important);
setPropertyInternal(property);
if (notifyChanged)
setNeedsStyleRecalc();
return true;
}
void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important)
{
ASSERT(!m_iteratorCount);
setPropertyInternal(CSSProperty(propertyId, CSSPrimitiveValue::create(value, type), important));
setNeedsStyleRecalc();
}
void CSSMutableStyleDeclaration::setImageProperty(int propertyId, const String& url, bool important)
{
ASSERT(!m_iteratorCount);
setPropertyInternal(CSSProperty(propertyId, CSSImageValue::create(url), important));
setNeedsStyleRecalc();
}
void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration)
{
ASSERT(!m_iteratorCount);
m_properties.clear();
CSSParser parser(useStrictParsing());
parser.parseDeclaration(this, styleDeclaration);
setNeedsStyleRecalc();
}
void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty* const* properties, int numProperties)
{
ASSERT(!m_iteratorCount);
m_properties.reserveCapacity(numProperties);
for (int i = 0; i < numProperties; ++i)
addParsedProperty(*properties[i]);
}
void CSSMutableStyleDeclaration::addParsedProperty(const CSSProperty& property)
{
ASSERT(!m_iteratorCount);
if (!getPropertyPriority(property.id()) || property.isImportant()) {
removeProperty(property.id(), false);
m_properties.append(property);
}
}
void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool )
{
ASSERT(!m_iteratorCount);
bool parseMode = useStrictParsing();
setStrictParsing(false);
setProperty(propertyId, value, important);
setStrictParsing(parseMode);
}
unsigned CSSMutableStyleDeclaration::virtualLength() const
{
return length();
}
String CSSMutableStyleDeclaration::item(unsigned i) const
{
if (i >= m_properties.size())
return "";
return getPropertyName(static_cast<CSSPropertyID>(m_properties[i].id()));
}
String CSSMutableStyleDeclaration::cssText() const
{
String result = "";
const CSSProperty* positionXProp = 0;
const CSSProperty* positionYProp = 0;
const CSSProperty* repeatXProp = 0;
const CSSProperty* repeatYProp = 0;
unsigned size = m_properties.size();
for (unsigned n = 0; n < size; ++n) {
const CSSProperty& prop = m_properties[n];
if (prop.id() == CSSPropertyBackgroundPositionX)
positionXProp = ∝
else if (prop.id() == CSSPropertyBackgroundPositionY)
positionYProp = ∝
else if (prop.id() == CSSPropertyBackgroundRepeatX)
repeatXProp = ∝
else if (prop.id() == CSSPropertyBackgroundRepeatY)
repeatYProp = ∝
else
result += prop.cssText();
}
if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) {
String positionValue;
const int properties[2] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList())
positionValue = getLayeredShorthandValue(properties);
else
positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText();
result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; ";
} else {
if (positionXProp)
result += positionXProp->cssText();
if (positionYProp)
result += positionYProp->cssText();
}
if (repeatXProp && repeatYProp && repeatXProp->isImportant() == repeatYProp->isImportant()) {
String repeatValue;
const int repeatProperties[2] = { CSSPropertyBackgroundRepeatX, CSSPropertyBackgroundRepeatY };
if (repeatXProp->value()->isValueList() || repeatYProp->value()->isValueList())
repeatValue = getLayeredShorthandValue(repeatProperties);
else
repeatValue = repeatXProp->value()->cssText() + " " + repeatYProp->value()->cssText();
result += "background-repeat: " + repeatValue + (repeatXProp->isImportant() ? " !important" : "") + "; ";
} else {
if (repeatXProp)
result += repeatXProp->cssText();
if (repeatYProp)
result += repeatYProp->cssText();
}
return result;
}
void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec)
{
ASSERT(!m_iteratorCount);
ec = 0;
m_properties.clear();
CSSParser parser(useStrictParsing());
parser.parseDeclaration(this, text);
setNeedsStyleRecalc();
}
void CSSMutableStyleDeclaration::merge(const CSSMutableStyleDeclaration* other, bool argOverridesOnConflict)
{
ASSERT(!m_iteratorCount);
unsigned size = other->m_properties.size();
for (unsigned n = 0; n < size; ++n) {
const CSSProperty& toMerge = other->m_properties[n];
CSSProperty* old = findPropertyWithId(toMerge.id());
if (old) {
if (!argOverridesOnConflict && old->value())
continue;
setPropertyInternal(toMerge, old);
} else
m_properties.append(toMerge);
}
}
void CSSMutableStyleDeclaration::addSubresourceStyleURLs(ListHashSet<KURL>& urls)
{
CSSStyleSheet* sheet = static_cast<CSSStyleSheet*>(stylesheet());
size_t size = m_properties.size();
for (size_t i = 0; i < size; ++i)
m_properties[i].value()->addSubresourceStyleURLs(urls, sheet);
}
static const int blockProperties[] = {
CSSPropertyOrphans,
CSSPropertyOverflow, CSSPropertyWebkitColumnCount,
CSSPropertyWebkitColumnGap,
CSSPropertyWebkitColumnRuleColor,
CSSPropertyWebkitColumnRuleStyle,
CSSPropertyWebkitColumnRuleWidth,
CSSPropertyWebkitColumnBreakBefore,
CSSPropertyWebkitColumnBreakAfter,
CSSPropertyWebkitColumnBreakInside,
CSSPropertyWebkitColumnWidth,
CSSPropertyPageBreakAfter,
CSSPropertyPageBreakBefore,
CSSPropertyPageBreakInside,
CSSPropertyTextAlign,
CSSPropertyTextIndent,
CSSPropertyWidows
};
const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties);
PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const
{
return copyPropertiesInSet(blockProperties, numBlockProperties);
}
void CSSMutableStyleDeclaration::removeBlockProperties()
{
removePropertiesInSet(blockProperties, numBlockProperties);
}
void CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged)
{
ASSERT(!m_iteratorCount);
if (m_properties.isEmpty())
return;
HashSet<int> toRemove;
for (unsigned i = 0; i < length; ++i)
toRemove.add(set[i]);
Vector<CSSProperty, 4> newProperties;
newProperties.reserveInitialCapacity(m_properties.size());
unsigned size = m_properties.size();
for (unsigned n = 0; n < size; ++n) {
const CSSProperty& property = m_properties[n];
if (!property.isImportant()) {
if (toRemove.contains(property.id()))
continue;
}
newProperties.append(property);
}
bool changed = newProperties.size() != m_properties.size();
m_properties = newProperties;
if (changed && notifyChanged)
setNeedsStyleRecalc();
}
PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable()
{
return this;
}
PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const
{
return adoptRef(new CSSMutableStyleDeclaration(0, m_properties));
}
const CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID) const
{
for (int n = m_properties.size() - 1 ; n >= 0; --n) {
if (propertyID == m_properties[n].m_id)
return &m_properties[n];
}
return 0;
}
CSSProperty* CSSMutableStyleDeclaration::findPropertyWithId(int propertyID)
{
for (int n = m_properties.size() - 1 ; n >= 0; --n) {
if (propertyID == m_properties[n].m_id)
return &m_properties[n];
}
return 0;
}
}