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/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:
PropertyReference(const StylePropertySet & propertySet,unsigned index)57 PropertyReference(const StylePropertySet& propertySet, unsigned index)
58 : m_propertySet(propertySet)
59 , m_index(index)
60 {
61 }
62
id()63 CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
shorthandID()64 CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
65
isImportant()66 bool isImportant() const { return propertyMetadata().m_important; }
isInherited()67 bool isInherited() const { return propertyMetadata().m_inherited; }
isImplicit()68 bool isImplicit() const { return propertyMetadata().m_implicit; }
69
70 String cssName() const;
71 String cssText() const;
72
value()73 const CSSValue* value() const { return propertyValue(); }
74 // FIXME: We should try to remove this mutable overload.
value()75 CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
76
77 // FIXME: Remove this.
toCSSProperty()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;
propertyAt(unsigned index)91 PropertyReference propertyAt(unsigned index) const { return PropertyReference(*this, index); }
92 int findPropertyIndex(CSSPropertyID) const;
hasProperty(CSSPropertyID property)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
cssParserMode()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
isMutable()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*);
traceAfterDispatch(Visitor *)126 void traceAfterDispatch(Visitor*) { }
127
128 protected:
129
130 enum { MaxArraySize = (1 << 28) - 1 };
131
StylePropertySet(CSSParserMode cssParserMode)132 StylePropertySet(CSSParserMode cssParserMode)
133 : m_cssParserMode(cssParserMode)
134 , m_isMutable(true)
135 , m_arraySize(0)
136 { }
137
StylePropertySet(CSSParserMode cssParserMode,unsigned immutableArraySize)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
propertyCount()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
new(std::size_t,void * location)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
valueArray()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
metadataArray()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:
~MutableStylePropertySet()189 ~MutableStylePropertySet() { }
190 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode);
191 static PassRefPtrWillBeRawPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count);
192
propertyCount()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
toMutableStylePropertySet(const RefPtrWillBeRawPtr<StylePropertySet> & set)241 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtrWillBeRawPtr<StylePropertySet>& set)
242 {
243 return toMutableStylePropertySet(set.get());
244 }
245
toMutableStylePropertySet(const Persistent<StylePropertySet> & set)246 inline MutableStylePropertySet* toMutableStylePropertySet(const Persistent<StylePropertySet>& set)
247 {
248 return toMutableStylePropertySet(set.get());
249 }
250
toMutableStylePropertySet(const Member<StylePropertySet> & set)251 inline MutableStylePropertySet* toMutableStylePropertySet(const Member<StylePropertySet>& set)
252 {
253 return toMutableStylePropertySet(set.get());
254 }
255
propertyMetadata()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
propertyValue()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
propertyCount()270 inline unsigned StylePropertySet::propertyCount() const
271 {
272 if (m_isMutable)
273 return toMutableStylePropertySet(this)->m_propertyVector.size();
274 return m_arraySize;
275 }
276
isEmpty()277 inline bool StylePropertySet::isEmpty() const
278 {
279 return !propertyCount();
280 }
281
282 #if !ENABLE(OILPAN)
deref()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
findPropertyIndex(CSSPropertyID propertyID)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