2 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
4 * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
5 * Copyright (C) 2013 Intel Corporation. All rights reserved.
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 "StyleProperties.h"
26 #include "CSSComputedStyleDeclaration.h"
27 #include "CSSCustomPropertyValue.h"
28 #include "CSSDeferredParser.h"
29 #include "CSSParser.h"
30 #include "CSSPendingSubstitutionValue.h"
31 #include "CSSValueKeywords.h"
32 #include "CSSValueList.h"
33 #include "CSSValuePool.h"
35 #include "PropertySetCSSStyleDeclaration.h"
36 #include "StylePropertyShorthand.h"
37 #include "StylePropertyShorthandFunctions.h"
38 #include "StyleSheetContents.h"
40 #include <wtf/text/StringBuilder.h>
44 #include <wtf/ASCIICType.h>
45 #include <wtf/text/CString.h>
50 static size_t sizeForImmutableStylePropertiesWithPropertyCount(unsigned count)
52 return sizeof(ImmutableStyleProperties) - sizeof(void*) + sizeof(CSSValue*) * count + sizeof(StylePropertyMetadata) * count;
55 static bool isInitialOrInherit(const String& value)
57 return value.length() == 7 && (value == "initial" || value == "inherit");
60 Ref<ImmutableStyleProperties> ImmutableStyleProperties::create(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode)
62 void* slot = WTF::fastMalloc(sizeForImmutableStylePropertiesWithPropertyCount(count));
63 return adoptRef(*new (NotNull, slot) ImmutableStyleProperties(properties, count, cssParserMode));
66 Ref<ImmutableStyleProperties> StyleProperties::immutableCopyIfNeeded() const
68 if (is<ImmutableStyleProperties>(*this))
69 return downcast<ImmutableStyleProperties>(const_cast<StyleProperties&>(*this));
70 const MutableStyleProperties& mutableThis = downcast<MutableStyleProperties>(*this);
71 return ImmutableStyleProperties::create(mutableThis.m_propertyVector.data(), mutableThis.m_propertyVector.size(), cssParserMode());
74 MutableStyleProperties::MutableStyleProperties(CSSParserMode cssParserMode)
75 : StyleProperties(cssParserMode, MutablePropertiesType)
79 MutableStyleProperties::MutableStyleProperties(const CSSProperty* properties, unsigned length)
80 : StyleProperties(HTMLStandardMode, MutablePropertiesType)
82 m_propertyVector.reserveInitialCapacity(length);
83 for (unsigned i = 0; i < length; ++i)
84 m_propertyVector.uncheckedAppend(properties[i]);
87 MutableStyleProperties::~MutableStyleProperties()
91 ImmutableStyleProperties::ImmutableStyleProperties(const CSSProperty* properties, unsigned length, CSSParserMode cssParserMode)
92 : StyleProperties(cssParserMode, length)
94 StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(this->metadataArray());
95 CSSValue** valueArray = const_cast<CSSValue**>(this->valueArray());
96 for (unsigned i = 0; i < length; ++i) {
97 metadataArray[i] = properties[i].metadata();
98 valueArray[i] = properties[i].value();
103 ImmutableStyleProperties::~ImmutableStyleProperties()
105 CSSValue** valueArray = const_cast<CSSValue**>(this->valueArray());
106 for (unsigned i = 0; i < m_arraySize; ++i)
107 valueArray[i]->deref();
110 MutableStyleProperties::MutableStyleProperties(const StyleProperties& other)
111 : StyleProperties(other.cssParserMode(), MutablePropertiesType)
113 ASSERT(other.type() != DeferredPropertiesType);
114 if (is<MutableStyleProperties>(other))
115 m_propertyVector = downcast<MutableStyleProperties>(other).m_propertyVector;
117 const auto& immutableOther = downcast<ImmutableStyleProperties>(other);
118 unsigned propertyCount = immutableOther.propertyCount();
119 m_propertyVector.reserveInitialCapacity(propertyCount);
120 for (unsigned i = 0; i < propertyCount; ++i)
121 m_propertyVector.uncheckedAppend(immutableOther.propertyAt(i).toCSSProperty());
125 String StyleProperties::getPropertyValue(CSSPropertyID propertyID) const
127 RefPtr<CSSValue> value = getPropertyCSSValue(propertyID);
129 return value->cssText();
131 const StylePropertyShorthand& shorthand = shorthandForProperty(propertyID);
132 if (shorthand.length()) {
133 RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[0]);
134 if (!value || value->isPendingSubstitutionValue())
138 // Shorthand and 4-values properties
139 switch (propertyID) {
141 return getCommonValue(allShorthand());
142 case CSSPropertyAnimation:
143 return getLayeredShorthandValue(animationShorthand());
144 case CSSPropertyBorderSpacing:
145 return borderSpacingValue(borderSpacingShorthand());
146 case CSSPropertyBackgroundPosition:
147 return getLayeredShorthandValue(backgroundPositionShorthand());
148 case CSSPropertyBackgroundRepeat:
149 return getLayeredShorthandValue(backgroundRepeatShorthand());
150 case CSSPropertyBackground:
151 return getLayeredShorthandValue(backgroundShorthand());
152 case CSSPropertyBorder:
153 return borderPropertyValue(OmitUncommonValues);
154 case CSSPropertyBorderTop:
155 return getShorthandValue(borderTopShorthand());
156 case CSSPropertyBorderRight:
157 return getShorthandValue(borderRightShorthand());
158 case CSSPropertyBorderBottom:
159 return getShorthandValue(borderBottomShorthand());
160 case CSSPropertyBorderLeft:
161 return getShorthandValue(borderLeftShorthand());
162 case CSSPropertyOutline:
163 return getShorthandValue(outlineShorthand());
164 case CSSPropertyBorderColor:
165 return get4Values(borderColorShorthand());
166 case CSSPropertyBorderWidth:
167 return get4Values(borderWidthShorthand());
168 case CSSPropertyBorderStyle:
169 return get4Values(borderStyleShorthand());
170 case CSSPropertyColumnRule:
171 return getShorthandValue(columnRuleShorthand());
172 case CSSPropertyColumns:
173 return getShorthandValue(columnsShorthand());
174 case CSSPropertyFlex:
175 return getShorthandValue(flexShorthand());
176 case CSSPropertyFlexFlow:
177 return getShorthandValue(flexFlowShorthand());
178 case CSSPropertyGridArea:
179 return getShorthandValue(gridAreaShorthand());
180 case CSSPropertyGridTemplate:
181 return getShorthandValue(gridTemplateShorthand());
182 case CSSPropertyGrid:
183 return getShorthandValue(gridShorthand());
184 case CSSPropertyGridColumn:
185 return getShorthandValue(gridColumnShorthand());
186 case CSSPropertyGridRow:
187 return getShorthandValue(gridRowShorthand());
188 case CSSPropertyPlaceContent:
189 return getAlignmentShorthandValue(placeContentShorthand());
190 case CSSPropertyPlaceItems:
191 return getAlignmentShorthandValue(placeItemsShorthand());
192 case CSSPropertyFont:
194 case CSSPropertyMargin:
195 return get4Values(marginShorthand());
196 case CSSPropertyWebkitMarginCollapse:
197 return getShorthandValue(webkitMarginCollapseShorthand());
198 case CSSPropertyOverflow:
199 return getCommonValue(overflowShorthand());
200 case CSSPropertyPadding:
201 return get4Values(paddingShorthand());
202 case CSSPropertyTransition:
203 return getLayeredShorthandValue(transitionShorthand());
204 case CSSPropertyListStyle:
205 return getShorthandValue(listStyleShorthand());
206 case CSSPropertyWebkitMarquee:
207 return getShorthandValue(webkitMarqueeShorthand());
208 case CSSPropertyWebkitMaskPosition:
209 return getLayeredShorthandValue(webkitMaskPositionShorthand());
210 case CSSPropertyWebkitMaskRepeat:
211 return getLayeredShorthandValue(webkitMaskRepeatShorthand());
212 case CSSPropertyWebkitMask:
213 return getLayeredShorthandValue(webkitMaskShorthand());
214 case CSSPropertyWebkitTextEmphasis:
215 return getShorthandValue(webkitTextEmphasisShorthand());
216 case CSSPropertyWebkitTextStroke:
217 return getShorthandValue(webkitTextStrokeShorthand());
218 case CSSPropertyPerspectiveOrigin:
219 return getShorthandValue(perspectiveOriginShorthand());
220 case CSSPropertyTransformOrigin:
221 return getShorthandValue(transformOriginShorthand());
222 case CSSPropertyMarker: {
223 RefPtr<CSSValue> value = getPropertyCSSValueInternal(CSSPropertyMarkerStart);
225 return value->cssText();
228 case CSSPropertyBorderRadius:
229 return get4Values(borderRadiusShorthand());
230 #if ENABLE(CSS_SCROLL_SNAP)
231 case CSSPropertyScrollSnapMargin:
232 return get4Values(scrollSnapMarginShorthand());
233 case CSSPropertyScrollPadding:
234 return get4Values(scrollPaddingShorthand());
241 String StyleProperties::getCustomPropertyValue(const String& propertyName) const
243 RefPtr<CSSValue> value = getCustomPropertyCSSValue(propertyName);
245 return value->cssText();
249 String StyleProperties::borderSpacingValue(const StylePropertyShorthand& shorthand) const
251 RefPtr<CSSValue> horizontalValue = getPropertyCSSValueInternal(shorthand.properties()[0]);
252 RefPtr<CSSValue> verticalValue = getPropertyCSSValueInternal(shorthand.properties()[1]);
254 // While standard border-spacing property does not allow specifying border-spacing-vertical without
255 // specifying border-spacing-horizontal <http://www.w3.org/TR/CSS21/tables.html#separated-borders>,
256 // -webkit-border-spacing-vertical can be set without -webkit-border-spacing-horizontal.
257 if (!horizontalValue || !verticalValue)
260 String horizontalValueCSSText = horizontalValue->cssText();
261 String verticalValueCSSText = verticalValue->cssText();
262 if (horizontalValueCSSText == verticalValueCSSText)
263 return horizontalValueCSSText;
264 return horizontalValueCSSText + ' ' + verticalValueCSSText;
267 void StyleProperties::appendFontLonghandValueIfExplicit(CSSPropertyID propertyID, StringBuilder& result, String& commonValue) const
269 int foundPropertyIndex = findPropertyIndex(propertyID);
270 if (foundPropertyIndex == -1)
271 return; // All longhands must have at least implicit values if "font" is specified.
273 if (propertyAt(foundPropertyIndex).isImplicit()) {
274 commonValue = String();
279 switch (propertyID) {
280 case CSSPropertyFontStyle:
282 case CSSPropertyFontFamily:
283 case CSSPropertyFontVariantCaps:
284 case CSSPropertyFontWeight:
285 case CSSPropertyFontStretch:
288 case CSSPropertyLineHeight:
292 ASSERT_NOT_REACHED();
295 if (prefix && !result.isEmpty())
296 result.append(prefix);
297 String value = propertyAt(foundPropertyIndex).value()->cssText();
298 result.append(value);
299 if (!commonValue.isNull() && commonValue != value)
300 commonValue = String();
303 String StyleProperties::fontValue() const
305 int fontSizePropertyIndex = findPropertyIndex(CSSPropertyFontSize);
306 int fontFamilyPropertyIndex = findPropertyIndex(CSSPropertyFontFamily);
307 if (fontSizePropertyIndex == -1 || fontFamilyPropertyIndex == -1)
308 return emptyString();
310 PropertyReference fontSizeProperty = propertyAt(fontSizePropertyIndex);
311 PropertyReference fontFamilyProperty = propertyAt(fontFamilyPropertyIndex);
312 if (fontSizeProperty.isImplicit() || fontFamilyProperty.isImplicit())
313 return emptyString();
315 String commonValue = fontSizeProperty.value()->cssText();
316 StringBuilder result;
317 appendFontLonghandValueIfExplicit(CSSPropertyFontStyle, result, commonValue);
318 appendFontLonghandValueIfExplicit(CSSPropertyFontVariantCaps, result, commonValue);
319 appendFontLonghandValueIfExplicit(CSSPropertyFontWeight, result, commonValue);
320 appendFontLonghandValueIfExplicit(CSSPropertyFontStretch, result, commonValue);
321 if (!result.isEmpty())
323 result.append(fontSizeProperty.value()->cssText());
324 appendFontLonghandValueIfExplicit(CSSPropertyLineHeight, result, commonValue);
325 if (!result.isEmpty())
327 result.append(fontFamilyProperty.value()->cssText());
328 if (isInitialOrInherit(commonValue))
330 return result.toString();
333 String StyleProperties::get4Values(const StylePropertyShorthand& shorthand) const
335 // Assume the properties are in the usual order top, right, bottom, left.
336 int topValueIndex = findPropertyIndex(shorthand.properties()[0]);
337 int rightValueIndex = findPropertyIndex(shorthand.properties()[1]);
338 int bottomValueIndex = findPropertyIndex(shorthand.properties()[2]);
339 int leftValueIndex = findPropertyIndex(shorthand.properties()[3]);
341 if (topValueIndex == -1 || rightValueIndex == -1 || bottomValueIndex == -1 || leftValueIndex == -1)
344 PropertyReference top = propertyAt(topValueIndex);
345 PropertyReference right = propertyAt(rightValueIndex);
346 PropertyReference bottom = propertyAt(bottomValueIndex);
347 PropertyReference left = propertyAt(leftValueIndex);
349 // All 4 properties must be specified.
350 if (!top.value() || !right.value() || !bottom.value() || !left.value())
353 if (top.isInherited() && right.isInherited() && bottom.isInherited() && left.isInherited())
354 return getValueName(CSSValueInherit);
356 if (top.value()->isInitialValue() || right.value()->isInitialValue() || bottom.value()->isInitialValue() || left.value()->isInitialValue()) {
357 if (top.value()->isInitialValue() && right.value()->isInitialValue() && bottom.value()->isInitialValue() && left.value()->isInitialValue() && !top.isImplicit()) {
358 // All components are "initial" and "top" is not implicit.
359 return getValueName(CSSValueInitial);
363 if (top.isImportant() != right.isImportant() || right.isImportant() != bottom.isImportant() || bottom.isImportant() != left.isImportant())
366 bool showLeft = !right.value()->equals(*left.value());
367 bool showBottom = !top.value()->equals(*bottom.value()) || showLeft;
368 bool showRight = !top.value()->equals(*right.value()) || showBottom;
370 StringBuilder result;
371 result.append(top.value()->cssText());
374 result.append(right.value()->cssText());
378 result.append(bottom.value()->cssText());
382 result.append(left.value()->cssText());
384 return result.toString();
387 String StyleProperties::getLayeredShorthandValue(const StylePropertyShorthand& shorthand) const
389 StringBuilder result;
391 const unsigned size = shorthand.length();
392 // Begin by collecting the properties into an array.
393 Vector< RefPtr<CSSValue>> values(size);
394 size_t numLayers = 0;
396 for (unsigned i = 0; i < size; ++i) {
397 values[i] = getPropertyCSSValueInternal(shorthand.properties()[i]);
399 // We don't have all longhand properties defined as required for the shorthand
400 // property and thus should not serialize to a shorthand value. See spec at
401 // http://www.w3.org/TR/cssom-1/#serialize-a-css-declaration-block.
404 if (values[i]->isBaseValueList())
405 numLayers = std::max(downcast<CSSValueList>(*values[i]).length(), numLayers);
407 numLayers = std::max<size_t>(1U, numLayers);
411 bool commonValueInitialized = false;
413 // Now stitch the properties together. Implicit initial values are flagged as such and
414 // can safely be omitted.
415 for (size_t i = 0; i < numLayers; i++) {
416 StringBuilder layerResult;
417 bool useRepeatXShorthand = false;
418 bool useRepeatYShorthand = false;
419 bool useSingleWordShorthand = false;
420 bool foundPositionYCSSProperty = false;
421 for (unsigned j = 0; j < size; j++) {
422 RefPtr<CSSValue> value;
424 if (values[j]->isBaseValueList())
425 value = downcast<CSSValueList>(*values[j]).item(i);
429 // Color only belongs in the last layer.
430 if (shorthand.properties()[j] == CSSPropertyBackgroundColor) {
431 if (i != numLayers - 1)
433 } else if (i) // Other singletons only belong in the first layer.
438 // We need to report background-repeat as it was written in the CSS. If the property is implicit,
439 // then it was written with only one value. Here we figure out which value that was so we can
440 // report back correctly.
441 if ((shorthand.properties()[j] == CSSPropertyBackgroundRepeatX && isPropertyImplicit(shorthand.properties()[j]))
442 || (shorthand.properties()[j] == CSSPropertyWebkitMaskRepeatX && isPropertyImplicit(shorthand.properties()[j]))) {
444 // BUG 49055: make sure the value was not reset in the layer check just above.
445 if ((j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyBackgroundRepeatY && value)
446 || (j < size - 1 && shorthand.properties()[j + 1] == CSSPropertyWebkitMaskRepeatY && value)) {
447 RefPtr<CSSValue> yValue;
448 RefPtr<CSSValue> nextValue = values[j + 1];
450 if (is<CSSValueList>(*nextValue))
451 yValue = downcast<CSSValueList>(*nextValue).itemWithoutBoundsCheck(i);
455 if (!is<CSSPrimitiveValue>(*value) || !is<CSSPrimitiveValue>(*yValue))
458 CSSValueID xId = downcast<CSSPrimitiveValue>(*value).valueID();
459 CSSValueID yId = downcast<CSSPrimitiveValue>(*yValue).valueID();
461 if (xId == CSSValueRepeat && yId == CSSValueNoRepeat) {
462 useRepeatXShorthand = true;
464 } else if (xId == CSSValueNoRepeat && yId == CSSValueRepeat) {
465 useRepeatYShorthand = true;
469 useSingleWordShorthand = true;
477 if (value && !value->isImplicitInitialValue()) {
478 if (!layerResult.isEmpty())
479 layerResult.append(' ');
480 if (foundPositionYCSSProperty
481 && (shorthand.properties()[j] == CSSPropertyBackgroundSize || shorthand.properties()[j] == CSSPropertyWebkitMaskSize))
482 layerResult.appendLiteral("/ ");
483 if (!foundPositionYCSSProperty
484 && (shorthand.properties()[j] == CSSPropertyBackgroundSize || shorthand.properties()[j] == CSSPropertyWebkitMaskSize))
487 if (useRepeatXShorthand) {
488 useRepeatXShorthand = false;
489 layerResult.append(getValueName(CSSValueRepeatX));
490 } else if (useRepeatYShorthand) {
491 useRepeatYShorthand = false;
492 layerResult.append(getValueName(CSSValueRepeatY));
494 if (useSingleWordShorthand)
495 useSingleWordShorthand = false;
496 valueText = value->cssText();
497 layerResult.append(valueText);
500 if (shorthand.properties()[j] == CSSPropertyBackgroundPositionY
501 || shorthand.properties()[j] == CSSPropertyWebkitMaskPositionY) {
502 foundPositionYCSSProperty = true;
504 // background-position is a special case: if only the first offset is specified,
505 // the second one defaults to "center", not the same value.
506 if (commonValueInitialized && commonValue != "initial" && commonValue != "inherit")
507 commonValue = String();
511 if (!commonValueInitialized) {
512 commonValue = valueText;
513 commonValueInitialized = true;
514 } else if (!commonValue.isNull() && commonValue != valueText)
515 commonValue = String();
518 if (!layerResult.isEmpty()) {
519 if (!result.isEmpty())
520 result.appendLiteral(", ");
521 result.append(layerResult);
525 if (isInitialOrInherit(commonValue))
528 if (result.isEmpty())
530 return result.toString();
533 String StyleProperties::getShorthandValue(const StylePropertyShorthand& shorthand) const
536 StringBuilder result;
537 for (unsigned i = 0; i < shorthand.length(); ++i) {
538 if (!isPropertyImplicit(shorthand.properties()[i])) {
539 RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
542 String valueText = value->cssText();
544 commonValue = valueText;
545 else if (!commonValue.isNull() && commonValue != valueText)
546 commonValue = String();
547 if (value->isInitialValue())
549 if (!result.isEmpty())
551 result.append(valueText);
553 commonValue = String();
555 if (isInitialOrInherit(commonValue))
557 if (result.isEmpty())
559 return result.toString();
562 // only returns a non-null value if all properties have the same, non-null value
563 String StyleProperties::getCommonValue(const StylePropertyShorthand& shorthand) const
566 bool lastPropertyWasImportant = false;
567 for (unsigned i = 0; i < shorthand.length(); ++i) {
568 RefPtr<CSSValue> value = getPropertyCSSValueInternal(shorthand.properties()[i]);
571 // FIXME: CSSInitialValue::cssText should generate the right value.
572 String text = value->cssText();
577 else if (res != text)
580 bool currentPropertyIsImportant = propertyIsImportant(shorthand.properties()[i]);
581 if (i && lastPropertyWasImportant != currentPropertyIsImportant)
583 lastPropertyWasImportant = currentPropertyIsImportant;
588 String StyleProperties::getAlignmentShorthandValue(const StylePropertyShorthand& shorthand) const
590 String value = getCommonValue(shorthand);
591 if (value.isNull() || value.isEmpty())
592 return getShorthandValue(shorthand);
596 String StyleProperties::borderPropertyValue(CommonValueMode valueMode) const
598 const StylePropertyShorthand properties[3] = { borderWidthShorthand(), borderStyleShorthand(), borderColorShorthand() };
600 StringBuilder result;
601 for (size_t i = 0; i < WTF_ARRAY_LENGTH(properties); ++i) {
602 String value = getCommonValue(properties[i]);
603 if (value.isNull()) {
604 if (valueMode == ReturnNullOnUncommonValues)
606 ASSERT(valueMode == OmitUncommonValues);
611 else if (!commonValue.isNull() && commonValue != value)
612 commonValue = String();
613 if (value == "initial")
615 if (!result.isEmpty())
617 result.append(value);
619 if (isInitialOrInherit(commonValue))
621 return result.isEmpty() ? String() : result.toString();
624 RefPtr<CSSValue> StyleProperties::getPropertyCSSValue(CSSPropertyID propertyID) const
626 return getPropertyCSSValueInternal(propertyID);
629 RefPtr<CSSValue> StyleProperties::getPropertyCSSValueInternal(CSSPropertyID propertyID) const
631 int foundPropertyIndex = findPropertyIndex(propertyID);
632 if (foundPropertyIndex == -1)
634 return propertyAt(foundPropertyIndex).value();
637 RefPtr<CSSValue> StyleProperties::getCustomPropertyCSSValue(const String& propertyName) const
639 int foundPropertyIndex = findCustomPropertyIndex(propertyName);
640 if (foundPropertyIndex == -1)
642 return propertyAt(foundPropertyIndex).value();
645 bool MutableStyleProperties::removeShorthandProperty(CSSPropertyID propertyID)
647 StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
648 if (!shorthand.length())
651 return removePropertiesInSet(shorthand.properties(), shorthand.length());
654 bool MutableStyleProperties::removeProperty(CSSPropertyID propertyID, String* returnText)
656 if (removeShorthandProperty(propertyID)) {
657 // FIXME: Return an equivalent shorthand when possible.
659 *returnText = emptyString();
663 int foundPropertyIndex = findPropertyIndex(propertyID);
664 if (foundPropertyIndex == -1) {
666 *returnText = emptyString();
671 *returnText = propertyAt(foundPropertyIndex).value()->cssText();
673 // A more efficient removal strategy would involve marking entries as empty
674 // and sweeping them when the vector grows too big.
675 m_propertyVector.remove(foundPropertyIndex);
680 bool MutableStyleProperties::removeCustomProperty(const String& propertyName, String* returnText)
682 int foundPropertyIndex = findCustomPropertyIndex(propertyName);
683 if (foundPropertyIndex == -1) {
685 *returnText = emptyString();
690 *returnText = propertyAt(foundPropertyIndex).value()->cssText();
692 // A more efficient removal strategy would involve marking entries as empty
693 // and sweeping them when the vector grows too big.
694 m_propertyVector.remove(foundPropertyIndex);
699 bool StyleProperties::propertyIsImportant(CSSPropertyID propertyID) const
701 int foundPropertyIndex = findPropertyIndex(propertyID);
702 if (foundPropertyIndex != -1)
703 return propertyAt(foundPropertyIndex).isImportant();
705 StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
706 if (!shorthand.length())
709 for (unsigned i = 0; i < shorthand.length(); ++i) {
710 if (!propertyIsImportant(shorthand.properties()[i]))
716 bool StyleProperties::customPropertyIsImportant(const String& propertyName) const
718 int foundPropertyIndex = findCustomPropertyIndex(propertyName);
719 if (foundPropertyIndex != -1)
720 return propertyAt(foundPropertyIndex).isImportant();
724 String StyleProperties::getPropertyShorthand(CSSPropertyID propertyID) const
726 int foundPropertyIndex = findPropertyIndex(propertyID);
727 if (foundPropertyIndex == -1)
729 return getPropertyNameString(propertyAt(foundPropertyIndex).shorthandID());
732 bool StyleProperties::isPropertyImplicit(CSSPropertyID propertyID) const
734 int foundPropertyIndex = findPropertyIndex(propertyID);
735 if (foundPropertyIndex == -1)
737 return propertyAt(foundPropertyIndex).isImplicit();
740 bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, const String& value, bool important, CSSParserContext parserContext)
742 // Setting the value to an empty string just removes the property in both IE and Gecko.
743 // Setting it to null seems to produce less consistent results, but we treat it just the same.
745 return removeProperty(propertyID);
747 parserContext.mode = cssParserMode();
749 // When replacing an existing property value, this moves the property to the end of the list.
750 // Firefox preserves the position, and MSIE moves the property to the beginning.
751 return CSSParser::parseValue(*this, propertyID, value, important, parserContext) == CSSParser::ParseResult::Changed;
754 bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, const String& value, bool important)
756 CSSParserContext parserContext(cssParserMode());
757 return setProperty(propertyID, value, important, parserContext);
760 bool MutableStyleProperties::setCustomProperty(const String& propertyName, const String& value, bool important, CSSParserContext parserContext)
762 // Setting the value to an empty string just removes the property in both IE and Gecko.
763 // Setting it to null seems to produce less consistent results, but we treat it just the same.
765 return removeCustomProperty(propertyName);
767 parserContext.mode = cssParserMode();
768 // When replacing an existing property value, this moves the property to the end of the list.
769 // Firefox preserves the position, and MSIE moves the property to the beginning.
770 return CSSParser::parseCustomPropertyValue(*this, propertyName, value, important, parserContext) == CSSParser::ParseResult::Changed;
773 void MutableStyleProperties::setProperty(CSSPropertyID propertyID, RefPtr<CSSValue>&& value, bool important)
775 StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
776 if (!shorthand.length()) {
777 setProperty(CSSProperty(propertyID, WTFMove(value), important));
781 removePropertiesInSet(shorthand.properties(), shorthand.length());
783 for (unsigned i = 0; i < shorthand.length(); ++i)
784 m_propertyVector.append(CSSProperty(shorthand.properties()[i], value.copyRef(), important));
787 bool MutableStyleProperties::setProperty(const CSSProperty& property, CSSProperty* slot)
789 if (!removeShorthandProperty(property.id())) {
790 CSSProperty* toReplace = slot;
792 if (property.id() == CSSPropertyCustom) {
793 if (property.value())
794 toReplace = findCustomCSSPropertyWithName(downcast<CSSCustomPropertyValue>(*property.value()).name());
796 toReplace = findCSSPropertyWithID(property.id());
800 if (*toReplace == property)
803 *toReplace = property;
808 m_propertyVector.append(property);
812 bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, CSSValueID identifier, bool important)
814 return setProperty(CSSProperty(propertyID, CSSValuePool::singleton().createIdentifierValue(identifier), important));
817 bool MutableStyleProperties::setProperty(CSSPropertyID propertyID, CSSPropertyID identifier, bool important)
819 return setProperty(CSSProperty(propertyID, CSSValuePool::singleton().createIdentifierValue(identifier), important));
822 bool MutableStyleProperties::parseDeclaration(const String& styleDeclaration, CSSParserContext context)
824 auto oldProperties = WTFMove(m_propertyVector);
825 m_propertyVector.clear();
827 context.mode = cssParserMode();
829 CSSParser parser(context);
830 parser.parseDeclaration(*this, styleDeclaration);
832 // We could do better. Just changing property order does not require style invalidation.
833 return oldProperties != m_propertyVector;
836 bool MutableStyleProperties::addParsedProperties(const ParsedPropertyVector& properties)
838 bool anyChanged = false;
839 m_propertyVector.reserveCapacity(m_propertyVector.size() + properties.size());
840 for (const auto& property : properties) {
841 if (addParsedProperty(property))
848 bool MutableStyleProperties::addParsedProperty(const CSSProperty& property)
850 if (property.id() == CSSPropertyCustom) {
851 if ((property.value() && !customPropertyIsImportant(downcast<CSSCustomPropertyValue>(*property.value()).name())) || property.isImportant())
852 return setProperty(property);
855 return setProperty(property);
858 String StyleProperties::asText() const
860 StringBuilder result;
862 int positionXPropertyIndex = -1;
863 int positionYPropertyIndex = -1;
864 int repeatXPropertyIndex = -1;
865 int repeatYPropertyIndex = -1;
867 std::bitset<numCSSProperties> shorthandPropertyUsed;
868 std::bitset<numCSSProperties> shorthandPropertyAppeared;
870 unsigned size = propertyCount();
871 unsigned numDecls = 0;
872 for (unsigned n = 0; n < size; ++n) {
873 PropertyReference property = propertyAt(n);
874 CSSPropertyID propertyID = property.id();
875 CSSPropertyID shorthandPropertyID = CSSPropertyInvalid;
876 CSSPropertyID borderFallbackShorthandProperty = CSSPropertyInvalid;
879 if (property.value() && property.value()->isPendingSubstitutionValue()) {
880 auto& substitutionValue = downcast<CSSPendingSubstitutionValue>(*property.value());
881 shorthandPropertyID = substitutionValue.shorthandPropertyId();
882 value = substitutionValue.shorthandValue()->cssText();
884 switch (propertyID) {
885 case CSSPropertyAnimationName:
886 case CSSPropertyAnimationDuration:
887 case CSSPropertyAnimationTimingFunction:
888 case CSSPropertyAnimationDelay:
889 case CSSPropertyAnimationIterationCount:
890 case CSSPropertyAnimationDirection:
891 case CSSPropertyAnimationFillMode:
892 case CSSPropertyAnimationPlayState:
893 shorthandPropertyID = CSSPropertyAnimation;
895 case CSSPropertyBackgroundPositionX:
896 positionXPropertyIndex = n;
898 case CSSPropertyBackgroundPositionY:
899 positionYPropertyIndex = n;
901 case CSSPropertyBackgroundRepeatX:
902 repeatXPropertyIndex = n;
904 case CSSPropertyBackgroundRepeatY:
905 repeatYPropertyIndex = n;
907 case CSSPropertyBorderTopWidth:
908 case CSSPropertyBorderRightWidth:
909 case CSSPropertyBorderBottomWidth:
910 case CSSPropertyBorderLeftWidth:
911 if (!borderFallbackShorthandProperty)
912 borderFallbackShorthandProperty = CSSPropertyBorderWidth;
914 case CSSPropertyBorderTopStyle:
915 case CSSPropertyBorderRightStyle:
916 case CSSPropertyBorderBottomStyle:
917 case CSSPropertyBorderLeftStyle:
918 if (!borderFallbackShorthandProperty)
919 borderFallbackShorthandProperty = CSSPropertyBorderStyle;
921 case CSSPropertyBorderTopColor:
922 case CSSPropertyBorderRightColor:
923 case CSSPropertyBorderBottomColor:
924 case CSSPropertyBorderLeftColor:
925 if (!borderFallbackShorthandProperty)
926 borderFallbackShorthandProperty = CSSPropertyBorderColor;
928 // FIXME: Deal with cases where only some of border-(top|right|bottom|left) are specified.
929 ASSERT(CSSPropertyBorder - firstCSSProperty < shorthandPropertyAppeared.size());
930 if (!shorthandPropertyAppeared[CSSPropertyBorder - firstCSSProperty]) {
931 value = borderPropertyValue(ReturnNullOnUncommonValues);
933 shorthandPropertyAppeared.set(CSSPropertyBorder - firstCSSProperty);
935 shorthandPropertyID = CSSPropertyBorder;
936 } else if (shorthandPropertyUsed[CSSPropertyBorder - firstCSSProperty])
937 shorthandPropertyID = CSSPropertyBorder;
938 if (!shorthandPropertyID)
939 shorthandPropertyID = borderFallbackShorthandProperty;
941 case CSSPropertyWebkitBorderHorizontalSpacing:
942 case CSSPropertyWebkitBorderVerticalSpacing:
943 shorthandPropertyID = CSSPropertyBorderSpacing;
945 case CSSPropertyFontFamily:
946 case CSSPropertyLineHeight:
947 case CSSPropertyFontSize:
948 case CSSPropertyFontStyle:
949 case CSSPropertyFontVariantCaps:
950 case CSSPropertyFontWeight:
951 // Don't use CSSPropertyFont because old UAs can't recognize them but are important for editing.
953 case CSSPropertyListStyleType:
954 case CSSPropertyListStylePosition:
955 case CSSPropertyListStyleImage:
956 shorthandPropertyID = CSSPropertyListStyle;
958 case CSSPropertyMarginTop:
959 case CSSPropertyMarginRight:
960 case CSSPropertyMarginBottom:
961 case CSSPropertyMarginLeft:
962 shorthandPropertyID = CSSPropertyMargin;
964 case CSSPropertyOutlineWidth:
965 case CSSPropertyOutlineStyle:
966 case CSSPropertyOutlineColor:
967 shorthandPropertyID = CSSPropertyOutline;
969 case CSSPropertyOverflowX:
970 case CSSPropertyOverflowY:
971 shorthandPropertyID = CSSPropertyOverflow;
973 case CSSPropertyPaddingTop:
974 case CSSPropertyPaddingRight:
975 case CSSPropertyPaddingBottom:
976 case CSSPropertyPaddingLeft:
977 shorthandPropertyID = CSSPropertyPadding;
979 #if ENABLE(CSS_SCROLL_SNAP)
980 case CSSPropertyScrollPaddingTop:
981 case CSSPropertyScrollPaddingRight:
982 case CSSPropertyScrollPaddingBottom:
983 case CSSPropertyScrollPaddingLeft:
984 shorthandPropertyID = CSSPropertyScrollPadding;
986 case CSSPropertyScrollSnapMarginTop:
987 case CSSPropertyScrollSnapMarginRight:
988 case CSSPropertyScrollSnapMarginBottom:
989 case CSSPropertyScrollSnapMarginLeft:
990 shorthandPropertyID = CSSPropertyScrollSnapMargin;
993 case CSSPropertyTransitionProperty:
994 case CSSPropertyTransitionDuration:
995 case CSSPropertyTransitionTimingFunction:
996 case CSSPropertyTransitionDelay:
997 shorthandPropertyID = CSSPropertyTransition;
999 case CSSPropertyFlexDirection:
1000 case CSSPropertyFlexWrap:
1001 shorthandPropertyID = CSSPropertyFlexFlow;
1003 case CSSPropertyFlexBasis:
1004 case CSSPropertyFlexGrow:
1005 case CSSPropertyFlexShrink:
1006 shorthandPropertyID = CSSPropertyFlex;
1008 case CSSPropertyWebkitMaskPositionX:
1009 case CSSPropertyWebkitMaskPositionY:
1010 case CSSPropertyWebkitMaskRepeatX:
1011 case CSSPropertyWebkitMaskRepeatY:
1012 case CSSPropertyWebkitMaskImage:
1013 case CSSPropertyWebkitMaskRepeat:
1014 case CSSPropertyWebkitMaskPosition:
1015 case CSSPropertyWebkitMaskClip:
1016 case CSSPropertyWebkitMaskOrigin:
1017 shorthandPropertyID = CSSPropertyWebkitMask;
1019 case CSSPropertyPerspectiveOriginX:
1020 case CSSPropertyPerspectiveOriginY:
1021 shorthandPropertyID = CSSPropertyPerspectiveOrigin;
1023 case CSSPropertyTransformOriginX:
1024 case CSSPropertyTransformOriginY:
1025 case CSSPropertyTransformOriginZ:
1026 shorthandPropertyID = CSSPropertyTransformOrigin;
1033 unsigned shortPropertyIndex = shorthandPropertyID - firstCSSProperty;
1034 if (shorthandPropertyID) {
1035 ASSERT(shortPropertyIndex < shorthandPropertyUsed.size());
1036 if (shorthandPropertyUsed[shortPropertyIndex])
1038 if (!shorthandPropertyAppeared[shortPropertyIndex] && value.isNull())
1039 value = getPropertyValue(shorthandPropertyID);
1040 shorthandPropertyAppeared.set(shortPropertyIndex);
1043 if (!value.isNull()) {
1044 propertyID = shorthandPropertyID;
1045 shorthandPropertyUsed.set(shortPropertyIndex);
1047 value = property.value()->cssText();
1049 if (propertyID != CSSPropertyCustom && value == "initial" && !CSSProperty::isInheritedProperty(propertyID))
1055 if (propertyID == CSSPropertyCustom)
1056 result.append(downcast<CSSCustomPropertyValue>(*property.value()).name());
1058 result.append(getPropertyName(propertyID));
1060 result.appendLiteral(": ");
1061 result.append(value);
1062 if (property.isImportant())
1063 result.appendLiteral(" !important");
1067 // FIXME: This is a not-so-nice way to turn x/y positions into single background-position in output.
1068 // It is required because background-position-x/y are non-standard properties and WebKit generated output
1069 // would not work in Firefox (<rdar://problem/5143183>)
1070 // It would be a better solution if background-position was CSS_PAIR.
1071 if (positionXPropertyIndex != -1 && positionYPropertyIndex != -1 && propertyAt(positionXPropertyIndex).isImportant() == propertyAt(positionYPropertyIndex).isImportant()) {
1072 PropertyReference positionXProperty = propertyAt(positionXPropertyIndex);
1073 PropertyReference positionYProperty = propertyAt(positionYPropertyIndex);
1077 result.appendLiteral("background-position: ");
1078 if (positionXProperty.value()->isValueList() || positionYProperty.value()->isValueList())
1079 result.append(getLayeredShorthandValue(backgroundPositionShorthand()));
1081 result.append(positionXProperty.value()->cssText());
1083 result.append(positionYProperty.value()->cssText());
1085 if (positionXProperty.isImportant())
1086 result.appendLiteral(" !important");
1089 if (positionXPropertyIndex != -1) {
1092 result.append(propertyAt(positionXPropertyIndex).cssText());
1094 if (positionYPropertyIndex != -1) {
1097 result.append(propertyAt(positionYPropertyIndex).cssText());
1101 // FIXME: We need to do the same for background-repeat.
1102 if (repeatXPropertyIndex != -1 && repeatYPropertyIndex != -1 && propertyAt(repeatXPropertyIndex).isImportant() == propertyAt(repeatYPropertyIndex).isImportant()) {
1103 PropertyReference repeatXProperty = propertyAt(repeatXPropertyIndex);
1104 PropertyReference repeatYProperty = propertyAt(repeatYPropertyIndex);
1108 result.appendLiteral("background-repeat: ");
1109 if (repeatXProperty.value()->isValueList() || repeatYProperty.value()->isValueList())
1110 result.append(getLayeredShorthandValue(backgroundRepeatShorthand()));
1112 result.append(repeatXProperty.value()->cssText());
1114 result.append(repeatYProperty.value()->cssText());
1116 if (repeatXProperty.isImportant())
1117 result.appendLiteral(" !important");
1120 if (repeatXPropertyIndex != -1) {
1123 result.append(propertyAt(repeatXPropertyIndex).cssText());
1125 if (repeatYPropertyIndex != -1) {
1128 result.append(propertyAt(repeatYPropertyIndex).cssText());
1132 ASSERT(!numDecls ^ !result.isEmpty());
1133 return result.toString();
1136 bool StyleProperties::hasCSSOMWrapper() const
1138 return is<MutableStyleProperties>(*this) && downcast<MutableStyleProperties>(*this).m_cssomWrapper;
1141 void MutableStyleProperties::mergeAndOverrideOnConflict(const StyleProperties& other)
1143 unsigned size = other.propertyCount();
1144 for (unsigned i = 0; i < size; ++i)
1145 addParsedProperty(other.propertyAt(i).toCSSProperty());
1148 bool StyleProperties::traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const
1150 unsigned size = propertyCount();
1151 for (unsigned i = 0; i < size; ++i) {
1152 if (propertyAt(i).value()->traverseSubresources(handler))
1158 // This is the list of properties we want to copy in the copyBlockProperties() function.
1159 // It is the list of CSS properties that apply specially to block-level elements.
1160 static const CSSPropertyID blockProperties[] = {
1162 CSSPropertyOverflow, // This can be also be applied to replaced elements
1163 CSSPropertyWebkitAspectRatio,
1164 CSSPropertyColumnCount,
1165 CSSPropertyColumnGap,
1166 CSSPropertyColumnRuleColor,
1167 CSSPropertyColumnRuleStyle,
1168 CSSPropertyColumnRuleWidth,
1169 CSSPropertyWebkitColumnBreakBefore,
1170 CSSPropertyWebkitColumnBreakAfter,
1171 CSSPropertyWebkitColumnBreakInside,
1172 CSSPropertyColumnWidth,
1173 CSSPropertyPageBreakAfter,
1174 CSSPropertyPageBreakBefore,
1175 CSSPropertyPageBreakInside,
1176 #if ENABLE(CSS_REGIONS)
1177 CSSPropertyWebkitRegionBreakAfter,
1178 CSSPropertyWebkitRegionBreakBefore,
1179 CSSPropertyWebkitRegionBreakInside,
1181 CSSPropertyTextAlign,
1182 #if ENABLE(CSS3_TEXT)
1183 CSSPropertyWebkitTextAlignLast,
1184 CSSPropertyWebkitTextJustify,
1186 CSSPropertyTextIndent,
1190 void MutableStyleProperties::clear()
1192 m_propertyVector.clear();
1195 const unsigned numBlockProperties = WTF_ARRAY_LENGTH(blockProperties);
1197 Ref<MutableStyleProperties> StyleProperties::copyBlockProperties() const
1199 return copyPropertiesInSet(blockProperties, numBlockProperties);
1202 void MutableStyleProperties::removeBlockProperties()
1204 removePropertiesInSet(blockProperties, numBlockProperties);
1207 bool MutableStyleProperties::removePropertiesInSet(const CSSPropertyID* set, unsigned length)
1209 if (m_propertyVector.isEmpty())
1212 // FIXME: This is always used with static sets and in that case constructing the hash repeatedly is pretty pointless.
1213 HashSet<CSSPropertyID> toRemove;
1214 for (unsigned i = 0; i < length; ++i)
1215 toRemove.add(set[i]);
1217 return m_propertyVector.removeAllMatching([&toRemove] (const CSSProperty& property) {
1218 // Not quite sure if the isImportant test is needed but it matches the existing behavior.
1219 return !property.isImportant() && toRemove.contains(property.id());
1223 int ImmutableStyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
1225 // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
1226 // the compiler converting it to an int multiple times in the loop.
1227 uint16_t id = static_cast<uint16_t>(propertyID);
1228 for (int n = m_arraySize - 1 ; n >= 0; --n) {
1229 if (metadataArray()[n].m_propertyID == id)
1236 int MutableStyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
1238 // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
1239 // the compiler converting it to an int multiple times in the loop.
1240 uint16_t id = static_cast<uint16_t>(propertyID);
1241 for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) {
1242 if (m_propertyVector.at(n).metadata().m_propertyID == id)
1249 int ImmutableStyleProperties::findCustomPropertyIndex(const String& propertyName) const
1251 // Convert the propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
1252 // the compiler converting it to an int multiple times in the loop.
1253 for (int n = m_arraySize - 1 ; n >= 0; --n) {
1254 if (metadataArray()[n].m_propertyID == CSSPropertyCustom) {
1255 // We found a custom property. See if the name matches.
1256 if (!valueArray()[n])
1258 if (downcast<CSSCustomPropertyValue>(*valueArray()[n]).name() == propertyName)
1266 int MutableStyleProperties::findCustomPropertyIndex(const String& propertyName) const
1268 // Convert the propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
1269 // the compiler converting it to an int multiple times in the loop.
1270 for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) {
1271 if (m_propertyVector.at(n).metadata().m_propertyID == CSSPropertyCustom) {
1272 // We found a custom property. See if the name matches.
1273 if (!m_propertyVector.at(n).value())
1275 if (downcast<CSSCustomPropertyValue>(*m_propertyVector.at(n).value()).name() == propertyName)
1283 CSSProperty* MutableStyleProperties::findCSSPropertyWithID(CSSPropertyID propertyID)
1285 int foundPropertyIndex = findPropertyIndex(propertyID);
1286 if (foundPropertyIndex == -1)
1288 return &m_propertyVector.at(foundPropertyIndex);
1291 CSSProperty* MutableStyleProperties::findCustomCSSPropertyWithName(const String& propertyName)
1293 int foundPropertyIndex = findCustomPropertyIndex(propertyName);
1294 if (foundPropertyIndex == -1)
1296 return &m_propertyVector.at(foundPropertyIndex);
1299 bool StyleProperties::propertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const
1301 int foundPropertyIndex = findPropertyIndex(propertyID);
1302 if (foundPropertyIndex == -1)
1304 return propertyAt(foundPropertyIndex).value()->equals(*propertyValue);
1307 Ref<MutableStyleProperties> StyleProperties::mutableCopy() const
1309 return adoptRef(*new MutableStyleProperties(*this));
1312 Ref<MutableStyleProperties> StyleProperties::copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const
1314 Vector<CSSProperty, 256> list;
1315 list.reserveInitialCapacity(length);
1316 for (unsigned i = 0; i < length; ++i) {
1317 if (auto value = getPropertyCSSValueInternal(set[i]))
1318 list.uncheckedAppend(CSSProperty(set[i], WTFMove(value), false));
1320 return MutableStyleProperties::create(list.data(), list.size());
1323 PropertySetCSSStyleDeclaration* MutableStyleProperties::cssStyleDeclaration()
1325 return m_cssomWrapper.get();
1328 CSSStyleDeclaration* MutableStyleProperties::ensureCSSStyleDeclaration()
1330 if (m_cssomWrapper) {
1331 ASSERT(!static_cast<CSSStyleDeclaration*>(m_cssomWrapper.get())->parentRule());
1332 ASSERT(!m_cssomWrapper->parentElement());
1333 return m_cssomWrapper.get();
1335 m_cssomWrapper = std::make_unique<PropertySetCSSStyleDeclaration>(this);
1336 return m_cssomWrapper.get();
1339 CSSStyleDeclaration* MutableStyleProperties::ensureInlineCSSStyleDeclaration(StyledElement* parentElement)
1341 if (m_cssomWrapper) {
1342 ASSERT(m_cssomWrapper->parentElement() == parentElement);
1343 return m_cssomWrapper.get();
1345 m_cssomWrapper = std::make_unique<InlineCSSStyleDeclaration>(this, parentElement);
1346 return m_cssomWrapper.get();
1349 unsigned StyleProperties::averageSizeInBytes()
1351 // Please update this if the storage scheme changes so that this longer reflects the actual size.
1352 return sizeForImmutableStylePropertiesWithPropertyCount(4);
1355 // See the function above if you need to update this.
1356 struct SameSizeAsStyleProperties : public RefCounted<SameSizeAsStyleProperties> {
1359 COMPILE_ASSERT(sizeof(StyleProperties) == sizeof(SameSizeAsStyleProperties), style_property_set_should_stay_small);
1362 void StyleProperties::showStyle()
1364 fprintf(stderr, "%s\n", asText().ascii().data());
1368 Ref<MutableStyleProperties> MutableStyleProperties::create(CSSParserMode cssParserMode)
1370 return adoptRef(*new MutableStyleProperties(cssParserMode));
1373 Ref<MutableStyleProperties> MutableStyleProperties::create(const CSSProperty* properties, unsigned count)
1375 return adoptRef(*new MutableStyleProperties(properties, count));
1378 String StyleProperties::PropertyReference::cssName() const
1380 if (id() == CSSPropertyCustom)
1381 return downcast<CSSCustomPropertyValue>(*value()).name();
1382 return getPropertyNameString(id());
1385 String StyleProperties::PropertyReference::cssText() const
1387 StringBuilder result;
1388 result.append(cssName());
1389 result.appendLiteral(": ");
1390 result.append(m_value->cssText());
1392 result.appendLiteral(" !important");
1394 return result.toString();
1397 Ref<DeferredStyleProperties> DeferredStyleProperties::create(const CSSParserTokenRange& tokenRange, CSSDeferredParser& parser)
1399 return adoptRef(*new DeferredStyleProperties(tokenRange, parser));
1402 DeferredStyleProperties::DeferredStyleProperties(const CSSParserTokenRange& range, CSSDeferredParser& parser)
1403 : StylePropertiesBase(parser.mode(), DeferredPropertiesType)
1406 size_t length = range.end() - range.begin();
1407 m_tokens.reserveCapacity(length);
1408 m_tokens.append(range.begin(), length);
1411 DeferredStyleProperties::~DeferredStyleProperties()
1415 Ref<ImmutableStyleProperties> DeferredStyleProperties::parseDeferredProperties()
1417 return m_parser->parseDeclaration(m_tokens);
1420 } // namespace WebCore