2 * This file is part of the DOM implementation for KDE.
4 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
5 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
24 #include "CSSMutableStyleDeclaration.h"
26 #include "CSSImageValue.h"
27 #include "CSSParser.h"
28 #include "CSSProperty.h"
29 #include "CSSPropertyNames.h"
30 #include "CSSStyleSheet.h"
31 #include "CSSValueList.h"
33 #include "ExceptionCode.h"
34 #include "StyledElement.h"
40 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration()
45 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent)
46 : CSSStyleDeclaration(parent)
51 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const DeprecatedValueList<CSSProperty>& values)
52 : CSSStyleDeclaration(parent)
56 // FIXME: This allows duplicate properties.
59 CSSMutableStyleDeclaration::CSSMutableStyleDeclaration(CSSRule* parent, const CSSProperty* const * properties, int numProperties)
60 : CSSStyleDeclaration(parent)
63 for (int i = 0; i < numProperties; ++i) {
64 ASSERT(properties[i]);
65 m_values.append(*properties[i]);
67 // FIXME: This allows duplicate properties.
70 CSSMutableStyleDeclaration& CSSMutableStyleDeclaration::operator=(const CSSMutableStyleDeclaration& other)
72 // don't attach it to the same node, just leave the current m_node value
73 m_values = other.m_values;
77 String CSSMutableStyleDeclaration::getPropertyValue(int propertyID) const
79 RefPtr<CSSValue> value = getPropertyCSSValue(propertyID);
81 return value->cssText();
83 // Shorthand and 4-values properties
85 case CSS_PROP_BACKGROUND_POSITION: {
86 // FIXME: Is this correct? The code in cssparser.cpp is confusing
87 const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X,
88 CSS_PROP_BACKGROUND_POSITION_Y };
89 return getLayeredShorthandValue(properties, 2);
91 case CSS_PROP_BACKGROUND: {
92 const int properties[6] = { CSS_PROP_BACKGROUND_IMAGE, CSS_PROP_BACKGROUND_REPEAT,
93 CSS_PROP_BACKGROUND_ATTACHMENT, CSS_PROP_BACKGROUND_POSITION_X,
94 CSS_PROP_BACKGROUND_POSITION_Y, CSS_PROP_BACKGROUND_COLOR };
95 return getLayeredShorthandValue(properties, 6);
97 case CSS_PROP_BORDER: {
98 const int properties[3] = { CSS_PROP_BORDER_WIDTH, CSS_PROP_BORDER_STYLE,
99 CSS_PROP_BORDER_COLOR };
100 return getShorthandValue(properties, 3);
102 case CSS_PROP_BORDER_TOP: {
103 const int properties[3] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_TOP_STYLE,
104 CSS_PROP_BORDER_TOP_COLOR};
105 return getShorthandValue(properties, 3);
107 case CSS_PROP_BORDER_RIGHT: {
108 const int properties[3] = { CSS_PROP_BORDER_RIGHT_WIDTH, CSS_PROP_BORDER_RIGHT_STYLE,
109 CSS_PROP_BORDER_RIGHT_COLOR};
110 return getShorthandValue(properties, 3);
112 case CSS_PROP_BORDER_BOTTOM: {
113 const int properties[3] = { CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_BOTTOM_STYLE,
114 CSS_PROP_BORDER_BOTTOM_COLOR};
115 return getShorthandValue(properties, 3);
117 case CSS_PROP_BORDER_LEFT: {
118 const int properties[3] = { CSS_PROP_BORDER_LEFT_WIDTH, CSS_PROP_BORDER_LEFT_STYLE,
119 CSS_PROP_BORDER_LEFT_COLOR};
120 return getShorthandValue(properties, 3);
122 case CSS_PROP_OUTLINE: {
123 const int properties[3] = { CSS_PROP_OUTLINE_WIDTH, CSS_PROP_OUTLINE_STYLE,
124 CSS_PROP_OUTLINE_COLOR };
125 return getShorthandValue(properties, 3);
127 case CSS_PROP_BORDER_COLOR: {
128 const int properties[4] = { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_RIGHT_COLOR,
129 CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_LEFT_COLOR };
130 return get4Values(properties);
132 case CSS_PROP_BORDER_WIDTH: {
133 const int properties[4] = { CSS_PROP_BORDER_TOP_WIDTH, CSS_PROP_BORDER_RIGHT_WIDTH,
134 CSS_PROP_BORDER_BOTTOM_WIDTH, CSS_PROP_BORDER_LEFT_WIDTH };
135 return get4Values(properties);
137 case CSS_PROP_BORDER_STYLE: {
138 const int properties[4] = { CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_RIGHT_STYLE,
139 CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_LEFT_STYLE };
140 return get4Values(properties);
142 case CSS_PROP_MARGIN: {
143 const int properties[4] = { CSS_PROP_MARGIN_TOP, CSS_PROP_MARGIN_RIGHT,
144 CSS_PROP_MARGIN_BOTTOM, CSS_PROP_MARGIN_LEFT };
145 return get4Values(properties);
147 case CSS_PROP_PADDING: {
148 const int properties[4] = { CSS_PROP_PADDING_TOP, CSS_PROP_PADDING_RIGHT,
149 CSS_PROP_PADDING_BOTTOM, CSS_PROP_PADDING_LEFT };
150 return get4Values(properties);
152 case CSS_PROP_LIST_STYLE: {
153 const int properties[3] = { CSS_PROP_LIST_STYLE_TYPE, CSS_PROP_LIST_STYLE_POSITION,
154 CSS_PROP_LIST_STYLE_IMAGE };
155 return getShorthandValue(properties, 3);
161 String CSSMutableStyleDeclaration::get4Values( const int* properties ) const
164 for (int i = 0; i < 4; ++i) {
165 if (!isPropertyImplicit(properties[i])) {
166 RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
168 // apparently all 4 properties must be specified.
174 res += value->cssText();
180 String CSSMutableStyleDeclaration::getLayeredShorthandValue(const int* properties, unsigned number) const
186 // Begin by collecting the properties into an array.
187 Vector< RefPtr<CSSValue> > values(number);
188 unsigned numLayers = 0;
190 for (i = 0; i < number; ++i) {
191 values[i] = getPropertyCSSValue(properties[i]);
193 if (values[i]->isValueList()) {
194 CSSValueList* valueList = static_cast<CSSValueList*>(values[i].get());
195 numLayers = max(valueList->length(), numLayers);
197 numLayers = max(1U, numLayers);
201 // Now stitch the properties together. Implicit initial values are flagged as such and
202 // can safely be omitted.
203 for (i = 0; i < numLayers; i++) {
205 for (j = 0; j < number; j++) {
206 RefPtr<CSSValue> value;
208 if (values[j]->isValueList())
209 value = static_cast<CSSValueList*>(values[j].get())->item(i);
213 // Color only belongs in the last layer.
214 if (properties[j] == CSS_PROP_BACKGROUND_COLOR) {
215 if (i != numLayers - 1)
217 } else if (i != 0) // Other singletons only belong in the first layer.
222 if (value && !value->isImplicitInitialValue()) {
223 if (!layerRes.isNull())
225 layerRes += value->cssText();
229 if (!layerRes.isNull()) {
239 String CSSMutableStyleDeclaration::getShorthandValue(const int* properties, int number) const
242 for (int i = 0; i < number; ++i) {
243 if (!isPropertyImplicit(properties[i])) {
244 RefPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
245 // FIXME: provide default value if !value
249 res += value->cssText();
256 PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propertyID) const
258 DeprecatedValueListConstIterator<CSSProperty> end;
259 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.fromLast(); it != end; --it) {
260 if (propertyID == (*it).m_id)
261 return (*it).value();
266 struct PropertyLonghand {
273 PropertyLonghand(const int* firstProperty, unsigned numProperties)
274 : m_properties(firstProperty)
275 , m_length(numProperties)
279 const int* properties() const { return m_properties; }
280 unsigned length() const { return m_length; }
283 const int* m_properties;
287 static void initShorthandMap(HashMap<int, PropertyLonghand>& shorthandMap)
289 #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \
290 map.set(propID, PropertyLonghand(array, sizeof(array) / sizeof(array[0])))
292 // FIXME: The 'font' property has "shorthand nature" but is not parsed as a shorthand.
294 // Do not change the order of the following four shorthands, and keep them together.
295 static const int borderProperties[4][3] = {
296 { CSS_PROP_BORDER_TOP_COLOR, CSS_PROP_BORDER_TOP_STYLE, CSS_PROP_BORDER_TOP_WIDTH },
297 { CSS_PROP_BORDER_RIGHT_COLOR, CSS_PROP_BORDER_RIGHT_STYLE, CSS_PROP_BORDER_RIGHT_WIDTH },
298 { CSS_PROP_BORDER_BOTTOM_COLOR, CSS_PROP_BORDER_BOTTOM_STYLE, CSS_PROP_BORDER_BOTTOM_WIDTH },
299 { CSS_PROP_BORDER_LEFT_COLOR, CSS_PROP_BORDER_LEFT_STYLE, CSS_PROP_BORDER_LEFT_WIDTH }
301 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_TOP, borderProperties[0]);
302 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_RIGHT, borderProperties[1]);
303 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_BOTTOM, borderProperties[2]);
304 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_LEFT, borderProperties[3]);
306 shorthandMap.set(CSS_PROP_BORDER, PropertyLonghand(borderProperties[0], sizeof(borderProperties) / sizeof(borderProperties[0][0])));
308 static const int borderColorProperties[] = {
309 CSS_PROP_BORDER_TOP_COLOR,
310 CSS_PROP_BORDER_RIGHT_COLOR,
311 CSS_PROP_BORDER_BOTTOM_COLOR,
312 CSS_PROP_BORDER_LEFT_COLOR
314 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_COLOR, borderColorProperties);
316 static const int borderStyleProperties[] = {
317 CSS_PROP_BORDER_TOP_STYLE,
318 CSS_PROP_BORDER_RIGHT_STYLE,
319 CSS_PROP_BORDER_BOTTOM_STYLE,
320 CSS_PROP_BORDER_LEFT_STYLE
322 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_STYLE, borderStyleProperties);
324 static const int borderWidthProperties[] = {
325 CSS_PROP_BORDER_TOP_WIDTH,
326 CSS_PROP_BORDER_RIGHT_WIDTH,
327 CSS_PROP_BORDER_BOTTOM_WIDTH,
328 CSS_PROP_BORDER_LEFT_WIDTH
330 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_WIDTH, borderWidthProperties);
332 static const int backgroundPositionProperties[] = { CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y };
333 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BACKGROUND_POSITION, backgroundPositionProperties);
335 static const int borderSpacingProperties[] = { CSS_PROP__WEBKIT_BORDER_HORIZONTAL_SPACING, CSS_PROP__WEBKIT_BORDER_VERTICAL_SPACING };
336 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BORDER_SPACING, borderSpacingProperties);
338 static const int listStyleProperties[] = {
339 CSS_PROP_LIST_STYLE_IMAGE,
340 CSS_PROP_LIST_STYLE_POSITION,
341 CSS_PROP_LIST_STYLE_TYPE
343 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_LIST_STYLE, listStyleProperties);
345 static const int marginProperties[] = {
347 CSS_PROP_MARGIN_RIGHT,
348 CSS_PROP_MARGIN_BOTTOM,
351 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_MARGIN, marginProperties);
353 static const int marginCollapseProperties[] = { CSS_PROP__WEBKIT_MARGIN_TOP_COLLAPSE, CSS_PROP__WEBKIT_MARGIN_BOTTOM_COLLAPSE };
354 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_MARGIN_COLLAPSE, marginCollapseProperties);
356 static const int marqueeProperties[] = {
357 CSS_PROP__WEBKIT_MARQUEE_DIRECTION,
358 CSS_PROP__WEBKIT_MARQUEE_INCREMENT,
359 CSS_PROP__WEBKIT_MARQUEE_REPETITION,
360 CSS_PROP__WEBKIT_MARQUEE_STYLE,
361 CSS_PROP__WEBKIT_MARQUEE_SPEED
363 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_MARQUEE, marqueeProperties);
365 static const int outlineProperties[] = {
366 CSS_PROP_OUTLINE_COLOR,
367 CSS_PROP_OUTLINE_OFFSET,
368 CSS_PROP_OUTLINE_STYLE,
369 CSS_PROP_OUTLINE_WIDTH
371 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_OUTLINE, outlineProperties);
373 static const int paddingProperties[] = {
374 CSS_PROP_PADDING_TOP,
375 CSS_PROP_PADDING_RIGHT,
376 CSS_PROP_PADDING_BOTTOM,
377 CSS_PROP_PADDING_LEFT
379 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_PADDING, paddingProperties);
381 static const int textStrokeProperties[] = { CSS_PROP__WEBKIT_TEXT_STROKE_COLOR, CSS_PROP__WEBKIT_TEXT_STROKE_WIDTH };
382 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_TEXT_STROKE, textStrokeProperties);
384 static const int backgroundProperties[] = {
385 CSS_PROP_BACKGROUND_ATTACHMENT,
386 CSS_PROP_BACKGROUND_COLOR,
387 CSS_PROP_BACKGROUND_IMAGE,
388 CSS_PROP_BACKGROUND_POSITION_X,
389 CSS_PROP_BACKGROUND_POSITION_Y,
390 CSS_PROP_BACKGROUND_REPEAT,
391 CSS_PROP__WEBKIT_BACKGROUND_SIZE
393 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_BACKGROUND, backgroundProperties);
395 static const int columnsProperties[] = { CSS_PROP__WEBKIT_COLUMN_WIDTH, CSS_PROP__WEBKIT_COLUMN_COUNT };
396 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_COLUMNS, columnsProperties);
398 static const int columnRuleProperties[] = {
399 CSS_PROP__WEBKIT_COLUMN_RULE_COLOR,
400 CSS_PROP__WEBKIT_COLUMN_RULE_STYLE,
401 CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH
403 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_COLUMN_RULE, columnRuleProperties);
405 static const int overflowProperties[] = { CSS_PROP_OVERFLOW_X, CSS_PROP_OVERFLOW_Y };
406 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP_OVERFLOW, overflowProperties);
408 static const int borderRadiusProperties[] = {
409 CSS_PROP__WEBKIT_BORDER_TOP_RIGHT_RADIUS,
410 CSS_PROP__WEBKIT_BORDER_TOP_LEFT_RADIUS,
411 CSS_PROP__WEBKIT_BORDER_BOTTOM_LEFT_RADIUS,
412 CSS_PROP__WEBKIT_BORDER_BOTTOM_RIGHT_RADIUS
414 SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSS_PROP__WEBKIT_BORDER_RADIUS, borderRadiusProperties);
416 #undef SET_SHORTHAND_MAP_ENTRY
419 String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText, ExceptionCode& ec)
423 static HashMap<int, PropertyLonghand> shorthandMap;
424 if (shorthandMap.isEmpty())
425 initShorthandMap(shorthandMap);
427 PropertyLonghand longhand = shorthandMap.get(propertyID);
428 if (longhand.length()) {
429 removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged);
430 // FIXME: Return an equivalent shorthand when possible.
436 DeprecatedValueListIterator<CSSProperty> end;
437 for (DeprecatedValueListIterator<CSSProperty> it = m_values.fromLast(); it != end; --it) {
438 if (propertyID == (*it).m_id) {
440 value = (*it).value()->cssText();
451 void CSSMutableStyleDeclaration::clear()
457 void CSSMutableStyleDeclaration::setChanged(StyleChangeType changeType)
460 m_node->setChanged(changeType);
461 // FIXME: Ideally, this should be factored better and there
462 // should be a subclass of CSSMutableStyleDeclaration just
463 // for inline style declarations that handles this
464 if (m_node->isStyledElement() && this == static_cast<StyledElement*>(m_node)->inlineStyleDecl())
465 static_cast<StyledElement*>(m_node)->invalidateStyleAttribute();
469 // FIXME: quick&dirty hack for KDE 3.0... make this MUCH better! (Dirk)
470 StyleBase* root = this;
471 while (StyleBase* parent = root->parent())
473 if (root->isCSSStyleSheet())
474 static_cast<CSSStyleSheet*>(root)->doc()->updateStyleSelector();
477 bool CSSMutableStyleDeclaration::getPropertyPriority(int propertyID) const
479 DeprecatedValueListConstIterator<CSSProperty> end;
480 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) {
481 if (propertyID == (*it).id())
482 return (*it).isImportant();
487 int CSSMutableStyleDeclaration::getPropertyShorthand(int propertyID) const
489 DeprecatedValueListConstIterator<CSSProperty> end;
490 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) {
491 if (propertyID == (*it).id())
492 return (*it).shorthandID();
497 bool CSSMutableStyleDeclaration::isPropertyImplicit(int propertyID) const
499 DeprecatedValueListConstIterator<CSSProperty> end;
500 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) {
501 if (propertyID == (*it).id())
502 return (*it).isImplicit();
507 void CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, ExceptionCode& ec)
509 setProperty(propertyID, value, important, true, ec);
512 String CSSMutableStyleDeclaration::removeProperty(int propertyID, ExceptionCode& ec)
514 return removeProperty(propertyID, true, true, ec);
517 bool CSSMutableStyleDeclaration::setProperty(int propertyID, const String& value, bool important, bool notifyChanged, ExceptionCode& ec)
521 // Setting the value to an empty string just removes the property in both IE and Gecko.
522 // Setting it to null seems to produce less consistent results, but we treat it just the same.
523 if (value.isEmpty()) {
524 removeProperty(propertyID, notifyChanged, false, ec);
528 // When replacing an existing property value, this moves the property to the end of the list.
529 // Firefox preserves the position, and MSIE moves the property to the beginning.
530 CSSParser parser(useStrictParsing());
531 bool success = parser.parseValue(this, propertyID, value, important);
533 // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
534 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
535 } else if (notifyChanged)
536 setChanged(InlineStyleChange);
541 bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged)
543 removeProperty(propertyID);
544 m_values.append(CSSProperty(propertyID, new CSSPrimitiveValue(value), important));
550 void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important)
552 removeProperty(propertyId);
553 m_values.append(CSSProperty(propertyId, new CSSPrimitiveValue(value, type), important));
557 void CSSMutableStyleDeclaration::setImageProperty(int propertyId, const String& url, bool important)
559 removeProperty(propertyId);
560 m_values.append(CSSProperty(propertyId, new CSSImageValue(url, this), important));
564 void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration)
567 CSSParser parser(useStrictParsing());
568 parser.parseDeclaration(this, styleDeclaration);
572 void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty * const * properties, int numProperties)
574 for (int i = 0; i < numProperties; ++i) {
575 // Only add properties that have no !important counterpart present
576 if (!getPropertyPriority(properties[i]->id()) || properties[i]->isImportant()) {
577 removeProperty(properties[i]->id(), false);
578 ASSERT(properties[i]);
579 m_values.append(*properties[i]);
582 // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add
583 // a notifyChanged argument to this function to follow the model of other functions in this class.
586 void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool /*multiLength*/)
588 bool parseMode = useStrictParsing();
589 setStrictParsing(false);
590 setProperty(propertyId, value, important);
591 setStrictParsing(parseMode);
594 unsigned CSSMutableStyleDeclaration::length() const
596 return m_values.count();
599 String CSSMutableStyleDeclaration::item(unsigned i) const
601 if (i >= m_values.count())
603 return getPropertyName(static_cast<CSSPropertyID>(m_values[i].id()));
606 String CSSMutableStyleDeclaration::cssText() const
610 const CSSProperty* positionXProp = 0;
611 const CSSProperty* positionYProp = 0;
613 DeprecatedValueListConstIterator<CSSProperty> end;
614 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) {
615 const CSSProperty& prop = *it;
616 if (prop.id() == CSS_PROP_BACKGROUND_POSITION_X)
617 positionXProp = ∝
618 else if (prop.id() == CSS_PROP_BACKGROUND_POSITION_Y)
619 positionYProp = ∝
621 result += prop.cssText();
624 // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output.
625 // It is required because background-position-x/y are non-standard properties and WebKit generated output
626 // would not work in Firefox (<rdar://problem/5143183>)
627 // It would be a better solution if background-position was CSS_PAIR.
628 if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) {
629 String positionValue;
630 const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y };
631 if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList())
632 positionValue = getLayeredShorthandValue(properties, 2);
634 positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText();
635 result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; ";
638 result += positionXProp->cssText();
640 result += positionYProp->cssText();
646 void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec)
650 CSSParser parser(useStrictParsing());
651 parser.parseDeclaration(this, text);
652 // FIXME: Detect syntax errors and set ec.
656 void CSSMutableStyleDeclaration::merge(CSSMutableStyleDeclaration* other, bool argOverridesOnConflict)
658 DeprecatedValueListConstIterator<CSSProperty> end;
659 for (DeprecatedValueListConstIterator<CSSProperty> it = other->valuesIterator(); it != end; ++it) {
660 const CSSProperty& property = *it;
661 RefPtr<CSSValue> value = getPropertyCSSValue(property.id());
663 if (!argOverridesOnConflict)
665 removeProperty(property.id());
667 m_values.append(property);
669 // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add
670 // a notifyChanged argument to this function to follow the model of other functions in this class.
673 // This is the list of properties we want to copy in the copyBlockProperties() function.
674 // It is the list of CSS properties that apply specially to block-level elements.
675 static const int blockProperties[] = {
677 CSS_PROP_OVERFLOW, // This can be also be applied to replaced elements
678 CSS_PROP__WEBKIT_COLUMN_COUNT,
679 CSS_PROP__WEBKIT_COLUMN_GAP,
680 CSS_PROP__WEBKIT_COLUMN_RULE_COLOR,
681 CSS_PROP__WEBKIT_COLUMN_RULE_STYLE,
682 CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH,
683 CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE,
684 CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER,
685 CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE,
686 CSS_PROP__WEBKIT_COLUMN_WIDTH,
687 CSS_PROP_PAGE_BREAK_AFTER,
688 CSS_PROP_PAGE_BREAK_BEFORE,
689 CSS_PROP_PAGE_BREAK_INSIDE,
691 CSS_PROP_TEXT_INDENT,
695 const unsigned numBlockProperties = sizeof(blockProperties) / sizeof(blockProperties[0]);
697 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const
699 return copyPropertiesInSet(blockProperties, numBlockProperties);
702 void CSSMutableStyleDeclaration::removeBlockProperties()
704 removePropertiesInSet(blockProperties, numBlockProperties);
707 void CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged)
709 bool changed = false;
710 for (unsigned i = 0; i < length; i++) {
711 RefPtr<CSSValue> value = getPropertyCSSValue(set[i]);
713 m_values.remove(CSSProperty(set[i], value.release(), false));
717 if (changed && notifyChanged)
721 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable()
726 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const
728 return new CSSMutableStyleDeclaration(0, m_values);
731 } // namespace WebCore