1 /*
2 * (C) 1999-2003 Lars Knoll (knoll@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:
PropertyReference(const StylePropertySet & propertySet,unsigned index)61 PropertyReference(const StylePropertySet& propertySet, unsigned index)
62 : m_propertySet(propertySet)
63 , m_index(index)
64 {
65 }
66
id()67 CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
shorthandID()68 CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
69
isImportant()70 bool isImportant() const { return propertyMetadata().m_important; }
isInherited()71 bool isInherited() const { return propertyMetadata().m_inherited; }
isImplicit()72 bool isImplicit() const { return propertyMetadata().m_implicit; }
73
74 String cssName() const;
75 String cssText() const;
76
value()77 const CSSValue* value() const { return propertyValue(); }
78 // FIXME: We should try to remove this mutable overload.
value()79 CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
80
81 // FIXME: Remove this.
toCSSProperty()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;
propertyAt(unsigned index)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
cssParserMode()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
isMutable()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*);
traceAfterDispatch(Visitor *)129 void traceAfterDispatch(Visitor*) { }
130
131 protected:
132
133 enum { MaxArraySize = (1 << 28) - 1 };
134
StylePropertySet(CSSParserMode cssParserMode)135 StylePropertySet(CSSParserMode cssParserMode)
136 : m_cssParserMode(cssParserMode)
137 , m_isMutable(true)
138 , m_arraySize(0)
139 { }
140
StylePropertySet(CSSParserMode cssParserMode,unsigned immutableArraySize)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
propertyCount()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
new(std::size_t,void * location)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
valueArray()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
metadataArray()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
toImmutableStylePropertySet(const RefPtr<StylePropertySet> & set)190 inline ImmutableStylePropertySet* toImmutableStylePropertySet(const RefPtr<StylePropertySet>& set)
191 {
192 return toImmutableStylePropertySet(set.get());
193 }
194
195 class MutableStylePropertySet : public StylePropertySet {
196 public:
~MutableStylePropertySet()197 ~MutableStylePropertySet() { }
198 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode);
199 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count);
200
propertyCount()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
toMutableStylePropertySet(const RefPtr<StylePropertySet> & set)250 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtr<StylePropertySet>& set)
251 {
252 return toMutableStylePropertySet(set.get());
253 }
254
propertyMetadata()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
propertyValue()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
propertyCount()269 inline unsigned StylePropertySet::propertyCount() const
270 {
271 if (m_isMutable)
272 return toMutableStylePropertySet(this)->m_propertyVector.size();
273 return m_arraySize;
274 }
275
isEmpty()276 inline bool StylePropertySet::isEmpty() const
277 {
278 return !propertyCount();
279 }
280
281 #if !ENABLE(OILPAN)
deref()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
findPropertyIndex(CSSPropertyID propertyID)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