Move URL from WebCore to WTF
[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 "CSSParserContext.h"
25 #include "CSSParserTokenRange.h"
26 #include "CSSProperty.h"
27 #include "CSSValueKeywords.h"
28 #include <memory>
29 #include <wtf/Function.h>
30 #include <wtf/TypeCasts.h>
31 #include <wtf/Vector.h>
32 #include <wtf/text/WTFString.h>
33
34 namespace WebCore {
35
36 class CSSDeferredParser;
37 class CSSStyleDeclaration;
38 class CachedResource;
39 class Color;
40 class ImmutableStyleProperties;
41 class MutableStyleProperties;
42 class PropertySetCSSStyleDeclaration;
43 class StyledElement;
44 class StylePropertyShorthand;
45 class StyleSheetContents;
46
47 enum StylePropertiesType { ImmutablePropertiesType, MutablePropertiesType, DeferredPropertiesType };
48     
49 class StylePropertiesBase : public RefCounted<StylePropertiesBase> {
50 public:
51     // Override RefCounted's deref() to ensure operator delete is called on
52     // the appropriate subclass type.
53     void deref();
54     
55     StylePropertiesType type() const { return static_cast<StylePropertiesType>(m_type); }
56
57     CSSParserMode cssParserMode() const { return static_cast<CSSParserMode>(m_cssParserMode); }
58
59 protected:
60     StylePropertiesBase(CSSParserMode cssParserMode, StylePropertiesType type)
61         : m_cssParserMode(cssParserMode)
62         , m_type(type)
63         , m_arraySize(0)
64     { }
65     
66     StylePropertiesBase(CSSParserMode cssParserMode, unsigned immutableArraySize)
67         : m_cssParserMode(cssParserMode)
68         , m_type(ImmutablePropertiesType)
69         , m_arraySize(immutableArraySize)
70     { }
71     
72     unsigned m_cssParserMode : 3;
73     mutable unsigned m_type : 2;
74     unsigned m_arraySize : 27;
75 };
76
77 class StyleProperties : public StylePropertiesBase {
78     friend class PropertyReference;
79 public:
80     class PropertyReference {
81     public:
82         PropertyReference(const StylePropertyMetadata& metadata, const CSSValue* value)
83             : m_metadata(metadata)
84             , m_value(value)
85         { }
86
87         CSSPropertyID id() const { return static_cast<CSSPropertyID>(m_metadata.m_propertyID); }
88         CSSPropertyID shorthandID() const { return m_metadata.shorthandID(); }
89
90         bool isImportant() const { return m_metadata.m_important; }
91         bool isInherited() const { return m_metadata.m_inherited; }
92         bool isImplicit() const { return m_metadata.m_implicit; }
93
94         String cssName() const;
95         String cssText() const;
96
97         const CSSValue* value() const { return m_value; }
98         // FIXME: We should try to remove this mutable overload.
99         CSSValue* value() { return const_cast<CSSValue*>(m_value); }
100
101         // FIXME: Remove this.
102         CSSProperty toCSSProperty() const { return CSSProperty(id(), const_cast<CSSValue*>(m_value), isImportant(), m_metadata.m_isSetFromShorthand, m_metadata.m_indexInShorthandsVector, isImplicit()); }
103
104     private:
105         const StylePropertyMetadata& m_metadata;
106         const CSSValue* m_value;
107     };
108
109     unsigned propertyCount() const;
110     bool isEmpty() const { return !propertyCount(); }
111     PropertyReference propertyAt(unsigned) const;
112
113     WEBCORE_EXPORT RefPtr<CSSValue> getPropertyCSSValue(CSSPropertyID) const;
114     WEBCORE_EXPORT String getPropertyValue(CSSPropertyID) const;
115
116     WEBCORE_EXPORT std::optional<Color> propertyAsColor(CSSPropertyID) const;
117     WEBCORE_EXPORT CSSValueID propertyAsValueID(CSSPropertyID) const;
118
119     bool propertyIsImportant(CSSPropertyID) const;
120     String getPropertyShorthand(CSSPropertyID) const;
121     bool isPropertyImplicit(CSSPropertyID) const;
122
123     RefPtr<CSSValue> getCustomPropertyCSSValue(const String& propertyName) const;
124     String getCustomPropertyValue(const String& propertyName) const;
125     bool customPropertyIsImportant(const String& propertyName) const;
126
127     Ref<MutableStyleProperties> copyBlockProperties() const;
128
129     WEBCORE_EXPORT Ref<MutableStyleProperties> mutableCopy() const;
130     Ref<ImmutableStyleProperties> immutableCopyIfNeeded() const;
131
132     Ref<MutableStyleProperties> copyPropertiesInSet(const CSSPropertyID* set, unsigned length) const;
133     
134     String asText() const;
135
136     bool hasCSSOMWrapper() const;
137     bool isMutable() const { return type() == MutablePropertiesType; }
138
139     bool traverseSubresources(const WTF::Function<bool (const CachedResource&)>& handler) const;
140
141     static unsigned averageSizeInBytes();
142
143 #ifndef NDEBUG
144     void showStyle();
145 #endif
146
147     bool propertyMatches(CSSPropertyID, const CSSValue*) const;
148
149 protected:
150     StyleProperties(CSSParserMode cssParserMode, StylePropertiesType type)
151         : StylePropertiesBase(cssParserMode, type)
152     { }
153
154     StyleProperties(CSSParserMode cssParserMode, unsigned immutableArraySize)
155         : StylePropertiesBase(cssParserMode, immutableArraySize)
156     { }
157
158     int findPropertyIndex(CSSPropertyID) const;
159     int findCustomPropertyIndex(const String& propertyName) const;
160
161 private:
162     String getShorthandValue(const StylePropertyShorthand&) const;
163     String getCommonValue(const StylePropertyShorthand&) const;
164     String getAlignmentShorthandValue(const StylePropertyShorthand&) const;
165     String borderPropertyValue() const;
166     String getLayeredShorthandValue(const StylePropertyShorthand&) const;
167     String get4Values(const StylePropertyShorthand&) const;
168     String borderSpacingValue(const StylePropertyShorthand&) const;
169     String fontValue() const;
170     void appendFontLonghandValueIfExplicit(CSSPropertyID, StringBuilder& result, String& value) const;
171     
172     RefPtr<CSSValue> getPropertyCSSValueInternal(CSSPropertyID) const;
173     
174     friend class PropertySetCSSStyleDeclaration;
175 };
176
177 class ImmutableStyleProperties final : public StyleProperties {
178 public:
179     WEBCORE_EXPORT ~ImmutableStyleProperties();
180     static Ref<ImmutableStyleProperties> create(const CSSProperty* properties, unsigned count, CSSParserMode);
181
182     unsigned propertyCount() const { return m_arraySize; }
183     bool isEmpty() const { return !propertyCount(); }
184     PropertyReference propertyAt(unsigned index) const;
185
186     const CSSValue** valueArray() const;
187     const StylePropertyMetadata* metadataArray() const;
188     int findPropertyIndex(CSSPropertyID) const;
189     int findCustomPropertyIndex(const String& propertyName) const;
190     
191     void* m_storage;
192
193 private:
194     ImmutableStyleProperties(const CSSProperty*, unsigned count, CSSParserMode);
195 };
196
197 inline const CSSValue** ImmutableStyleProperties::valueArray() const
198 {
199     return reinterpret_cast<const CSSValue**>(const_cast<const void**>((&(this->m_storage))));
200 }
201
202 inline const StylePropertyMetadata* ImmutableStyleProperties::metadataArray() const
203 {
204     return reinterpret_cast_ptr<const StylePropertyMetadata*>(&reinterpret_cast_ptr<const char*>(&(this->m_storage))[m_arraySize * sizeof(CSSValue*)]);
205 }
206
207 class MutableStyleProperties final : public StyleProperties {
208 public:
209     WEBCORE_EXPORT static Ref<MutableStyleProperties> create(CSSParserMode = HTMLQuirksMode);
210     static Ref<MutableStyleProperties> create(const CSSProperty* properties, unsigned count);
211
212     WEBCORE_EXPORT ~MutableStyleProperties();
213
214     unsigned propertyCount() const { return m_propertyVector.size(); }
215     bool isEmpty() const { return !propertyCount(); }
216     PropertyReference propertyAt(unsigned index) const;
217
218     PropertySetCSSStyleDeclaration* cssStyleDeclaration();
219
220     bool addParsedProperties(const ParsedPropertyVector&);
221     bool addParsedProperty(const CSSProperty&);
222
223     // These expand shorthand properties into multiple properties.
224     bool setProperty(CSSPropertyID, const String& value, bool important, CSSParserContext);
225     bool setProperty(CSSPropertyID, const String& value, bool important = false);
226     void setProperty(CSSPropertyID, RefPtr<CSSValue>&&, bool important = false);
227
228     // These do not. FIXME: This is too messy, we can do better.
229     bool setProperty(CSSPropertyID, CSSValueID identifier, bool important = false);
230     bool setProperty(CSSPropertyID, CSSPropertyID identifier, bool important = false);
231     bool setProperty(const CSSProperty&, CSSProperty* slot = nullptr);
232
233     bool removeProperty(CSSPropertyID, String* returnText = nullptr);
234     void removeBlockProperties();
235     bool removePropertiesInSet(const CSSPropertyID* set, unsigned length);
236
237     void mergeAndOverrideOnConflict(const StyleProperties&);
238
239     void clear();
240     bool parseDeclaration(const String& styleDeclaration, CSSParserContext);
241
242     WEBCORE_EXPORT CSSStyleDeclaration& ensureCSSStyleDeclaration();
243     CSSStyleDeclaration& ensureInlineCSSStyleDeclaration(StyledElement& parentElement);
244
245     int findPropertyIndex(CSSPropertyID) const;
246     int findCustomPropertyIndex(const String& propertyName) const;
247     
248     Vector<CSSProperty, 4> m_propertyVector;
249
250     // Methods for querying and altering CSS custom properties.
251     bool setCustomProperty(const Document*, const String& propertyName, const String& value, bool important, CSSParserContext);
252     bool removeCustomProperty(const String& propertyName, String* returnText = nullptr);
253
254 private:
255     explicit MutableStyleProperties(CSSParserMode);
256     explicit MutableStyleProperties(const StyleProperties&);
257     MutableStyleProperties(const CSSProperty* properties, unsigned count);
258
259     bool removeShorthandProperty(CSSPropertyID);
260     CSSProperty* findCSSPropertyWithID(CSSPropertyID);
261     CSSProperty* findCustomCSSPropertyWithName(const String&);
262     std::unique_ptr<PropertySetCSSStyleDeclaration> m_cssomWrapper;
263
264     friend class StyleProperties;
265 };
266
267 class DeferredStyleProperties final : public StylePropertiesBase {
268 public:
269     WEBCORE_EXPORT ~DeferredStyleProperties();
270     static Ref<DeferredStyleProperties> create(const CSSParserTokenRange&, CSSDeferredParser&);
271
272     Ref<ImmutableStyleProperties> parseDeferredProperties();
273     
274 private:
275     DeferredStyleProperties(const CSSParserTokenRange&, CSSDeferredParser&);
276     
277     Vector<CSSParserToken> m_tokens;
278     Ref<CSSDeferredParser> m_parser;
279 };
280
281 inline ImmutableStyleProperties::PropertyReference ImmutableStyleProperties::propertyAt(unsigned index) const
282 {
283     return PropertyReference(metadataArray()[index], valueArray()[index]);
284 }
285
286 inline MutableStyleProperties::PropertyReference MutableStyleProperties::propertyAt(unsigned index) const
287 {
288     const CSSProperty& property = m_propertyVector[index];
289     return PropertyReference(property.metadata(), property.value());
290 }
291
292 inline StyleProperties::PropertyReference StyleProperties::propertyAt(unsigned index) const
293 {
294     if (is<MutableStyleProperties>(*this))
295         return downcast<MutableStyleProperties>(*this).propertyAt(index);
296     return downcast<ImmutableStyleProperties>(*this).propertyAt(index);
297 }
298
299 inline unsigned StyleProperties::propertyCount() const
300 {
301     if (is<MutableStyleProperties>(*this))
302         return downcast<MutableStyleProperties>(*this).propertyCount();
303     return downcast<ImmutableStyleProperties>(*this).propertyCount();
304 }
305
306 inline void StylePropertiesBase::deref()
307 {
308     if (!derefBase())
309         return;
310
311     if (is<MutableStyleProperties>(*this))
312         delete downcast<MutableStyleProperties>(this);
313     else if (is<ImmutableStyleProperties>(*this))
314         delete downcast<ImmutableStyleProperties>(this);
315     else
316         delete downcast<DeferredStyleProperties>(this);
317 }
318
319 inline int StyleProperties::findPropertyIndex(CSSPropertyID propertyID) const
320 {
321     if (is<MutableStyleProperties>(*this))
322         return downcast<MutableStyleProperties>(*this).findPropertyIndex(propertyID);
323     return downcast<ImmutableStyleProperties>(*this).findPropertyIndex(propertyID);
324 }
325
326 inline int StyleProperties::findCustomPropertyIndex(const String& propertyName) const
327 {
328     if (is<MutableStyleProperties>(*this))
329         return downcast<MutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
330     return downcast<ImmutableStyleProperties>(*this).findCustomPropertyIndex(propertyName);
331 }
332
333 } // namespace WebCore
334
335 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::StyleProperties)
336     static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() != WebCore::DeferredPropertiesType; }
337 SPECIALIZE_TYPE_TRAITS_END()
338
339 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MutableStyleProperties)
340     static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::MutablePropertiesType; }
341 SPECIALIZE_TYPE_TRAITS_END()
342
343 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ImmutableStyleProperties)
344     static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::ImmutablePropertiesType; }
345 SPECIALIZE_TYPE_TRAITS_END()
346
347 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::DeferredStyleProperties)
348     static bool isType(const WebCore::StylePropertiesBase& set) { return set.type() == WebCore::DeferredPropertiesType; }
349 SPECIALIZE_TYPE_TRAITS_END()