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/CSSPrimitiveValue.h" 26 #include "core/css/CSSProperty.h" 27 #include "core/css/PropertySetCSSStyleDeclaration.h" 28 #include "core/css/parser/CSSParserMode.h" 29 #include "wtf/ListHashSet.h" 30 #include "wtf/Vector.h" 31 #include "wtf/text/WTFString.h" 32 33 namespace blink { 34 35 class CSSStyleDeclaration; 36 class ImmutableStylePropertySet; 37 class MutableStylePropertySet; 38 class StyleSheetContents; 39 40 class StylePropertySet : public RefCountedWillBeGarbageCollectedFinalized<StylePropertySet> { 41 friend class PropertyReference; 42 public: 43 44 #if ENABLE(OILPAN) 45 // When oilpan is enabled override the finalize method to dispatch to the subclasses' 46 // destructor. This can be removed once the MutableStylePropertySet's OwnPtr is moved 47 // to the heap. 48 void finalizeGarbageCollectedObject(); 49 #else 50 // Override RefCounted's deref() to ensure operator delete is called on 51 // the appropriate subclass type. 52 void deref(); 53 #endif 54 55 class PropertyReference { 56 public: 57 PropertyReference(const StylePropertySet& propertySet, unsigned index) 58 : m_propertySet(propertySet) 59 , m_index(index) 60 { 61 } 62 63 CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); } 64 CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); } 65 66 bool isImportant() const { return propertyMetadata().m_important; } 67 bool isInherited() const { return propertyMetadata().m_inherited; } 68 bool isImplicit() const { return propertyMetadata().m_implicit; } 69 70 String cssName() const; 71 String cssText() const; 72 73 const CSSValue* value() const { return propertyValue(); } 74 // FIXME: We should try to remove this mutable overload. 75 CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); } 76 77 // FIXME: Remove this. 78 CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); } 79 80 const StylePropertyMetadata& propertyMetadata() const; 81 82 private: 83 const CSSValue* propertyValue() const; 84 85 const StylePropertySet& m_propertySet; 86 unsigned m_index; 87 }; 88 89 unsigned propertyCount() const; 90 bool isEmpty() const; 91 PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } 92 int findPropertyIndex(CSSPropertyID) const; 93 bool hasProperty(CSSPropertyID property) const { return findPropertyIndex(property) != -1; } 94 95 PassRefPtrWillBeRawPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; 96 String getPropertyValue(CSSPropertyID) const; 97 98 bool propertyIsImportant(CSSPropertyID) const; 99 CSSPropertyID getPropertyShorthand(CSSPropertyID) const; 100 bool isPropertyImplicit(CSSPropertyID) const; 101 102 PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyBlockProperties() const; 103 104 CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); } 105 106 PassRefPtrWillBeRawPtr<MutableStylePropertySet> mutableCopy() const; 107 PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const; 108 109 PassRefPtrWillBeRawPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; 110 111 String asText() const; 112 113 bool isMutable() const { return m_isMutable; } 114 115 bool hasFailedOrCanceledSubresources() const; 116 117 static unsigned averageSizeInBytes(); 118 119 #ifndef NDEBUG 120 void showStyle(); 121 #endif 122 123 bool propertyMatches(CSSPropertyID, const CSSValue*) const; 124 125 void trace(Visitor*); 126 void traceAfterDispatch(Visitor*) { } 127 128 protected: 129 130 enum { MaxArraySize = (1 << 28) - 1 }; 131 132 StylePropertySet(CSSParserMode cssParserMode) 133 : m_cssParserMode(cssParserMode) 134 , m_isMutable(true) 135 , m_arraySize(0) 136 { } 137 138 StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize) 139 : m_cssParserMode(cssParserMode) 140 , m_isMutable(false) 141 , m_arraySize(std::min(immutableArraySize, unsigned(MaxArraySize))) 142 { } 143 144 unsigned m_cssParserMode : 3; 145 mutable unsigned m_isMutable : 1; 146 unsigned m_arraySize : 28; 147 148 friend class PropertySetCSSStyleDeclaration; 149 }; 150 151 class ImmutableStylePropertySet : public StylePropertySet { 152 public: 153 ~ImmutableStylePropertySet(); 154 static PassRefPtrWillBeRawPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode); 155 156 unsigned propertyCount() const { return m_arraySize; } 157 158 const RawPtrWillBeMember<CSSValue>* valueArray() const; 159 const StylePropertyMetadata* metadataArray() const; 160 int findPropertyIndex(CSSPropertyID) const; 161 162 void traceAfterDispatch(Visitor*); 163 164 void* operator new(std::size_t, void* location) 165 { 166 return location; 167 } 168 169 void* m_storage; 170 171 private: 172 ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); 173 }; 174 175 inline const RawPtrWillBeMember<CSSValue>* ImmutableStylePropertySet::valueArray() const 176 { 177 return reinterpret_cast<const RawPtrWillBeMember<CSSValue>*>(const_cast<const void**>(&(this->m_storage))); 178 } 179 180 inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const 181 { 182 return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(RawPtrWillBeMember<CSSValue>)]); 183 } 184 185 DEFINE_TYPE_CASTS(ImmutableStylePropertySet, StylePropertySet, set, !set->isMutable(), !set.isMutable()); 186 187 class MutableStylePropertySet : public StylePropertySet { 188 public: 189 ~MutableStylePropertySet() { } 190 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode); 191 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); 192 193 unsigned propertyCount() const { return m_propertyVector.size(); } 194 195 void addParsedProperties(const WillBeHeapVector<CSSProperty, 256>&); 196 void addParsedProperty(const CSSProperty&); 197 198 // These expand shorthand properties into multiple properties. 199 bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); 200 void setProperty(CSSPropertyID, PassRefPtrWillBeRawPtr<CSSValue>, bool important = false); 201 202 // These do not. FIXME: This is too messy, we can do better. 203 bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 204 void appendPrefixingVariantProperty(const CSSProperty&); 205 void setPrefixingVariantProperty(const CSSProperty&); 206 void setProperty(const CSSProperty&, CSSProperty* slot = 0); 207 208 bool removeProperty(CSSPropertyID, String* returnText = 0); 209 void removePrefixedOrUnprefixedProperty(CSSPropertyID); 210 void removeBlockProperties(); 211 bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); 212 void removeEquivalentProperties(const StylePropertySet*); 213 void removeEquivalentProperties(const CSSStyleDeclaration*); 214 215 void mergeAndOverrideOnConflict(const StylePropertySet*); 216 217 void clear(); 218 void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet); 219 220 CSSStyleDeclaration* ensureCSSStyleDeclaration(); 221 int findPropertyIndex(CSSPropertyID) const; 222 223 void traceAfterDispatch(Visitor*); 224 225 private: 226 explicit MutableStylePropertySet(CSSParserMode); 227 explicit MutableStylePropertySet(const StylePropertySet&); 228 MutableStylePropertySet(const CSSProperty* properties, unsigned count); 229 230 bool removeShorthandProperty(CSSPropertyID); 231 CSSProperty* findCSSPropertyWithID(CSSPropertyID); 232 OwnPtrWillBeMember<PropertySetCSSStyleDeclaration> m_cssomWrapper; 233 234 friend class StylePropertySet; 235 236 WillBeHeapVector<CSSProperty, 4> m_propertyVector; 237 }; 238 239 DEFINE_TYPE_CASTS(MutableStylePropertySet, StylePropertySet, set, set->isMutable(), set.isMutable()); 240 241 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtrWillBeRawPtr<StylePropertySet>& set) 242 { 243 return toMutableStylePropertySet(set.get()); 244 } 245 246 inline MutableStylePropertySet* toMutableStylePropertySet(const Persistent<StylePropertySet>& set) 247 { 248 return toMutableStylePropertySet(set.get()); 249 } 250 251 inline MutableStylePropertySet* toMutableStylePropertySet(const Member<StylePropertySet>& set) 252 { 253 return toMutableStylePropertySet(set.get()); 254 } 255 256 inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const 257 { 258 if (m_propertySet.isMutable()) 259 return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).metadata(); 260 return toImmutableStylePropertySet(m_propertySet).metadataArray()[m_index]; 261 } 262 263 inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const 264 { 265 if (m_propertySet.isMutable()) 266 return toMutableStylePropertySet(m_propertySet).m_propertyVector.at(m_index).value(); 267 return toImmutableStylePropertySet(m_propertySet).valueArray()[m_index]; 268 } 269 270 inline unsigned StylePropertySet::propertyCount() const 271 { 272 if (m_isMutable) 273 return toMutableStylePropertySet(this)->m_propertyVector.size(); 274 return m_arraySize; 275 } 276 277 inline bool StylePropertySet::isEmpty() const 278 { 279 return !propertyCount(); 280 } 281 282 #if !ENABLE(OILPAN) 283 inline void StylePropertySet::deref() 284 { 285 if (!derefBase()) 286 return; 287 288 if (m_isMutable) 289 delete toMutableStylePropertySet(this); 290 else 291 delete toImmutableStylePropertySet(this); 292 } 293 #endif // !ENABLE(OILPAN) 294 295 inline int StylePropertySet::findPropertyIndex(CSSPropertyID propertyID) const 296 { 297 if (m_isMutable) 298 return toMutableStylePropertySet(this)->findPropertyIndex(propertyID); 299 return toImmutableStylePropertySet(this)->findPropertyIndex(propertyID); 300 } 301 302 } // namespace blink 303 304 #endif // StylePropertySet_h 305