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