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