b85e85e9722db5ed748a761e15e4a5502fb10a7c
[WebKit-https.git] / Source / WebCore / css / StyleProperties.h
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  * Copyright (C) 2013 Intel Corporation. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #pragma once
23
24 #include "CSSParserMode.h"
25 #include "CSSProperty.h"
26 #include "CSSValueKeywords.h"
27 #include <memory>
28 #include <wtf/ListHashSet.h>
29 #include <wtf/TypeCasts.h>
30 #include <wtf/Vector.h>
31 #include <wtf/text/WTFString.h>
32
33 namespace WebCore {
34
35 class CSSStyleDeclaration;
36 class CachedResource;
37 class ImmutableStyleProperties;
38 class URL;
39 class MutableStyleProperties;
40 class PropertySetCSSStyleDeclaration;
41 class StyledElement;
42 class StylePropertyShorthand;
43 class StyleSheetContents;
44
45 class StyleProperties : public RefCounted<StyleProperties> {
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 StylePropertyMetadata& metadata, const CSSValue* value)
55             : m_metadata(metadata)
56             , m_value(value)
57         { }
58
59         CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); }
60         CSSPropertyID shorthandID() const { return m_metadata.shorthandID(); }
61
62         bool isImportant() const { return m_metadata.m_important; }
63         bool isInherited() const { return m_metadata.m_inherited; }
64         bool isImplicit() const { return m_metadata.m_implicit; }
65
66         String cssName() const;
67         String cssText() const;
68
69         const CSSValue* value() const { return m_value; }
70         // FIXME: We should try to remove this mutable overload.
71         CSSValue* value() { return const_cast<CSSValue*>(m_value); }
72
73         // FIXME: Remove this.
74         CSSProperty toCSSProperty() const { return CSSProperty(id(), const_cast<CSSValue*>(m_value), isImportant(), m_metadata.m_isSetFromShorthand, m_metadata.m_indexInShorthandsVector, isImplicit()); }
75
76     private:
77         const StylePropertyMetadata& m_metadata;
78         const CSSValue* m_value;
79     };
80
81     unsigned propertyCount() const;
82     bool isEmpty() const { return !propertyCount(); }
83     PropertyReference propertyAt(unsigned) const;
84
85     WEBCORE_EXPORT RefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
86     WEBCORE_EXPORT String getPropertyValue(CSSPropertyID) const;
87     bool propertyIsImportant(CSSPropertyID) const;
88     String getPropertyShorthand(CSSPropertyID) const;
89     bool isPropertyImplicit(CSSPropertyID) const;
90
91     RefPtr<CSSValue> getCustomPropertyCSSValue(const String& propertyName) const;
92     String getCustomPropertyValue(const String& propertyName) const;
93     bool customPropertyIsImportant(const String& propertyName) const;
94
95     Ref<MutableStyleProperties> copyBlockProperties() const;
96
97     CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
98
99     void addSubresourceStyleURLs(ListHashSet<URL>&, StyleSheetContents* contextStyleSheet) const;
100
101     WEBCORE_EXPORT Ref<MutableStyleProperties> mutableCopy() const;
102     Ref<ImmutableStyleProperties> immutableCopyIfNeeded() const;
103
104     Ref<MutableStyleProperties> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const;
105     
106     String asText() const;
107
108     bool isMutable() const { return m_isMutable; }
109     bool hasCSSOMWrapper() const;
110
111     bool traverseSubresources(const std::function<bool (const CachedResource&)>& handler) const;
112
113     static unsigned averageSizeInBytes();
114
115 #ifndef NDEBUG
116     void showStyle();
117 #endif
118
119     bool propertyMatches(CSSPropertyID, const CSSValue*) const;
120
121 protected:
122     StyleProperties(CSSParserMode cssParserMode)
123         : m_cssParserMode(cssParserMode)
124         , m_isMutable(true)
125         , m_arraySize(0)
126     { }
127
128     StyleProperties(CSSParserMode cssParserMode, unsigned immutableArraySize)
129         : m_cssParserMode(cssParserMode)
130         , m_isMutable(false)
131         , m_arraySize(immutableArraySize)
132     { }
133
134     int findPropertyIndex(CSSPropertyID) const;
135     int findCustomPropertyIndex(const String& propertyName) const;
136     
137     unsigned m_cssParserMode : 2;
138     mutable unsigned m_isMutable : 1;
139     unsigned m_arraySize : 29;
140     
141 private:
142     String getShorthandValue(const StylePropertyShorthand&) const;
143     String getCommonValue(const StylePropertyShorthand&) const;
144     enum CommonValueMode { OmitUncommonValues, ReturnNullOnUncommonValues };
145     String borderPropertyValue(CommonValueMode) const;
146     String getLayeredShorthandValue(const StylePropertyShorthand&) const;
147     String get4Values(const StylePropertyShorthand&) const;
148     String borderSpacingValue(const StylePropertyShorthand&) const;
149     String fontValue() const;
150     void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const;
151     
152     RefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) const;
153     
154     friend class PropertySetCSSStyleDeclaration;
155 };
156
157 class ImmutableStyleProperties : public StyleProperties {
158 public:
159     WEBCORE_EXPORT ~ImmutableStyleProperties();
160     static Ref<ImmutableStyleProperties> create(const CSSProperty* properties, unsigned count, CSSParserMode);
161
162     unsigned propertyCount() const { return m_arraySize; }
163     bool isEmpty() const { return !propertyCount(); }
164     PropertyReference propertyAt(unsigned index) const;
165
166     const CSSValue** valueArray() const;
167     const StylePropertyMetadata* metadataArray() const;
168     int findPropertyIndex(CSSPropertyID) const;
169     int findCustomPropertyIndex(const String& propertyName) const;
170     
171     void* m_storage;
172
173 private:
174     ImmutableStyleProperties(const CSSProperty*, unsigned count, CSSParserMode);
175 };
176
177 inline const CSSValue** ImmutableStyleProperties::valueArray() const
178 {
179     return reinterpret_cast<const CSSValue**>(const_cast<const void**>((&(this->m_storage))));
180 }
181
182 inline const StylePropertyMetadata* ImmutableStyleProperties::metadataArray() const
183 {
184     return reinterpret_cast_ptr<const StylePropertyMetadata*>(&reinterpret_cast_ptr<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]);
185 }
186
187 class MutableStyleProperties : public StyleProperties {
188 public:
189     WEBCORE_EXPORT static Ref<MutableStyleProperties> create(CSSParserMode = CSSQuirksMode);
190     static Ref<MutableStyleProperties> create(const CSSProperty* properties, unsigned count);
191
192     WEBCORE_EXPORT ~MutableStyleProperties();
193
194     unsigned propertyCount() const { return m_propertyVector.size(); }
195     bool isEmpty() const { return !propertyCount(); }
196     PropertyReference propertyAt(unsigned index) const;
197
198     PropertySetCSSStyleDeclaration* cssStyleDeclaration();
199
200     bool addParsedProperties(const ParsedPropertyVector&);
201     bool addParsedProperty(const CSSProperty&);
202
203     // These expand shorthand properties into multiple properties.
204     bool setProperty(CSSPropertyID, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
205     void setProperty(CSSPropertyID, RefPtr<CSSValue>&&, bool important = false);
206
207     // These do not. FIXME: This is too messy, we can do better.
208     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
209     bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
210     bool setProperty(const CSSProperty&, CSSProperty* slot = nullptr);
211
212     bool removeProperty(CSSPropertyID, String* returnText = nullptr);
213     void removeBlockProperties();
214     bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
215
216     void mergeAndOverrideOnConflict(const StyleProperties&);
217
218     void clear();
219     bool parseDeclaration(const String& styleDeclaration, StyleSheetContents* contextStyleSheet);
220
221     WEBCORE_EXPORT CSSStyleDeclaration* ensureCSSStyleDeclaration();
222     CSSStyleDeclaration* ensureInlineCSSStyleDeclaration(StyledElement* parentElement);
223
224     int findPropertyIndex(CSSPropertyID) const;
225     int findCustomPropertyIndex(const String& propertyName) const;
226     
227     Vector<CSSProperty, 4> m_propertyVector;
228
229     // Methods for querying and altering CSS custom properties.
230     bool setCustomProperty(const String& propertyName, const String& value, bool important = false, StyleSheetContents* contextStyleSheet = 0);
231     bool removeCustomProperty(const String& propertyName, String* returnText = nullptr);
232
233 private:
234     explicit MutableStyleProperties(CSSParserMode);
235     explicit MutableStyleProperties(const StyleProperties&);
236     MutableStyleProperties(const CSSProperty* properties, unsigned count);
237
238     bool removeShorthandProperty(CSSPropertyID);
239     CSSProperty* findCSSPropertyWithID(CSSPropertyID);
240     CSSProperty* findCustomCSSPropertyWithName(const String&);
241     std::unique_ptr<PropertySetCSSStyleDeclaration> m_cssomWrapper;
242
243     friend class StyleProperties;
244 };
245
246 inline ImmutableStyleProperties::PropertyReference ImmutableStyleProperties::propertyAt(unsigned index) const
247 {
248     return PropertyReference(metadataArray()[index], valueArray()[index]);
249 }
250
251 inline MutableStyleProperties::PropertyReference MutableStyleProperties::propertyAt(unsigned index) const
252 {
253     const CSSProperty& property = m_propertyVector[index];
254     return PropertyReference(property.metadata(), property.value());
255 }
256
257 inline StyleProperties::PropertyReference StyleProperties::propertyAt(unsigned index) const
258 {
259     if (is<MutableStyleProperties>(*this))
260         return downcast<MutableStyleProperties>(*this).propertyAt(index);
261     return downcast<ImmutableStyleProperties>(*this).propertyAt(index);
262 }
263
264 inline unsigned StyleProperties::propertyCount() const
265 {
266     if (is<MutableStyleProperties>(*this))
267         return downcast<MutableStyleProperties>(*this).propertyCount();
268     return downcast<ImmutableStyleProperties>(*this).propertyCount();
269 }
270
271 inline void StyleProperties::deref()
272 {
273     if (!derefBase())
274         return;
275
276     if (is<MutableStyleProperties>(*this))
277         delete downcast<MutableStyleProperties>(this);
278     else
279         delete downcast<ImmutableStyleProperties>(this);
280 }
281
282 inline int StyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
283 {
284     if (is<MutableStyleProperties>(*this))
285         return downcast<MutableStyleProperties>(*this).findPropertyIndex(propertyID);
286     return downcast<ImmutableStyleProperties>(*this).findPropertyIndex(propertyID);
287 }
288
289 inline int StyleProperties::findCustomPropertyIndex(const String& propertyName) const
290 {
291     if (is<MutableStyleProperties>(*this))
292         return downcast<MutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
293     return downcast<ImmutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
294 }
295
296 } // namespace WebCore
297
298 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MutableStyleProperties)
299     static bool isType(const WebCore::StyleProperties& set) { return set.isMutable(); }
300 SPECIALIZE_TYPE_TRAITS_END()
301
302 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ImmutableStyleProperties)
303     static bool isType(const WebCore::StyleProperties& set) { return !set.isMutable(); }
304 SPECIALIZE_TYPE_TRAITS_END()