• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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:
PropertyReference(const StylePropertySet & propertySet,unsigned index)54         PropertyReference(const StylePropertySet& propertySet, unsigned index)
55             : m_propertySet(propertySet)
56             , m_index(index)
57         {
58         }
59 
id()60         CSSPropertyID id() const { return static_cast<CSSPropertyID>(propertyMetadata().m_propertyID); }
shorthandID()61         CSSPropertyID shorthandID() const { return propertyMetadata().shorthandID(); }
62 
isImportant()63         bool isImportant() const { return propertyMetadata().m_important; }
isInherited()64         bool isInherited() const { return propertyMetadata().m_inherited; }
isImplicit()65         bool isImplicit() const { return propertyMetadata().m_implicit; }
66 
67         String cssName() const;
68         String cssText() const;
69 
value()70         const CSSValue* value() const { return propertyValue(); }
71         // FIXME: We should try to remove this mutable overload.
value()72         CSSValue* value() { return const_cast<CSSValue*>(propertyValue()); }
73 
74         // FIXME: Remove this.
toCSSProperty()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;
propertyAt(unsigned index)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 
cssParserMode()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 
isMutable()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 
StylePropertySet(CSSParserMode cssParserMode)131     StylePropertySet(CSSParserMode cssParserMode)
132         : m_cssParserMode(cssParserMode)
133         , m_isMutable(true)
134         , m_arraySize(0)
135     { }
136 
StylePropertySet(CSSParserMode cssParserMode,unsigned immutableArraySize)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 
propertyCount()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 
valueArray()166 inline const CSSValue** ImmutableStylePropertySet::valueArray() const
167 {
168     return reinterpret_cast<const CSSValue**>(const_cast<const void**>(&(this->m_storage)));
169 }
170 
metadataArray()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 
toImmutableStylePropertySet(const RefPtr<StylePropertySet> & set)178 inline ImmutableStylePropertySet* toImmutableStylePropertySet(const RefPtr<StylePropertySet>& set)
179 {
180     return toImmutableStylePropertySet(set.get());
181 }
182 
183 class MutableStylePropertySet : public StylePropertySet {
184 public:
~MutableStylePropertySet()185     ~MutableStylePropertySet() { }
186     static PassRefPtr<MutableStylePropertySet> create(CSSParserMode = HTMLQuirksMode);
187     static PassRefPtr<MutableStylePropertySet> create(const CSSProperty* properties, unsigned count);
188 
propertyCount()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 
variablesIterator()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:
~VariablesIterator()231         virtual ~VariablesIterator() { }
232         static PassRefPtr<VariablesIterator> create(MutableStylePropertySet*);
233     private:
VariablesIterator(MutableStylePropertySet * propertySet)234         explicit VariablesIterator(MutableStylePropertySet* propertySet) : m_propertySet(propertySet) { }
takeRemainingNames(Vector<AtomicString> & remainingNames)235         void takeRemainingNames(Vector<AtomicString>& remainingNames) { m_remainingNames.swap(remainingNames); }
236         virtual void advance() OVERRIDE;
atEnd()237         virtual bool atEnd() const OVERRIDE { return m_remainingNames.isEmpty(); }
name()238         virtual AtomicString name() const OVERRIDE { return m_remainingNames.last(); }
value()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 
toMutableStylePropertySet(const RefPtr<StylePropertySet> & set)262 inline MutableStylePropertySet* toMutableStylePropertySet(const RefPtr<StylePropertySet>& set)
263 {
264     return toMutableStylePropertySet(set.get());
265 }
266 
propertyMetadata()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 
propertyValue()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 
propertyCount()281 inline unsigned StylePropertySet::propertyCount() const
282 {
283     if (m_isMutable)
284         return toMutableStylePropertySet(this)->m_propertyVector.size();
285     return m_arraySize;
286 }
287 
isEmpty()288 inline bool StylePropertySet::isEmpty() const
289 {
290     return !propertyCount();
291 }
292 
deref()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