1 /* 2 * (C) 1999-2003 Lars Knoll (knoll (at) kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2008, 2012 Apple Inc. All rights reserved. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Library General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Library General Public License for more details. 14 * 15 * You should have received a copy of the GNU Library General Public License 16 * along with this library; see the file COPYING.LIB. If not, write to 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 * Boston, MA 02110-1301, USA. 19 */ 20 21 #ifndef StylePropertySet_h 22 #define StylePropertySet_h 23 24 #include "core/CSSPropertyNames.h" 25 #include "core/css/CSSParserMode.h" 26 #include "core/css/CSSPrimitiveValue.h" 27 #include "core/css/CSSProperty.h" 28 #include "core/css/PropertySetCSSStyleDeclaration.h" 29 #include "wtf/ListHashSet.h" 30 #include "wtf/Vector.h" 31 #include "wtf/text/WTFString.h" 32 33 namespace WebCore { 34 35 class CSSRule; 36 class CSSStyleDeclaration; 37 class Element; 38 class ImmutableStylePropertySet; 39 class KURL; 40 class MutableStylePropertySet; 41 class StylePropertyShorthand; 42 class StyleSheetContents; 43 44 class StylePropertySet : public RefCountedWillBeRefCountedGarbageCollected<StylePropertySet> { 45 friend class PropertyReference; 46 public: 47 48 #if ENABLE(OILPAN) 49 // When oilpan is enabled override the finalize method to dispatch to the subclasses' 50 // destructor. This can be removed once the MutableStylePropertySet's OwnPtr is moved 51 // to the heap. 52 void finalizeGarbageCollectedObject(); 53 #else 54 // Override RefCounted's deref() to ensure operator delete is called on 55 // the appropriate subclass type. 56 void deref(); 57 #endif 58 59 class PropertyReference { 60 public: 61 PropertyReference(const StylePropertySet& propertySet, unsigned index) 62 : m_propertySet(propertySet) 63 , m_index(index) 64 { 65 } 66 67 CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); } 68 CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); } 69 70 bool isImportant() const { return propertyMetadata().m_important; } 71 bool isInherited() const { return propertyMetadata().m_inherited; } 72 bool isImplicit() const { return propertyMetadata().m_implicit; } 73 74 String cssName() const; 75 String cssText() const; 76 77 const CSSValue* value() const { return propertyValue(); } 78 // FIXME: We should try to remove this mutable overload. 79 CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); } 80 81 // FIXME: Remove this. 82 CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); } 83 84 const StylePropertyMetadata& propertyMetadata() const; 85 86 private: 87 const CSSValue* propertyValue() const; 88 89 const StylePropertySet& m_propertySet; 90 unsigned m_index; 91 }; 92 93 unsigned propertyCount() const; 94 bool isEmpty() const; 95 PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } 96 int findPropertyIndex(CSSPropertyID) const; 97 98 PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; 99 String getPropertyValue(CSSPropertyID) const; 100 101 bool propertyIsImportant(CSSPropertyID) const; 102 CSSPropertyID getPropertyShorthand(CSSPropertyID) const; 103 bool isPropertyImplicit(CSSPropertyID) const; 104 105 PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyBlockProperties() const; 106 107 CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); } 108 109 PassRefPtrWillBeRawPtr<MutableStylePropertySet> mutableCopy() const; 110 PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const; 111 112 PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; 113 114 String asText() const; 115 116 bool isMutable() const { return m_isMutable; } 117 118 bool hasFailedOrCanceledSubresources() const; 119 120 static unsigned averageSizeInBytes(); 121 122 #ifndef NDEBUG 123 void showStyle(); 124 #endif 125 126 bool propertyMatches(CSSPropertyID, const CSSValue*) const; 127 128 void trace(Visitor*); 129 void traceAfterDispatch(Visitor*) { } 130 131 protected: 132 133 enum { MaxArraySize = (1 << 28) - 1 }; 134 135 StylePropertySet(CSSParserMode cssParserMode) 136 : m_cssParserMode(cssParserMode) 137 , m_isMutable(true) 138 , m_arraySize(0) 139 { } 140 141 StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize) 142 : m_cssParserMode(cssParserMode) 143 , m_isMutable(false) 144 , m_arraySize(std::min(immutableArraySize, unsigned(MaxArraySize))) 145 { } 146 147 unsigned m_cssParserMode : 3; 148 mutable unsigned m_isMutable : 1; 149 unsigned m_arraySize : 28; 150 151 friend class PropertySetCSSStyleDeclaration; 152 }; 153 154 class ImmutableStylePropertySet : public StylePropertySet { 155 public: 156 ~ImmutableStylePropertySet(); 157 static PassRefPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode); 158 159 unsigned propertyCount() const { return m_arraySize; } 160 161 const RawPtrWillBeMember<CSSValue>* valueArray() const; 162 const StylePropertyMetadata* metadataArray() const; 163 int findPropertyIndex(CSSPropertyID) const; 164 165 void traceAfterDispatch(Visitor*); 166 167 void* operator new(std::size_t, void* location) 168 { 169 return location; 170 } 171 172 void* m_storage; 173 174 private: 175 ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); 176 }; 177 178 inline const RawPtrWillBeMember<CSSValue>* ImmutableStylePropertySet::valueArray() const 179 { 180 return reinterpret_cast<const RawPtrWillBeMember<CSSValue>*>(const_cast<const void**>(&(this->m_storage))); 181 } 182 183 inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const 184 { 185 return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(RawPtrWillBeMember<CSSValue>)]); 186 } 187 188 DEFINE_TYPE_CASTS(ImmutableStylePropertySet, StylePropertySet, set, !set->isMutable(), !set.isMutable()); 189 190 inline ImmutableStylePropertySet* toImmutableStylePropertySet(const RefPtr<StylePropertySet>& set) 191 { 192 return toImmutableStylePropertySet(set.get()); 193 } 194 195 class MutableStylePropertySet : public StylePropertySet { 196 public: 197 ~MutableStylePropertySet() { } 198 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode); 199 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); 200 201 unsigned propertyCount() const { return m_propertyVector.size(); } 202 203 void addParsedProperties(const WillBeHeapVector<CSSProperty, 256>&); 204 void addParsedProperty(const CSSProperty&); 205 206 // These expand shorthand properties into multiple properties. 207 bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); 208 void setProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important = false); 209 210 // These do not. FIXME: This is too messy, we can do better. 211 bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 212 bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false); 213 void appendPrefixingVariantProperty(const CSSProperty&); 214 void setPrefixingVariantProperty(const CSSProperty&); 215 void setProperty(const CSSProperty&, CSSProperty* slot = 0); 216 217 bool removeProperty(CSSPropertyID, String* returnText = 0); 218 void removePrefixedOrUnprefixedProperty(CSSPropertyID); 219 void removeBlockProperties(); 220 bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); 221 void removeEquivalentProperties(const StylePropertySet*); 222 void removeEquivalentProperties(const CSSStyleDeclaration*); 223 224 void mergeAndOverrideOnConflict(const StylePropertySet*); 225 226 void clear(); 227 void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet); 228 229 CSSStyleDeclaration* ensureCSSStyleDeclaration(); 230 int findPropertyIndex(CSSPropertyID) const; 231 232 void traceAfterDispatch(Visitor*); 233 234 private: 235 explicit MutableStylePropertySet(CSSParserMode); 236 explicit MutableStylePropertySet(const StylePropertySet&); 237 MutableStylePropertySet(const CSSProperty* properties, unsigned count); 238 239 bool removeShorthandProperty(CSSPropertyID); 240 CSSProperty* findCSSPropertyWithID(CSSPropertyID); 241 OwnPtrWillBeMember<PropertySetCSSStyleDeclaration> m_cssomWrapper; 242 243 friend class StylePropertySet; 244 245 WillBeHeapVector<CSSProperty, 4> m_propertyVector; 246 }; 247 248 DEFINE_TYPE_CASTS(MutableStylePropertySet, StylePropertySet, set, set->isMutable(), set.isMutable()); 249 250 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtr<StylePropertySet>& set) 251 { 252 return toMutableStylePropertySet(set.get()); 253 } 254 255 inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const 256 { 257 if (m_propertySet.isMutable()) 258 return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).metadata(); 259 return toImmutableStylePropertySet(m_propertySet).metadataArray()[m_index]; 260 } 261 262 inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const 263 { 264 if (m_propertySet.isMutable()) 265 return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).value(); 266 return toImmutableStylePropertySet(m_propertySet).valueArray()[m_index]; 267 } 268 269 inline unsigned StylePropertySet::propertyCount() const 270 { 271 if (m_isMutable) 272 return toMutableStylePropertySet(this)->m_propertyVector.size(); 273 return m_arraySize; 274 } 275 276 inline bool StylePropertySet::isEmpty() const 277 { 278 return !propertyCount(); 279 } 280 281 #if !ENABLE(OILPAN) 282 inline void StylePropertySet::deref() 283 { 284 if (!derefBase()) 285 return; 286 287 if (m_isMutable) 288 delete toMutableStylePropertySet(this); 289 else 290 delete toImmutableStylePropertySet(this); 291 } 292 #endif // !ENABLE(OILPAN) 293 294 inline int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const 295 { 296 if (m_isMutable) 297 return toMutableStylePropertySet(this)->findPropertyIndex(propertyID); 298 return toImmutableStylePropertySet(this)->findPropertyIndex(propertyID); 299 } 300 301 } // namespace WebCore 302 303 #endif // StylePropertySet_h 304