Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / css / StylePropertySet.cpp
1 /*
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.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "config.h"
24 #include "core/css/StylePropertySet.h"
25
26 #include "core/StylePropertyShorthand.h"
27 #include "core/css/parser/BisonCSSParser.h"
28 #include "core/css/CSSValuePool.h"
29 #include "core/css/RuntimeCSSEnabled.h"
30 #include "core/css/StylePropertySerializer.h"
31 #include "core/css/StyleSheetContents.h"
32 #include "core/frame/UseCounter.h"
33 #include "platform/RuntimeEnabledFeatures.h"
34 #include "wtf/text/StringBuilder.h"
35
36 #ifndef NDEBUG
37 #include "wtf/text/CString.h"
38 #include <stdio.h>
39 #endif
40
41 namespace blink {
42
43 static size_t sizeForImmutableStylePropertySetWithPropertyCount(unsigned count)
44 {
45     return sizeof(ImmutableStylePropertySet) - sizeof(void*) + sizeof(CSSValue*) * count + sizeof(StylePropertyMetadata) * count;
46 }
47
48 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> ImmutableStylePropertySet::create(const CSSProperty* properties, unsigned count, CSSParserMode cssParserMode)
49 {
50     ASSERT(count <= MaxArraySize);
51 #if ENABLE(OILPAN)
52     void* slot = Heap::allocate<StylePropertySet>(sizeForImmutableStylePropertySetWithPropertyCount(count));
53 #else
54     void* slot = WTF::fastMalloc(sizeForImmutableStylePropertySetWithPropertyCount(count));
55 #endif // ENABLE(OILPAN)
56     return adoptRefWillBeNoop(new (slot) ImmutableStylePropertySet(properties, count, cssParserMode));
57 }
58
59 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> StylePropertySet::immutableCopyIfNeeded() const
60 {
61     if (!isMutable())
62         return toImmutableStylePropertySet(const_cast<StylePropertySet*>(this));
63     const MutableStylePropertySet* mutableThis = toMutableStylePropertySet(this);
64     return ImmutableStylePropertySet::create(mutableThis->m_propertyVector.data(), mutableThis->m_propertyVector.size(), cssParserMode());
65 }
66
67 MutableStylePropertySet::MutableStylePropertySet(CSSParserMode cssParserMode)
68     : StylePropertySet(cssParserMode)
69 {
70 }
71
72 MutableStylePropertySet::MutableStylePropertySet(const CSSProperty* properties, unsigned length)
73     : StylePropertySet(HTMLStandardMode)
74 {
75     m_propertyVector.reserveInitialCapacity(length);
76     for (unsigned i = 0; i < length; ++i)
77         m_propertyVector.uncheckedAppend(properties[i]);
78 }
79
80 ImmutableStylePropertySet::ImmutableStylePropertySet(const CSSProperty* properties, unsigned length, CSSParserMode cssParserMode)
81     : StylePropertySet(cssParserMode, length)
82 {
83     StylePropertyMetadata* metadataArray = const_cast<StylePropertyMetadata*>(this->metadataArray());
84     RawPtrWillBeMember<CSSValue>* valueArray = const_cast<RawPtrWillBeMember<CSSValue>*>(this->valueArray());
85     for (unsigned i = 0; i < m_arraySize; ++i) {
86         metadataArray[i] = properties[i].metadata();
87         valueArray[i] = properties[i].value();
88 #if !ENABLE(OILPAN)
89         valueArray[i]->ref();
90 #endif
91     }
92 }
93
94 ImmutableStylePropertySet::~ImmutableStylePropertySet()
95 {
96 #if !ENABLE(OILPAN)
97     RawPtrWillBeMember<CSSValue>* valueArray = const_cast<RawPtrWillBeMember<CSSValue>*>(this->valueArray());
98     for (unsigned i = 0; i < m_arraySize; ++i)
99         valueArray[i]->deref();
100 #endif
101 }
102
103 int ImmutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const
104 {
105     // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
106     // the compiler converting it to an int multiple times in the loop.
107     uint16_t id = static_cast<uint16_t>(propertyID);
108     for (int n = m_arraySize - 1 ; n >= 0; --n) {
109         if (metadataArray()[n].m_propertyID == id) {
110             // Only enabled or internal properties should be part of the style.
111             ASSERT(RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID) || isInternalProperty(propertyID));
112             return n;
113         }
114     }
115
116     return -1;
117 }
118
119 void ImmutableStylePropertySet::traceAfterDispatch(Visitor* visitor)
120 {
121     const RawPtrWillBeMember<CSSValue>* values = valueArray();
122     for (unsigned i = 0; i < m_arraySize; i++)
123         visitor->trace(values[i]);
124     StylePropertySet::traceAfterDispatch(visitor);
125 }
126
127 MutableStylePropertySet::MutableStylePropertySet(const StylePropertySet& other)
128     : StylePropertySet(other.cssParserMode())
129 {
130     if (other.isMutable()) {
131         m_propertyVector = toMutableStylePropertySet(other).m_propertyVector;
132     } else {
133         m_propertyVector.reserveInitialCapacity(other.propertyCount());
134         for (unsigned i = 0; i < other.propertyCount(); ++i)
135             m_propertyVector.uncheckedAppend(other.propertyAt(i).toCSSProperty());
136     }
137 }
138
139 String StylePropertySet::getPropertyValue(CSSPropertyID propertyID) const
140 {
141     RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(propertyID);
142     if (value)
143         return value->cssText();
144
145     return StylePropertySerializer(*this).getPropertyValue(propertyID);
146 }
147
148 PassRefPtrWillBeRawPtr<CSSValue> StylePropertySet::getPropertyCSSValue(CSSPropertyID propertyID) const
149 {
150     int foundPropertyIndex = findPropertyIndex(propertyID);
151     if (foundPropertyIndex == -1)
152         return nullptr;
153     return propertyAt(foundPropertyIndex).value();
154 }
155
156 void StylePropertySet::trace(Visitor* visitor)
157 {
158     if (m_isMutable)
159         toMutableStylePropertySet(this)->traceAfterDispatch(visitor);
160     else
161         toImmutableStylePropertySet(this)->traceAfterDispatch(visitor);
162 }
163
164 #if ENABLE(OILPAN)
165 void StylePropertySet::finalizeGarbageCollectedObject()
166 {
167     if (m_isMutable)
168         toMutableStylePropertySet(this)->~MutableStylePropertySet();
169     else
170         toImmutableStylePropertySet(this)->~ImmutableStylePropertySet();
171 }
172 #endif
173
174 bool MutableStylePropertySet::removeShorthandProperty(CSSPropertyID propertyID)
175 {
176     StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
177     if (!shorthand.length())
178         return false;
179
180     bool ret = removePropertiesInSet(shorthand.properties(), shorthand.length());
181
182     CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(propertyID);
183     if (prefixingVariant == propertyID)
184         return ret;
185
186     StylePropertyShorthand shorthandPrefixingVariant = shorthandForProperty(prefixingVariant);
187     return removePropertiesInSet(shorthandPrefixingVariant.properties(), shorthandPrefixingVariant.length());
188 }
189
190 bool MutableStylePropertySet::removeProperty(CSSPropertyID propertyID, String* returnText)
191 {
192     if (removeShorthandProperty(propertyID)) {
193         // FIXME: Return an equivalent shorthand when possible.
194         if (returnText)
195             *returnText = "";
196         return true;
197     }
198
199     int foundPropertyIndex = findPropertyIndex(propertyID);
200     if (foundPropertyIndex == -1) {
201         if (returnText)
202             *returnText = "";
203         return false;
204     }
205
206     if (returnText)
207         *returnText = propertyAt(foundPropertyIndex).value()->cssText();
208
209     // A more efficient removal strategy would involve marking entries as empty
210     // and sweeping them when the vector grows too big.
211     m_propertyVector.remove(foundPropertyIndex);
212
213     removePrefixedOrUnprefixedProperty(propertyID);
214
215     return true;
216 }
217
218 void MutableStylePropertySet::removePrefixedOrUnprefixedProperty(CSSPropertyID propertyID)
219 {
220     int foundPropertyIndex = findPropertyIndex(prefixingVariantForPropertyId(propertyID));
221     if (foundPropertyIndex == -1)
222         return;
223     m_propertyVector.remove(foundPropertyIndex);
224 }
225
226 bool StylePropertySet::propertyIsImportant(CSSPropertyID propertyID) const
227 {
228     int foundPropertyIndex = findPropertyIndex(propertyID);
229     if (foundPropertyIndex != -1)
230         return propertyAt(foundPropertyIndex).isImportant();
231
232     StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
233     if (!shorthand.length())
234         return false;
235
236     for (unsigned i = 0; i < shorthand.length(); ++i) {
237         if (!propertyIsImportant(shorthand.properties()[i]))
238             return false;
239     }
240     return true;
241 }
242
243 CSSPropertyID StylePropertySet::getPropertyShorthand(CSSPropertyID propertyID) const
244 {
245     int foundPropertyIndex = findPropertyIndex(propertyID);
246     if (foundPropertyIndex == -1)
247         return CSSPropertyInvalid;
248     return propertyAt(foundPropertyIndex).shorthandID();
249 }
250
251 bool StylePropertySet::isPropertyImplicit(CSSPropertyID propertyID) const
252 {
253     int foundPropertyIndex = findPropertyIndex(propertyID);
254     if (foundPropertyIndex == -1)
255         return false;
256     return propertyAt(foundPropertyIndex).isImplicit();
257 }
258
259 bool MutableStylePropertySet::setProperty(CSSPropertyID propertyID, const String& value, bool important, StyleSheetContents* contextStyleSheet)
260 {
261     // Setting the value to an empty string just removes the property in both IE and Gecko.
262     // Setting it to null seems to produce less consistent results, but we treat it just the same.
263     if (value.isEmpty())
264         return removeProperty(propertyID);
265
266     // When replacing an existing property value, this moves the property to the end of the list.
267     // Firefox preserves the position, and MSIE moves the property to the beginning.
268     return BisonCSSParser::parseValue(this, propertyID, value, important, cssParserMode(), contextStyleSheet);
269 }
270
271 void MutableStylePropertySet::setProperty(CSSPropertyID propertyID, PassRefPtrWillBeRawPtr<CSSValue> prpValue, bool important)
272 {
273     StylePropertyShorthand shorthand = shorthandForProperty(propertyID);
274     if (!shorthand.length()) {
275         setProperty(CSSProperty(propertyID, prpValue, important));
276         return;
277     }
278
279     removePropertiesInSet(shorthand.properties(), shorthand.length());
280
281     RefPtrWillBeRawPtr<CSSValue> value = prpValue;
282     for (unsigned i = 0; i < shorthand.length(); ++i)
283         m_propertyVector.append(CSSProperty(shorthand.properties()[i], value, important));
284 }
285
286 void MutableStylePropertySet::setProperty(const CSSProperty& property, CSSProperty* slot)
287 {
288     if (!removeShorthandProperty(property.id())) {
289         CSSProperty* toReplace = slot ? slot : findCSSPropertyWithID(property.id());
290         if (toReplace) {
291             *toReplace = property;
292             setPrefixingVariantProperty(property);
293             return;
294         }
295     }
296     appendPrefixingVariantProperty(property);
297 }
298
299 unsigned getIndexInShorthandVectorForPrefixingVariant(const CSSProperty& property, CSSPropertyID prefixingVariant)
300 {
301     if (!property.isSetFromShorthand())
302         return 0;
303
304     CSSPropertyID prefixedShorthand = prefixingVariantForPropertyId(property.shorthandID());
305     Vector<StylePropertyShorthand, 4> shorthands;
306     getMatchingShorthandsForLonghand(prefixingVariant, &shorthands);
307     return indexOfShorthandForLonghand(prefixedShorthand, shorthands);
308 }
309
310 void MutableStylePropertySet::appendPrefixingVariantProperty(const CSSProperty& property)
311 {
312     m_propertyVector.append(property);
313     CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(property.id());
314     if (prefixingVariant == property.id())
315         return;
316
317     m_propertyVector.append(CSSProperty(prefixingVariant, property.value(), property.isImportant(), property.isSetFromShorthand(), getIndexInShorthandVectorForPrefixingVariant(property, prefixingVariant), property.metadata().m_implicit));
318 }
319
320 void MutableStylePropertySet::setPrefixingVariantProperty(const CSSProperty& property)
321 {
322     CSSPropertyID prefixingVariant = prefixingVariantForPropertyId(property.id());
323     CSSProperty* toReplace = findCSSPropertyWithID(prefixingVariant);
324     if (toReplace && prefixingVariant != property.id())
325         *toReplace = CSSProperty(prefixingVariant, property.value(), property.isImportant(), property.isSetFromShorthand(), getIndexInShorthandVectorForPrefixingVariant(property, prefixingVariant), property.metadata().m_implicit);
326 }
327
328 bool MutableStylePropertySet::setProperty(CSSPropertyID propertyID, CSSValueID identifier, bool important)
329 {
330     setProperty(CSSProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important));
331     return true;
332 }
333
334 bool MutableStylePropertySet::setProperty(CSSPropertyID propertyID, CSSPropertyID identifier, bool important)
335 {
336     setProperty(CSSProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important));
337     return true;
338 }
339
340 void MutableStylePropertySet::parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet)
341 {
342     m_propertyVector.clear();
343
344     CSSParserContext context(cssParserMode(), UseCounter::getFrom(contextStyleSheet));
345     if (contextStyleSheet) {
346         context = contextStyleSheet->parserContext();
347         context.setMode(cssParserMode());
348     }
349
350     BisonCSSParser parser(context);
351     parser.parseDeclaration(this, styleDeclaration, 0, contextStyleSheet);
352 }
353
354 void MutableStylePropertySet::addParsedProperties(const WillBeHeapVector<CSSProperty, 256>& properties)
355 {
356     m_propertyVector.reserveCapacity(m_propertyVector.size() + properties.size());
357     for (unsigned i = 0; i < properties.size(); ++i)
358         addParsedProperty(properties[i]);
359 }
360
361 void MutableStylePropertySet::addParsedProperty(const CSSProperty& property)
362 {
363     // Only add properties that have no !important counterpart present
364     if (!propertyIsImportant(property.id()) || property.isImportant())
365         setProperty(property);
366 }
367
368 String StylePropertySet::asText() const
369 {
370     return StylePropertySerializer(*this).asText();
371 }
372
373 void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other)
374 {
375     unsigned size = other->propertyCount();
376     for (unsigned n = 0; n < size; ++n) {
377         PropertyReference toMerge = other->propertyAt(n);
378         CSSProperty* old = findCSSPropertyWithID(toMerge.id());
379         if (old)
380             setProperty(toMerge.toCSSProperty(), old);
381         else
382             appendPrefixingVariantProperty(toMerge.toCSSProperty());
383     }
384 }
385
386 bool StylePropertySet::hasFailedOrCanceledSubresources() const
387 {
388     unsigned size = propertyCount();
389     for (unsigned i = 0; i < size; ++i) {
390         if (propertyAt(i).value()->hasFailedOrCanceledSubresources())
391             return true;
392     }
393     return false;
394 }
395
396 // This is the list of properties we want to copy in the copyBlockProperties() function.
397 // It is the list of CSS properties that apply specially to block-level elements.
398 static const CSSPropertyID staticBlockProperties[] = {
399     CSSPropertyOrphans,
400     CSSPropertyOverflow, // This can be also be applied to replaced elements
401     CSSPropertyWebkitAspectRatio,
402     CSSPropertyWebkitColumnCount,
403     CSSPropertyWebkitColumnGap,
404     CSSPropertyWebkitColumnRuleColor,
405     CSSPropertyWebkitColumnRuleStyle,
406     CSSPropertyWebkitColumnRuleWidth,
407     CSSPropertyWebkitColumnBreakBefore,
408     CSSPropertyWebkitColumnBreakAfter,
409     CSSPropertyWebkitColumnBreakInside,
410     CSSPropertyWebkitColumnWidth,
411     CSSPropertyPageBreakAfter,
412     CSSPropertyPageBreakBefore,
413     CSSPropertyPageBreakInside,
414     CSSPropertyTextAlign,
415     CSSPropertyTextAlignLast,
416     CSSPropertyTextIndent,
417     CSSPropertyTextJustify,
418     CSSPropertyWidows
419 };
420
421 static const Vector<CSSPropertyID>& blockProperties()
422 {
423     DEFINE_STATIC_LOCAL(Vector<CSSPropertyID>, properties, ());
424     if (properties.isEmpty())
425         RuntimeCSSEnabled::filterEnabledCSSPropertiesIntoVector(staticBlockProperties, WTF_ARRAY_LENGTH(staticBlockProperties), properties);
426     return properties;
427 }
428
429 void MutableStylePropertySet::clear()
430 {
431     m_propertyVector.clear();
432 }
433
434 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyBlockProperties() const
435 {
436     return copyPropertiesInSet(blockProperties());
437 }
438
439 void MutableStylePropertySet::removeBlockProperties()
440 {
441     removePropertiesInSet(blockProperties().data(), blockProperties().size());
442 }
443
444 inline bool containsId(const CSSPropertyID* set, unsigned length, CSSPropertyID id)
445 {
446     for (unsigned i = 0; i < length; ++i) {
447         if (set[i] == id)
448             return true;
449     }
450     return false;
451 }
452
453 bool MutableStylePropertySet::removePropertiesInSet(const CSSPropertyID* set, unsigned length)
454 {
455     if (m_propertyVector.isEmpty())
456         return false;
457
458     WillBeHeapVector<CSSProperty> newProperties;
459     newProperties.reserveInitialCapacity(m_propertyVector.size());
460
461     unsigned initialSize = m_propertyVector.size();
462     const CSSProperty* properties = m_propertyVector.data();
463     for (unsigned n = 0; n < initialSize; ++n) {
464         const CSSProperty& property = properties[n];
465         // Not quite sure if the isImportant test is needed but it matches the existing behavior.
466         if (!property.isImportant() && containsId(set, length, property.id()))
467             continue;
468         newProperties.append(property);
469     }
470
471     m_propertyVector = newProperties;
472     return initialSize != m_propertyVector.size();
473 }
474
475 CSSProperty* MutableStylePropertySet::findCSSPropertyWithID(CSSPropertyID propertyID)
476 {
477     int foundPropertyIndex = findPropertyIndex(propertyID);
478     if (foundPropertyIndex == -1)
479         return 0;
480     return &m_propertyVector.at(foundPropertyIndex);
481 }
482
483 bool StylePropertySet::propertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const
484 {
485     int foundPropertyIndex = findPropertyIndex(propertyID);
486     if (foundPropertyIndex == -1)
487         return false;
488     return propertyAt(foundPropertyIndex).value()->equals(*propertyValue);
489 }
490
491 void MutableStylePropertySet::removeEquivalentProperties(const StylePropertySet* style)
492 {
493     Vector<CSSPropertyID> propertiesToRemove;
494     unsigned size = m_propertyVector.size();
495     for (unsigned i = 0; i < size; ++i) {
496         PropertyReference property = propertyAt(i);
497         if (style->propertyMatches(property.id(), property.value()))
498             propertiesToRemove.append(property.id());
499     }
500     // FIXME: This should use mass removal.
501     for (unsigned i = 0; i < propertiesToRemove.size(); ++i)
502         removeProperty(propertiesToRemove[i]);
503 }
504
505 void MutableStylePropertySet::removeEquivalentProperties(const CSSStyleDeclaration* style)
506 {
507     Vector<CSSPropertyID> propertiesToRemove;
508     unsigned size = m_propertyVector.size();
509     for (unsigned i = 0; i < size; ++i) {
510         PropertyReference property = propertyAt(i);
511         if (style->cssPropertyMatches(property.id(), property.value()))
512             propertiesToRemove.append(property.id());
513     }
514     // FIXME: This should use mass removal.
515     for (unsigned i = 0; i < propertiesToRemove.size(); ++i)
516         removeProperty(propertiesToRemove[i]);
517 }
518
519 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::mutableCopy() const
520 {
521     return adoptRefWillBeNoop(new MutableStylePropertySet(*this));
522 }
523
524 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const
525 {
526     WillBeHeapVector<CSSProperty, 256> list;
527     list.reserveInitialCapacity(properties.size());
528     for (unsigned i = 0; i < properties.size(); ++i) {
529         RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(properties[i]);
530         if (value)
531             list.append(CSSProperty(properties[i], value.release(), false));
532     }
533     return MutableStylePropertySet::create(list.data(), list.size());
534 }
535
536 CSSStyleDeclaration* MutableStylePropertySet::ensureCSSStyleDeclaration()
537 {
538     // FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a
539     // style property set.
540     if (m_cssomWrapper) {
541         ASSERT(!static_cast<CSSStyleDeclaration*>(m_cssomWrapper.get())->parentRule());
542         ASSERT(!m_cssomWrapper->parentElement());
543         return m_cssomWrapper.get();
544     }
545     m_cssomWrapper = adoptPtrWillBeNoop(new PropertySetCSSStyleDeclaration(*this));
546     return m_cssomWrapper.get();
547 }
548
549 int MutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const
550 {
551     // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid
552     // the compiler converting it to an int multiple times in the loop.
553     uint16_t id = static_cast<uint16_t>(propertyID);
554     const CSSProperty* properties = m_propertyVector.data();
555     for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) {
556         if (properties[n].metadata().m_propertyID == id) {
557             // Only enabled or internal properties should be part of the style.
558             ASSERT(RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID) || isInternalProperty(propertyID));
559             return n;
560         }
561     }
562
563     return -1;
564 }
565
566 void MutableStylePropertySet::traceAfterDispatch(Visitor* visitor)
567 {
568     visitor->trace(m_cssomWrapper);
569     visitor->trace(m_propertyVector);
570     StylePropertySet::traceAfterDispatch(visitor);
571 }
572
573 unsigned StylePropertySet::averageSizeInBytes()
574 {
575     // Please update this if the storage scheme changes so that this longer reflects the actual size.
576     return sizeForImmutableStylePropertySetWithPropertyCount(4);
577 }
578
579 // See the function above if you need to update this.
580 struct SameSizeAsStylePropertySet : public RefCountedWillBeGarbageCollectedFinalized<SameSizeAsStylePropertySet> {
581     unsigned bitfield;
582 };
583 COMPILE_ASSERT(sizeof(StylePropertySet) == sizeof(SameSizeAsStylePropertySet), style_property_set_should_stay_small);
584
585 #ifndef NDEBUG
586 void StylePropertySet::showStyle()
587 {
588     fprintf(stderr, "%s\n", asText().ascii().data());
589 }
590 #endif
591
592 PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(CSSParserMode cssParserMode)
593 {
594     return adoptRefWillBeNoop(new MutableStylePropertySet(cssParserMode));
595 }
596
597 PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(const CSSProperty* properties, unsigned count)
598 {
599     return adoptRefWillBeNoop(new MutableStylePropertySet(properties, count));
600 }
601
602 String StylePropertySet::PropertyReference::cssName() const
603 {
604     return getPropertyNameString(id());
605 }
606
607 String StylePropertySet::PropertyReference::cssText() const
608 {
609     StringBuilder result;
610     result.append(cssName());
611     result.appendLiteral(": ");
612     result.append(propertyValue()->cssText());
613     if (isImportant())
614         result.appendLiteral(" !important");
615     result.append(';');
616     return result.toString();
617 }
618
619
620 } // namespace blink