1 /* 2 * (C) 1999-2003 Lars Knoll (knoll (at) 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/CSSPropertyMetadata.h" 28 #include "core/css/CSSValuePool.h" 29 #include "core/css/StylePropertySerializer.h" 30 #include "core/css/StyleSheetContents.h" 31 #include "core/css/parser/CSSParser.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(CSSPropertyMetadata::isEnabledProperty(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 CSSParser::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 void MutableStylePropertySet::parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet) 335 { 336 m_propertyVector.clear(); 337 338 CSSParserContext context(cssParserMode(), UseCounter::getFrom(contextStyleSheet)); 339 if (contextStyleSheet) { 340 context = contextStyleSheet->parserContext(); 341 context.setMode(cssParserMode()); 342 } 343 344 CSSParser parser(context); 345 parser.parseDeclaration(this, styleDeclaration, 0, contextStyleSheet); 346 } 347 348 void MutableStylePropertySet::addParsedProperties(const WillBeHeapVector<CSSProperty, 256>& properties) 349 { 350 m_propertyVector.reserveCapacity(m_propertyVector.size() + properties.size()); 351 for (unsigned i = 0; i < properties.size(); ++i) 352 addParsedProperty(properties[i]); 353 } 354 355 void MutableStylePropertySet::addParsedProperty(const CSSProperty& property) 356 { 357 // Only add properties that have no !important counterpart present 358 if (!propertyIsImportant(property.id()) || property.isImportant()) 359 setProperty(property); 360 } 361 362 String StylePropertySet::asText() const 363 { 364 return StylePropertySerializer(*this).asText(); 365 } 366 367 void MutableStylePropertySet::mergeAndOverrideOnConflict(const StylePropertySet* other) 368 { 369 unsigned size = other->propertyCount(); 370 for (unsigned n = 0; n < size; ++n) { 371 PropertyReference toMerge = other->propertyAt(n); 372 CSSProperty* old = findCSSPropertyWithID(toMerge.id()); 373 if (old) 374 setProperty(toMerge.toCSSProperty(), old); 375 else 376 appendPrefixingVariantProperty(toMerge.toCSSProperty()); 377 } 378 } 379 380 bool StylePropertySet::hasFailedOrCanceledSubresources() const 381 { 382 unsigned size = propertyCount(); 383 for (unsigned i = 0; i < size; ++i) { 384 if (propertyAt(i).value()->hasFailedOrCanceledSubresources()) 385 return true; 386 } 387 return false; 388 } 389 390 // This is the list of properties we want to copy in the copyBlockProperties() function. 391 // It is the list of CSS properties that apply specially to block-level elements. 392 static const CSSPropertyID staticBlockProperties[] = { 393 CSSPropertyOrphans, 394 CSSPropertyOverflow, // This can be also be applied to replaced elements 395 CSSPropertyWebkitAspectRatio, 396 CSSPropertyWebkitColumnCount, 397 CSSPropertyWebkitColumnGap, 398 CSSPropertyWebkitColumnRuleColor, 399 CSSPropertyWebkitColumnRuleStyle, 400 CSSPropertyWebkitColumnRuleWidth, 401 CSSPropertyWebkitColumnBreakBefore, 402 CSSPropertyWebkitColumnBreakAfter, 403 CSSPropertyWebkitColumnBreakInside, 404 CSSPropertyWebkitColumnWidth, 405 CSSPropertyPageBreakAfter, 406 CSSPropertyPageBreakBefore, 407 CSSPropertyPageBreakInside, 408 CSSPropertyTextAlign, 409 CSSPropertyTextAlignLast, 410 CSSPropertyTextIndent, 411 CSSPropertyTextJustify, 412 CSSPropertyWidows 413 }; 414 415 static const Vector<CSSPropertyID>& blockProperties() 416 { 417 DEFINE_STATIC_LOCAL(Vector<CSSPropertyID>, properties, ()); 418 if (properties.isEmpty()) 419 CSSPropertyMetadata::filterEnabledCSSPropertiesIntoVector(staticBlockProperties, WTF_ARRAY_LENGTH(staticBlockProperties), properties); 420 return properties; 421 } 422 423 void MutableStylePropertySet::clear() 424 { 425 m_propertyVector.clear(); 426 } 427 428 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyBlockProperties() const 429 { 430 return copyPropertiesInSet(blockProperties()); 431 } 432 433 void MutableStylePropertySet::removeBlockProperties() 434 { 435 removePropertiesInSet(blockProperties().data(), blockProperties().size()); 436 } 437 438 inline bool containsId(const CSSPropertyID* set, unsigned length, CSSPropertyID id) 439 { 440 for (unsigned i = 0; i < length; ++i) { 441 if (set[i] == id) 442 return true; 443 } 444 return false; 445 } 446 447 bool MutableStylePropertySet::removePropertiesInSet(const CSSPropertyID* set, unsigned length) 448 { 449 if (m_propertyVector.isEmpty()) 450 return false; 451 452 WillBeHeapVector<CSSProperty> newProperties; 453 newProperties.reserveInitialCapacity(m_propertyVector.size()); 454 455 unsigned initialSize = m_propertyVector.size(); 456 const CSSProperty* properties = m_propertyVector.data(); 457 for (unsigned n = 0; n < initialSize; ++n) { 458 const CSSProperty& property = properties[n]; 459 // Not quite sure if the isImportant test is needed but it matches the existing behavior. 460 if (!property.isImportant() && containsId(set, length, property.id())) 461 continue; 462 newProperties.append(property); 463 } 464 465 m_propertyVector = newProperties; 466 return initialSize != m_propertyVector.size(); 467 } 468 469 CSSProperty* MutableStylePropertySet::findCSSPropertyWithID(CSSPropertyID propertyID) 470 { 471 int foundPropertyIndex = findPropertyIndex(propertyID); 472 if (foundPropertyIndex == -1) 473 return 0; 474 return &m_propertyVector.at(foundPropertyIndex); 475 } 476 477 bool StylePropertySet::propertyMatches(CSSPropertyID propertyID, const CSSValue* propertyValue) const 478 { 479 int foundPropertyIndex = findPropertyIndex(propertyID); 480 if (foundPropertyIndex == -1) 481 return false; 482 return propertyAt(foundPropertyIndex).value()->equals(*propertyValue); 483 } 484 485 void MutableStylePropertySet::removeEquivalentProperties(const StylePropertySet* style) 486 { 487 Vector<CSSPropertyID> propertiesToRemove; 488 unsigned size = m_propertyVector.size(); 489 for (unsigned i = 0; i < size; ++i) { 490 PropertyReference property = propertyAt(i); 491 if (style->propertyMatches(property.id(), property.value())) 492 propertiesToRemove.append(property.id()); 493 } 494 // FIXME: This should use mass removal. 495 for (unsigned i = 0; i < propertiesToRemove.size(); ++i) 496 removeProperty(propertiesToRemove[i]); 497 } 498 499 void MutableStylePropertySet::removeEquivalentProperties(const CSSStyleDeclaration* style) 500 { 501 Vector<CSSPropertyID> propertiesToRemove; 502 unsigned size = m_propertyVector.size(); 503 for (unsigned i = 0; i < size; ++i) { 504 PropertyReference property = propertyAt(i); 505 if (style->cssPropertyMatches(property.id(), property.value())) 506 propertiesToRemove.append(property.id()); 507 } 508 // FIXME: This should use mass removal. 509 for (unsigned i = 0; i < propertiesToRemove.size(); ++i) 510 removeProperty(propertiesToRemove[i]); 511 } 512 513 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::mutableCopy() const 514 { 515 return adoptRefWillBeNoop(new MutableStylePropertySet(*this)); 516 } 517 518 PassRefPtrWillBeRawPtr<MutableStylePropertySet> StylePropertySet::copyPropertiesInSet(const Vector<CSSPropertyID>& properties) const 519 { 520 WillBeHeapVector<CSSProperty, 256> list; 521 list.reserveInitialCapacity(properties.size()); 522 for (unsigned i = 0; i < properties.size(); ++i) { 523 RefPtrWillBeRawPtr<CSSValue> value = getPropertyCSSValue(properties[i]); 524 if (value) 525 list.append(CSSProperty(properties[i], value.release(), false)); 526 } 527 return MutableStylePropertySet::create(list.data(), list.size()); 528 } 529 530 CSSStyleDeclaration* MutableStylePropertySet::ensureCSSStyleDeclaration() 531 { 532 // FIXME: get rid of this weirdness of a CSSStyleDeclaration inside of a 533 // style property set. 534 if (m_cssomWrapper) { 535 ASSERT(!static_cast<CSSStyleDeclaration*>(m_cssomWrapper.get())->parentRule()); 536 ASSERT(!m_cssomWrapper->parentElement()); 537 return m_cssomWrapper.get(); 538 } 539 m_cssomWrapper = adoptPtrWillBeNoop(new PropertySetCSSStyleDeclaration(*this)); 540 return m_cssomWrapper.get(); 541 } 542 543 int MutableStylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const 544 { 545 // Convert here propertyID into an uint16_t to compare it with the metadata's m_propertyID to avoid 546 // the compiler converting it to an int multiple times in the loop. 547 uint16_t id = static_cast<uint16_t>(propertyID); 548 const CSSProperty* properties = m_propertyVector.data(); 549 for (int n = m_propertyVector.size() - 1 ; n >= 0; --n) { 550 if (properties[n].metadata().m_propertyID == id) { 551 // Only enabled or internal properties should be part of the style. 552 ASSERT(CSSPropertyMetadata::isEnabledProperty(propertyID) || isInternalProperty(propertyID)); 553 return n; 554 } 555 } 556 557 return -1; 558 } 559 560 void MutableStylePropertySet::traceAfterDispatch(Visitor* visitor) 561 { 562 visitor->trace(m_cssomWrapper); 563 visitor->trace(m_propertyVector); 564 StylePropertySet::traceAfterDispatch(visitor); 565 } 566 567 unsigned StylePropertySet::averageSizeInBytes() 568 { 569 // Please update this if the storage scheme changes so that this longer reflects the actual size. 570 return sizeForImmutableStylePropertySetWithPropertyCount(4); 571 } 572 573 // See the function above if you need to update this. 574 struct SameSizeAsStylePropertySet : public RefCountedWillBeGarbageCollectedFinalized<SameSizeAsStylePropertySet> { 575 unsigned bitfield; 576 }; 577 COMPILE_ASSERT(sizeof(StylePropertySet) == sizeof(SameSizeAsStylePropertySet), style_property_set_should_stay_small); 578 579 #ifndef NDEBUG 580 void StylePropertySet::showStyle() 581 { 582 fprintf(stderr, "%s\n", asText().ascii().data()); 583 } 584 #endif 585 586 PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(CSSParserMode cssParserMode) 587 { 588 return adoptRefWillBeNoop(new MutableStylePropertySet(cssParserMode)); 589 } 590 591 PassRefPtrWillBeRawPtr<MutableStylePropertySet> MutableStylePropertySet::create(const CSSProperty* properties, unsigned count) 592 { 593 return adoptRefWillBeNoop(new MutableStylePropertySet(properties, count)); 594 } 595 596 String StylePropertySet::PropertyReference::cssName() const 597 { 598 return getPropertyNameString(id()); 599 } 600 601 String StylePropertySet::PropertyReference::cssText() const 602 { 603 StringBuilder result; 604 result.append(cssName()); 605 result.appendLiteral(": "); 606 result.append(propertyValue()->cssText()); 607 if (isImportant()) 608 result.appendLiteral(" !important"); 609 result.append(';'); 610 return result.toString(); 611 } 612 613 614 } // namespace blink 615