1/* 2 * (C) 1999-2003 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 2004, 2005, 2006, 2008, 2012, 2013 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 "CSSParserMode.h" 25#include "CSSPrimitiveValue.h" 26#include "CSSProperty.h" 27#include "CSSPropertyNames.h" 28#include <wtf/ListHashSet.h> 29#include <wtf/Vector.h> 30#include <wtf/text/WTFString.h> 31 32namespace WebCore { 33 34class CSSRule; 35class CSSStyleDeclaration; 36class ComputedStyleExtractor; 37class ImmutableStylePropertySet; 38class KURL; 39class MutableStylePropertySet; 40class PropertySetCSSStyleDeclaration; 41class StyledElement; 42class StylePropertyShorthand; 43class StyleSheetContents; 44 45class StylePropertySet : public RefCounted<StylePropertySet> { 46 friend class PropertyReference; 47public: 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 static_cast<CSSPropertyID>(propertyMetadata().m_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 private: 78 StylePropertyMetadata propertyMetadata() const; 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 89 PassRefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const; 90 String getPropertyValue(CSSPropertyID) const; 91 bool propertyIsImportant(CSSPropertyID) const; 92 String getPropertyShorthand(CSSPropertyID) const; 93 bool isPropertyImplicit(CSSPropertyID) const; 94 95 PassRefPtr<MutableStylePropertySet> copyBlockProperties() const; 96 97 CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); } 98 99 void addSubresourceStyleURLs(ListHashSet<KURL>&, StyleSheetContents* contextStyleSheet) const; 100 101 PassRefPtr<MutableStylePropertySet> mutableCopy() const; 102 PassRefPtr<ImmutableStylePropertySet> immutableCopyIfNeeded() const; 103 104 PassRefPtr<MutableStylePropertySet> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const; 105 106 String asText() const; 107 108 bool isMutable() const { return m_isMutable; } 109 bool hasCSSOMWrapper() const { return m_ownsCSSOMWrapper; } 110 111 bool hasFailedOrCanceledSubresources() const; 112 113 static unsigned averageSizeInBytes(); 114 115#ifndef NDEBUG 116 void showStyle(); 117#endif 118 119 bool propertyMatches(CSSPropertyID, const CSSValue*) const; 120 121protected: 122 StylePropertySet(CSSParserMode cssParserMode) 123 : m_cssParserMode(cssParserMode) 124 , m_ownsCSSOMWrapper(false) 125 , m_isMutable(true) 126 , m_arraySize(0) 127 { } 128 129 StylePropertySet(CSSParserMode cssParserMode, unsigned immutableArraySize) 130 : m_cssParserMode(cssParserMode) 131 , m_ownsCSSOMWrapper(false) 132 , m_isMutable(false) 133 , m_arraySize(immutableArraySize) 134 { } 135 136 int findPropertyIndex(CSSPropertyID) const; 137 138 unsigned m_cssParserMode : 2; 139 mutable unsigned m_ownsCSSOMWrapper : 1; 140 mutable unsigned m_isMutable : 1; 141 unsigned m_arraySize : 28; 142 143private: 144 String getShorthandValue(const StylePropertyShorthand&) const; 145 String getCommonValue(const StylePropertyShorthand&) const; 146 enum CommonValueMode { OmitUncommonValues, ReturnNullOnUncommonValues }; 147 String borderPropertyValue(CommonValueMode) const; 148 String getLayeredShorthandValue(const StylePropertyShorthand&) const; 149 String get4Values(const StylePropertyShorthand&) const; 150 String borderSpacingValue(const StylePropertyShorthand&) const; 151 String fontValue() const; 152 void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const; 153 154 friend class PropertySetCSSStyleDeclaration; 155}; 156 157class ImmutableStylePropertySet : public StylePropertySet { 158public: 159 ~ImmutableStylePropertySet(); 160 static PassRefPtr<ImmutableStylePropertySet> create(const CSSProperty* properties, unsigned count, CSSParserMode); 161 162 unsigned propertyCount() const { return m_arraySize; } 163 164 const CSSValue** valueArray() const; 165 const StylePropertyMetadata* metadataArray() const; 166 167 void* m_storage; 168 169private: 170 ImmutableStylePropertySet(const CSSProperty*, unsigned count, CSSParserMode); 171}; 172 173inline const CSSValue** ImmutableStylePropertySet::valueArray() const 174{ 175 return reinterpret_cast<const CSSValue**>(const_cast<const void**>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage))); 176} 177 178inline const StylePropertyMetadata* ImmutableStylePropertySet::metadataArray() const 179{ 180 return reinterpret_cast<const StylePropertyMetadata*>(&reinterpret_cast<const char*>((&static_cast<const ImmutableStylePropertySet*>(this)->m_storage))[m_arraySize * sizeof(CSSValue*)]); 181} 182 183class MutableStylePropertySet : public StylePropertySet { 184public: 185 ~MutableStylePropertySet(); 186 187 static PassRefPtr<MutableStylePropertySet> create(CSSParserMode = CSSQuirksMode); 188 static PassRefPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count); 189 190 MutableStylePropertySet(const StylePropertySet&); 191 192 unsigned propertyCount() const { return m_propertyVector.size(); } 193 194 PropertySetCSSStyleDeclaration* cssStyleDeclaration(); 195 196 void addParsedProperties(const Vector<CSSProperty>&); 197 void addParsedProperty(const CSSProperty&); 198 199 // These expand shorthand properties into multiple properties. 200 bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0); 201 void setProperty(CSSPropertyID, PassRefPtr<CSSValue>, bool important = false); 202 203 // These do not. FIXME: This is too messy, we can do better. 204 bool setProperty(CSSPropertyID, int identifier, bool important = false); 205 void appendPrefixingVariantProperty(const CSSProperty&); 206 void setPrefixingVariantProperty(const CSSProperty&); 207 void setProperty(const CSSProperty&, CSSProperty* slot = 0); 208 209 bool removeProperty(CSSPropertyID, String* returnText = 0); 210 void removePrefixedOrUnprefixedProperty(CSSPropertyID); 211 void removeBlockProperties(); 212 bool removePropertiesInSet(const CSSPropertyID* set, unsigned length); 213 214 // FIXME: These two can be moved to EditingStyle.cpp 215 void removeEquivalentProperties(const StylePropertySet*); 216 void removeEquivalentProperties(const ComputedStyleExtractor*); 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(StyledElement* parentElement); 225 226 Vector<CSSProperty, 4> m_propertyVector; 227 228private: 229 MutableStylePropertySet(CSSParserMode cssParserMode) 230 : StylePropertySet(cssParserMode) 231 { } 232 233 MutableStylePropertySet(const CSSProperty* properties, unsigned count); 234 235 bool removeShorthandProperty(CSSPropertyID); 236 CSSProperty* findCSSPropertyWithID(CSSPropertyID); 237}; 238 239inline StylePropertyMetadata StylePropertySet::PropertyReference::propertyMetadata() const 240{ 241 if (m_propertySet.isMutable()) 242 return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).metadata(); 243 return static_cast<const ImmutableStylePropertySet&>(m_propertySet).metadataArray()[m_index]; 244} 245 246inline const CSSValue* StylePropertySet::PropertyReference::propertyValue() const 247{ 248 if (m_propertySet.isMutable()) 249 return static_cast<const MutableStylePropertySet&>(m_propertySet).m_propertyVector.at(m_index).value(); 250 return static_cast<const ImmutableStylePropertySet&>(m_propertySet).valueArray()[m_index]; 251} 252 253inline unsigned StylePropertySet::propertyCount() const 254{ 255 if (m_isMutable) 256 return static_cast<const MutableStylePropertySet*>(this)->m_propertyVector.size(); 257 return m_arraySize; 258} 259 260inline bool StylePropertySet::isEmpty() const 261{ 262 return !propertyCount(); 263} 264 265inline void StylePropertySet::deref() 266{ 267 if (!derefBase()) 268 return; 269 270 if (m_isMutable) 271 delete static_cast<MutableStylePropertySet*>(this); 272 else 273 delete static_cast<ImmutableStylePropertySet*>(this); 274} 275 276} // namespace WebCore 277 278#endif // StylePropertySet_h 279