2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "CSSMutableStyleDeclaration.h"
24 #include "CSSImageValue.h"
25 #include "CSSParser.h"
26 #include "CSSProperty.h"
27 #include "CSSPropertyNames.h"
28 #include "CSSStyleSheet.h"
29 #include "CSSValueKeywords.h"
30 #include "CSSValueList.h"
32 #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 // Quirk for Xcode 3.0 initial help content. It relied on our incorrect handling of visibility
529 // of elements nested inside visibility: hiddent content.
530 if (propertyID == CSS_PROP_VISIBILITY && m_node && m_node->isHTMLElement() && static_cast<HTMLElement*>(m_node)->className() == "tab_content") {
531 if (Settings* settings = m_node->document()->settings()) {
532 if (settings->needsXcodeVisibilityQuirk()) {
533 setProperty(CSS_PROP_VISIBILITY, CSS_VAL_VISIBLE, false, notifyChanged);
534 if (value == "hidden")
535 setProperty(CSS_PROP_DISPLAY, CSS_VAL_NONE, false, notifyChanged);
537 removeProperty(CSS_PROP_DISPLAY, ec);
543 // When replacing an existing property value, this moves the property to the end of the list.
544 // Firefox preserves the position, and MSIE moves the property to the beginning.
545 CSSParser parser(useStrictParsing());
546 bool success = parser.parseValue(this, propertyID, value, important);
548 // CSS DOM requires raising SYNTAX_ERR here, but this is too dangerous for compatibility,
549 // see <http://bugs.webkit.org/show_bug.cgi?id=7296>.
550 } else if (notifyChanged)
551 setChanged(InlineStyleChange);
556 bool CSSMutableStyleDeclaration::setProperty(int propertyID, int value, bool important, bool notifyChanged)
558 removeProperty(propertyID);
559 m_values.append(CSSProperty(propertyID, new CSSPrimitiveValue(value), important));
565 void CSSMutableStyleDeclaration::setStringProperty(int propertyId, const String &value, CSSPrimitiveValue::UnitTypes type, bool important)
567 removeProperty(propertyId);
568 m_values.append(CSSProperty(propertyId, new CSSPrimitiveValue(value, type), important));
572 void CSSMutableStyleDeclaration::setImageProperty(int propertyId, const String& url, bool important)
574 removeProperty(propertyId);
575 m_values.append(CSSProperty(propertyId, new CSSImageValue(url, this), important));
579 void CSSMutableStyleDeclaration::parseDeclaration(const String& styleDeclaration)
582 CSSParser parser(useStrictParsing());
583 parser.parseDeclaration(this, styleDeclaration);
587 void CSSMutableStyleDeclaration::addParsedProperties(const CSSProperty * const * properties, int numProperties)
589 for (int i = 0; i < numProperties; ++i) {
590 // Only add properties that have no !important counterpart present
591 if (!getPropertyPriority(properties[i]->id()) || properties[i]->isImportant()) {
592 removeProperty(properties[i]->id(), false);
593 ASSERT(properties[i]);
594 m_values.append(*properties[i]);
597 // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add
598 // a notifyChanged argument to this function to follow the model of other functions in this class.
601 void CSSMutableStyleDeclaration::setLengthProperty(int propertyId, const String& value, bool important, bool /*multiLength*/)
603 bool parseMode = useStrictParsing();
604 setStrictParsing(false);
605 setProperty(propertyId, value, important);
606 setStrictParsing(parseMode);
609 unsigned CSSMutableStyleDeclaration::length() const
611 return m_values.count();
614 String CSSMutableStyleDeclaration::item(unsigned i) const
616 if (i >= m_values.count())
618 return getPropertyName(static_cast<CSSPropertyID>(m_values[i].id()));
621 String CSSMutableStyleDeclaration::cssText() const
625 const CSSProperty* positionXProp = 0;
626 const CSSProperty* positionYProp = 0;
628 DeprecatedValueListConstIterator<CSSProperty> end;
629 for (DeprecatedValueListConstIterator<CSSProperty> it = m_values.begin(); it != end; ++it) {
630 const CSSProperty& prop = *it;
631 if (prop.id() == CSS_PROP_BACKGROUND_POSITION_X)
632 positionXProp = ∝
633 else if (prop.id() == CSS_PROP_BACKGROUND_POSITION_Y)
634 positionYProp = ∝
636 result += prop.cssText();
639 // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output.
640 // It is required because background-position-x/y are non-standard properties and WebKit generated output
641 // would not work in Firefox (<rdar://problem/5143183>)
642 // It would be a better solution if background-position was CSS_PAIR.
643 if (positionXProp && positionYProp && positionXProp->isImportant() == positionYProp->isImportant()) {
644 String positionValue;
645 const int properties[2] = { CSS_PROP_BACKGROUND_POSITION_X, CSS_PROP_BACKGROUND_POSITION_Y };
646 if (positionXProp->value()->isValueList() || positionYProp->value()->isValueList())
647 positionValue = getLayeredShorthandValue(properties, 2);
649 positionValue = positionXProp->value()->cssText() + " " + positionYProp->value()->cssText();
650 result += "background-position: " + positionValue + (positionXProp->isImportant() ? " !important" : "") + "; ";
653 result += positionXProp->cssText();
655 result += positionYProp->cssText();
661 void CSSMutableStyleDeclaration::setCssText(const String& text, ExceptionCode& ec)
665 CSSParser parser(useStrictParsing());
666 parser.parseDeclaration(this, text);
667 // FIXME: Detect syntax errors and set ec.
671 void CSSMutableStyleDeclaration::merge(CSSMutableStyleDeclaration* other, bool argOverridesOnConflict)
673 DeprecatedValueListConstIterator<CSSProperty> end;
674 for (DeprecatedValueListConstIterator<CSSProperty> it = other->valuesIterator(); it != end; ++it) {
675 const CSSProperty& property = *it;
676 RefPtr<CSSValue> value = getPropertyCSSValue(property.id());
678 if (!argOverridesOnConflict)
680 removeProperty(property.id());
682 m_values.append(property);
684 // FIXME: This probably should have a call to setChanged() if something changed. We may also wish to add
685 // a notifyChanged argument to this function to follow the model of other functions in this class.
688 // This is the list of properties we want to copy in the copyBlockProperties() function.
689 // It is the list of CSS properties that apply specially to block-level elements.
690 static const int blockProperties[] = {
692 CSS_PROP_OVERFLOW, // This can be also be applied to replaced elements
693 CSS_PROP__WEBKIT_COLUMN_COUNT,
694 CSS_PROP__WEBKIT_COLUMN_GAP,
695 CSS_PROP__WEBKIT_COLUMN_RULE_COLOR,
696 CSS_PROP__WEBKIT_COLUMN_RULE_STYLE,
697 CSS_PROP__WEBKIT_COLUMN_RULE_WIDTH,
698 CSS_PROP__WEBKIT_COLUMN_BREAK_BEFORE,
699 CSS_PROP__WEBKIT_COLUMN_BREAK_AFTER,
700 CSS_PROP__WEBKIT_COLUMN_BREAK_INSIDE,
701 CSS_PROP__WEBKIT_COLUMN_WIDTH,
702 CSS_PROP_PAGE_BREAK_AFTER,
703 CSS_PROP_PAGE_BREAK_BEFORE,
704 CSS_PROP_PAGE_BREAK_INSIDE,
706 CSS_PROP_TEXT_INDENT,
710 const unsigned numBlockProperties = sizeof(blockProperties) / sizeof(blockProperties[0]);
712 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copyBlockProperties() const
714 return copyPropertiesInSet(blockProperties, numBlockProperties);
717 void CSSMutableStyleDeclaration::removeBlockProperties()
719 removePropertiesInSet(blockProperties, numBlockProperties);
722 void CSSMutableStyleDeclaration::removePropertiesInSet(const int* set, unsigned length, bool notifyChanged)
724 bool changed = false;
725 for (unsigned i = 0; i < length; i++) {
726 RefPtr<CSSValue> value = getPropertyCSSValue(set[i]);
728 m_values.remove(CSSProperty(set[i], value.release(), false));
732 if (changed && notifyChanged)
736 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::makeMutable()
741 PassRefPtr<CSSMutableStyleDeclaration> CSSMutableStyleDeclaration::copy() const
743 return new CSSMutableStyleDeclaration(0, m_values);
746 } // namespace WebCore