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