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 "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 RefCounted<StylePropertySet> { 45 friend class PropertyReference; 46 public: 47 // Override RefCounted's deref() to ensure operator delete is called on 48 // the appropriate subclass type. 49 void deref(); 50 51 class PropertyReference { 52 public: 53 PropertyReference(const StylePropertySet& propertySet, unsigned index) 54 : m_propertySet(propertySet) 55 , m_index(index) 56 { 57 } 58 59 CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); } 60 CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); } 61 62 bool isImportant() const { return propertyMetadata().m_important; } 63 bool isInherited() const { return propertyMetadata().m_inherited; } 64 bool isImplicit() const { return propertyMetadata().m_implicit; } 65 66 String cssName() const; 67 String cssText() const; 68 69 const CSSValue* value() const { return propertyValue(); } 70 // FIXME: We should try to remove this mutable overload. 71 CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); } 72 73 // FIXME: Remove this. 74 CSSProperty toCSSProperty() const { return CSSProperty(propertyMetadata(), const_cast<CSSValue*>(propertyValue())); } 75 76 const StylePropertyMetadata& propertyMetadata() const; 77 78 private: 79 const CSSValue* propertyValue() const; 80 81 const StylePropertySet& m_propertySet; 82 unsigned m_index; 83 }; 84 85 unsigned propertyCount() const; 86 bool isEmpty() const; 87 PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); } 88 int findPropertyIndex(CSSPropertyID) const; 89 size_t findVariableIndex(const AtomicString& name) const; 90 91 PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; 92 String getPropertyValue(CSSPropertyID) const; 93 unsigned variableCount() const; 94 String variableValue(const AtomicString& name) const; 95 96 bool propertyIsImportant(CSSPropertyID) const; 97 CSSPropertyID getPropertyShorthand(CSSPropertyID) const; 98 bool isPropertyImplicit(CSSPropertyID) const; 99 100 PassRefPtr<MutableStylePropertySet> copyBlockProperties() const; 101 102 CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); } 103 104 void addSubresourceStyleURLs(ListHashSet<KURL>&, StyleSheetContents* contextStyleSheet) const; 105 106 PassRefPtr<MutableStylePropertySet> mutableCopy() const; 107 PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const; 108 109 PassRefPtr<MutableStylePropertySet> copyPropertiesInSet(const Vector<CSSPropertyID>&) const; 110 111 String asText() const; 112 113 bool isMutable() const { return m_isMutable; } 114 bool hasCSSOMWrapper() const; 115 116 bool hasFailedOrCanceledSubresources() const; 117 118 static unsigned averageSizeInBytes(); 119 120 #ifndef NDEBUG 121 void showStyle(); 122 #endif 123 124 bool propertyMatches(CSSPropertyID, const CSSValue*) const; 125 126 protected: 127 StylePropertySet(CSSParserMode cssParserMode) 128 : m_cssParserMode(cssParserMode) 129 , m_isMutable(true) 130 , m_arraySize(0) 131 { } 132 133 StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize) 134 : m_cssParserMode(cssParserMode) 135 , m_isMutable(false) 136 , m_arraySize(immutableArraySize) 137 { } 138 139 unsigned m_cssParserMode : 2; 140 mutable unsigned m_isMutable : 1; 141 unsigned m_arraySize : 29; 142 143 friend class PropertySetCSSStyleDeclaration; 144 }; 145 146 class ImmutableStylePropertySet : public StylePropertySet { 147 public: 148 ~ImmutableStylePropertySet(); 149 static PassRefPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode); 150 151 unsigned propertyCount() const { return m_arraySize; } 152 153 const CSSValue** valueArray() const; 154 const StylePropertyMetadata* metadataArray() const; 155 156 void* m_storage; 157 158 private: 159 ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); 160 }; 161 162 inline const CSSValue** ImmutableStylePropertySet::valueArray() const 163 { 164 return reinterpret_cast<const CSSValue**>(const_cast<const void**>(&(this->m_storage))); 165 } 166 167 inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const 168 { 169 return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]); 170 } 171 172 class MutableStylePropertySet : public StylePropertySet { 173 public: 174 static PassRefPtr<MutableStylePropertySet> create(CSSParserMode = CSSQuirksMode); 175 static PassRefPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); 176 177 unsigned propertyCount() const { return m_propertyVector.size(); } 178 PropertySetCSSStyleDeclaration* cssStyleDeclaration(); 179 180 void addParsedProperties(const Vector<CSSProperty>&); 181 void addParsedProperty(const CSSProperty&); 182 183 // These expand shorthand properties into multiple properties. 184 bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); 185 void setProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important = false); 186 187 // These do not. FIXME: This is too messy, we can do better. 188 bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false); 189 bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false); 190 void appendPrefixingVariantProperty(const CSSProperty&); 191 void setPrefixingVariantProperty(const CSSProperty&); 192 void setProperty(const CSSProperty&, CSSProperty* slot = 0); 193 bool setVariableValue(const AtomicString& name, const String& value, bool important = false); 194 195 bool removeProperty(CSSPropertyID, String* returnText = 0); 196 void removePrefixedOrUnprefixedProperty(CSSPropertyID); 197 void removeBlockProperties(); 198 bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); 199 void removeEquivalentProperties(const StylePropertySet*); 200 void removeEquivalentProperties(const CSSStyleDeclaration*); 201 bool removeVariable(const AtomicString& name); 202 bool clearVariables(); 203 204 void mergeAndOverrideOnConflict(const StylePropertySet*); 205 206 void clear(); 207 void parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet); 208 209 CSSStyleDeclaration* ensureCSSStyleDeclaration(); 210 CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(Element* parentElement); 211 212 Vector<CSSProperty, 4> m_propertyVector; 213 214 private: 215 explicit MutableStylePropertySet(CSSParserMode); 216 explicit MutableStylePropertySet(const StylePropertySet&); 217 MutableStylePropertySet(const CSSProperty* properties, unsigned count); 218 219 bool removeShorthandProperty(CSSPropertyID); 220 CSSProperty* findCSSPropertyWithID(CSSPropertyID); 221 OwnPtr<PropertySetCSSStyleDeclaration> m_cssomWrapper; 222 223 friend class StylePropertySet; 224 }; 225 226 inline const StylePropertyMetadata& StylePropertySet::PropertyReference::propertyMetadata() const 227 { 228 if (m_propertySet.isMutable()) 229 return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).metadata(); 230 return static_cast<const ImmutableStylePropertySet&>(m_propertySet).metadataArray()[m_index]; 231 } 232 233 inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const 234 { 235 if (m_propertySet.isMutable()) 236 return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).value(); 237 return static_cast<const ImmutableStylePropertySet&>(m_propertySet).valueArray()[m_index]; 238 } 239 240 inline unsigned StylePropertySet::propertyCount() const 241 { 242 if (m_isMutable) 243 return static_cast<const MutableStylePropertySet*>(this)->m_propertyVector.size(); 244 return m_arraySize; 245 } 246 247 inline bool StylePropertySet::isEmpty() const 248 { 249 return !propertyCount(); 250 } 251 252 inline void StylePropertySet::deref() 253 { 254 if (!derefBase()) 255 return; 256 257 if (m_isMutable) 258 delete static_cast<MutableStylePropertySet*>(this); 259 else 260 delete static_cast<ImmutableStylePropertySet*>(this); 261 } 262 263 } // namespace WebCore 264 265 #endif // StylePropertySet_h 266