source: webkit/trunk/Source/WebCore/css/StyleProperties.h

Last change on this file was 295476, checked in by [email protected], 3 years ago

Delay system font shorthand resolution until after parsing
https://bugs.webkit.org/show_bug.cgi?id=241454

Reviewed by Antti Koivisto.

This is the fifth piece of https://bugs.webkit.org/show_bug.cgi?id=237817, and is the main crux
of the fix to that bug. When content says something like "font: caption" or "font: -apple-system-body"
we have to map that to CSS properties like font-size and font-weight, so inheritance works properly
across different elements. On iOS, system settings can affect this mapping. Before this patch, we
were performing this mapping inside the parser, which is wrong because we'll never re-parse things
in response to a change in the environment. So, if the page is live, and then the user changes a setting
in system preferences, we won't re-parse, which means the page won't update to accomodate the new setting
the user changed.

This patch changes the parser to not do this mapping, but instead just to emit CSSValues which directly
and simply represent the value that was present in the CSS source itself. So, if the content says
"font: caption" we'll create CSSPrimitiveValues which just hold "caption" and use that for all the longhands
of the font property. Then, we do the mapping when the values are applied, inside StyleBuilder. StyleBuilder
is re-run in response to environment changes, so this piece is necessary for system settings to immediately
take effect without a reload of the page.

This change is web-exposed, because the contents of CSSValues are exposed to webpages via inspecting the
CSSStyleSheet in JavaScript. So, the change is a little scary, but I think it's the only way to have the
right thing happen with system settings.

This patch also deletes the now-unused system font shorthand cache, which was reimplemented in
https://github.com/WebKit/WebKit/commit/10cdfcb983187328f4229d5812a0da2a4210e4ef.

This patch isn't sufficient to make system settings fully work - there are some follow-up patches which
are still necessary on top of this:

  1. Have font creation code actually interrogate system settings, and react accordingly, to create fonts

with the appropriate size/weight

  1. Make sure the right things get invalidated, so we don't get erroneous cache hits when system settings

change

  1. Make sure the right events are being delivered to the right places, and triggering the right invalidation,

in response to system settings being changed.

  • LayoutTests/fast/text/font-shorthand-resolution-expected.txt: Added.
  • LayoutTests/fast/text/font-shorthand-resolution.html: Added.
  • Source/WebCore/css/CSSProperties.json:
  • Source/WebCore/css/parser/CSSPropertyParser.cpp:

(WebCore::CSSPropertyParser::consumeSystemFont):
(WebCore::CSSPropertyParser::parseShorthand):

  • Source/WebCore/css/parser/CSSPropertyParserHelpers.h:

(WebCore::CSSPropertyParserHelpers::isSystemFontShorthand):
(WebCore::CSSPropertyParserHelpers::lowerFontShorthand):

  • Source/WebCore/platform/graphics/SystemFontDatabase.h:
  • Source/WebCore/rendering/RenderTheme.h:
  • Source/WebCore/rendering/RenderThemeCocoa.h:
  • Source/WebCore/rendering/RenderThemeCocoa.mm:

(WebCore::RenderThemeCocoa::systemFont const): Deleted.

  • Source/WebCore/rendering/RenderThemeGtk.cpp:

(WebCore::RenderThemeGtk::systemFont const): Deleted.

  • Source/WebCore/rendering/RenderThemePlayStation.cpp:

(WebCore::RenderThemePlayStation::systemFont const): Deleted.

  • Source/WebCore/rendering/RenderThemeWin.cpp:

(WebCore::RenderThemeWin::systemFont const): Deleted.

  • Source/WebCore/style/StyleBuilderConverter.h:

(WebCore::Style::BuilderConverter::convertFontWeight):
(WebCore::Style::BuilderConverter::convertFontVariantCaps):
(WebCore::Style::BuilderConverter::convertLineHeight):

  • Source/WebCore/style/StyleBuilderCustom.h:

(WebCore::Style::BuilderCustom::applyValueFontFamily):
(WebCore::Style::BuilderCustom::applyValueFontStyle):
(WebCore::Style::BuilderCustom::applyValueFontSize):

  • Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::contentSizeCategoryDidChange):

  • Source/WebKit/WebProcess/cocoa/WebProcessCocoa.mm:

(WebKit::WebProcess::accessibilityPreferencesDidChange):

Canonical link: https://commits.webkit.org/251481@main

  • Property svn:eol-style set to native
File size: 13.1 KB
Line 
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
34namespace WebCore {
35
36class CSSStyleDeclaration;
37class CachedResource;
38class Color;
39class ImmutableStyleProperties;
40class MutableStyleProperties;
41class PropertySetCSSStyleDeclaration;
42class StyledElement;
43class StylePropertyShorthand;
44class StyleSheetContents;
45
46enum StylePropertiesType { ImmutablePropertiesType, MutablePropertiesType };
47
48DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(StyleProperties);
49class StyleProperties : public RefCounted<StyleProperties> {
50 WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(StyleProperties);
51 friend class PropertyReference;
52public:
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
131protected:
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
151private:
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
177DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(ImmutableStyleProperties);
178class ImmutableStyleProperties final : public StyleProperties {
179 WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(ImmutableStyleProperties);
180public:
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
193private:
194 PackedPtr<const CSSValue>* valueArray() const;
195 const StylePropertyMetadata* metadataArray() const;
196 ImmutableStyleProperties(const CSSProperty*, unsigned count, CSSParserMode);
197};
198
199inline 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
204inline const StylePropertyMetadata* ImmutableStyleProperties::metadataArray() const
205{
206 return reinterpret_cast<const StylePropertyMetadata*>(const_cast<const void**>((&(this->m_storage))));
207}
208
209DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(MutableStyleProperties);
210class MutableStyleProperties final : public StyleProperties {
211 WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(MutableStyleProperties);
212public:
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
258private:
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
272inline ImmutableStyleProperties::PropertyReference ImmutableStyleProperties::propertyAt(unsigned index) const
273{
274 return PropertyReference(metadataArray()[index], valueArray()[index].get());
275}
276
277inline MutableStyleProperties::PropertyReference MutableStyleProperties::propertyAt(unsigned index) const
278{
279 const CSSProperty& property = m_propertyVector[index];
280 return PropertyReference(property.metadata(), property.value());
281}
282
283inline 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
290inline unsigned StyleProperties::propertyCount() const
291{
292 if (is<MutableStyleProperties>(*this))
293 return downcast<MutableStyleProperties>(*this).propertyCount();
294 return downcast<ImmutableStyleProperties>(*this).propertyCount();
295}
296
297inline 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
310inline 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
317inline 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
326SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MutableStyleProperties)
327 static bool isType(const WebCore::StyleProperties& set) { return set.type() == WebCore::MutablePropertiesType; }
328SPECIALIZE_TYPE_TRAITS_END()
329
330SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ImmutableStyleProperties)
331 static bool isType(const WebCore::StyleProperties& set) { return set.type() == WebCore::ImmutablePropertiesType; }
332SPECIALIZE_TYPE_TRAITS_END()
333
Note: See TracBrowser for help on using the repository browser.