Introduce Style::Builder
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 31 Oct 2019 18:55:34 +0000 (18:55 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 31 Oct 2019 18:55:34 +0000 (18:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203682

Reviewed by Zalan Bujtas.

Encapsulate the style building step into a new Builder class. It owns the cascade and the style building state.

Move tha applying code from StyleResolver and PropertyCascade there.
Move a bunch of font related state from StyleResolver::State to BuilderState.

* DerivedSources-output.xcfilelist:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/CSSVariableReferenceValue.cpp:
(WebCore::resolveVariableReference):
* css/DOMCSSRegisterCustomProperty.cpp:
(WebCore::DOMCSSRegisterCustomProperty::registerProperty):
* css/StyleResolver.cpp:
(WebCore::StyleResolver::styleForKeyframe):
(WebCore::StyleResolver::styleForPage):
(WebCore::StyleResolver::applyMatchedProperties):
(WebCore::StyleResolver::applyPropertyToCurrentStyle):
(WebCore::StyleResolver::initializeFontStyle):
(WebCore::StyleResolver::adjustStyleForInterCharacterRuby): Deleted.
(WebCore::checkForOrientationChange): Deleted.
(WebCore::StyleResolver::updateFont): Deleted.
(WebCore::StyleResolver::useSVGZoomRules const): Deleted.
(WebCore::StyleResolver::useSVGZoomRulesForLength const): Deleted.
(WebCore::StyleResolver::checkForTextSizeAdjust): Deleted.
(WebCore::StyleResolver::checkForZoomChange): Deleted.
(WebCore::StyleResolver::checkForGenericFamilyChange): Deleted.
(WebCore::StyleResolver::setFontSize): Deleted.
* css/StyleResolver.h:
(WebCore::StyleResolver::State::setFontSizeHasViewportUnits): Deleted.
(WebCore::StyleResolver::State::fontSizeHasViewportUnits const): Deleted.
(WebCore::StyleResolver::State::useSVGZoomRules const): Deleted.
* css/parser/CSSParser.cpp:
(WebCore::CSSParser::parseValueWithVariableReferences):
* css/parser/CSSPropertyParser.cpp:
* style/PropertyCascade.cpp:
(WebCore::Style::PropertyCascade::PropertyCascade):
(WebCore::Style::PropertyCascade::set):
(WebCore::Style::PropertyCascade::propertyCascadeForRollback const):
(WebCore::Style::PropertyCascade::resolveDirectionAndWritingMode const):
(WebCore::Style::PropertyCascade::applyDeferredProperties): Deleted.
(WebCore::Style::PropertyCascade::applyProperties): Deleted.
(WebCore::Style::PropertyCascade::applyPropertiesImpl): Deleted.
(WebCore::Style::PropertyCascade::applyCustomProperties): Deleted.
(WebCore::Style::PropertyCascade::applyCustomProperty): Deleted.
(WebCore::Style::PropertyCascade::propertyCascadeForRollback): Deleted.
(WebCore::Style::PropertyCascade::applyProperty): Deleted.
(WebCore::Style::PropertyCascade::resolveValue): Deleted.
(WebCore::Style::PropertyCascade::resolvedVariableValue): Deleted.
(WebCore::Style::PropertyCascade::resolveDirectionAndWritingMode): Deleted.
* style/PropertyCascade.h:
(WebCore::Style::PropertyCascade::deferredProperties const):
(WebCore::Style::PropertyCascade::customProperties const):
(WebCore::Style::PropertyCascade::direction const):
(WebCore::Style::PropertyCascade::builderState): Deleted.
* style/StyleBuilder.cpp: Added.
(WebCore::Style::directionFromStyle):
(WebCore::Style::Builder::Builder):
(WebCore::Style::Builder::applyAllProperties):
(WebCore::Style::Builder::applyHighPriorityProperties):
(WebCore::Style::Builder::applyLowPriorityProperties):
(WebCore::Style::Builder::applyPropertyValue):
(WebCore::Style::Builder::applyDeferredProperties):
(WebCore::Style::Builder::applyProperties):
(WebCore::Style::Builder::applyPropertiesImpl):
(WebCore::Style::Builder::applyCustomProperties):
(WebCore::Style::Builder::applyCustomProperty):
(WebCore::Style::Builder::applyCascadeProperty):
(WebCore::Style::Builder::applyProperty):
(WebCore::Style::Builder::resolveValue):
(WebCore::Style::Builder::resolvedVariableValue):
* style/StyleBuilder.h: Added.
(WebCore::Style::Builder::applyProperty):
(WebCore::Style::Builder::state):
* style/StyleBuilderCustom.h:
(WebCore::Style::BuilderCustom::applyValueFontSize):
* style/StyleBuilderState.cpp:
(WebCore::Style::BuilderState::BuilderState):
(WebCore::Style::BuilderState::useSVGZoomRules const):
(WebCore::Style::BuilderState::useSVGZoomRulesForLength const):
(WebCore::Style::BuilderState::adjustStyleForInterCharacterRuby):
(WebCore::Style::BuilderState::updateFont):
(WebCore::Style::BuilderState::updateFontForTextSizeAdjust):
(WebCore::Style::BuilderState::updateFontForZoomChange):
(WebCore::Style::BuilderState::updateFontForGenericFamilyChange):
(WebCore::Style::BuilderState::updateFontForOrientationChange):
(WebCore::Style::BuilderState::setFontSize):
* style/StyleBuilderState.h:
(WebCore::Style::BuilderState::builder):
(WebCore::Style::BuilderState::setFontDirty):
(WebCore::Style::BuilderState::cascade): Deleted.
(WebCore::Style::BuilderState::clearFontDirty): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@251864 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources-output.xcfilelist
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSVariableReferenceValue.cpp
Source/WebCore/css/DOMCSSRegisterCustomProperty.cpp
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/css/parser/CSSParser.cpp
Source/WebCore/css/parser/CSSPropertyParser.cpp
Source/WebCore/style/PropertyCascade.cpp
Source/WebCore/style/PropertyCascade.h
Source/WebCore/style/StyleBuilder.cpp [new file with mode: 0644]
Source/WebCore/style/StyleBuilder.h [new file with mode: 0644]
Source/WebCore/style/StyleBuilderCustom.h
Source/WebCore/style/StyleBuilderState.cpp
Source/WebCore/style/StyleBuilderState.h

index fcb4407..52e0c20 100644 (file)
@@ -1,3 +1,102 @@
+2019-10-31  Antti Koivisto  <antti@apple.com>
+
+        Introduce Style::Builder
+        https://bugs.webkit.org/show_bug.cgi?id=203682
+
+        Reviewed by Zalan Bujtas.
+
+        Encapsulate the style building step into a new Builder class. It owns the cascade and the style building state.
+
+        Move tha applying code from StyleResolver and PropertyCascade there.
+        Move a bunch of font related state from StyleResolver::State to BuilderState.
+
+        * DerivedSources-output.xcfilelist:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSVariableReferenceValue.cpp:
+        (WebCore::resolveVariableReference):
+        * css/DOMCSSRegisterCustomProperty.cpp:
+        (WebCore::DOMCSSRegisterCustomProperty::registerProperty):
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::styleForKeyframe):
+        (WebCore::StyleResolver::styleForPage):
+        (WebCore::StyleResolver::applyMatchedProperties):
+        (WebCore::StyleResolver::applyPropertyToCurrentStyle):
+        (WebCore::StyleResolver::initializeFontStyle):
+        (WebCore::StyleResolver::adjustStyleForInterCharacterRuby): Deleted.
+        (WebCore::checkForOrientationChange): Deleted.
+        (WebCore::StyleResolver::updateFont): Deleted.
+        (WebCore::StyleResolver::useSVGZoomRules const): Deleted.
+        (WebCore::StyleResolver::useSVGZoomRulesForLength const): Deleted.
+        (WebCore::StyleResolver::checkForTextSizeAdjust): Deleted.
+        (WebCore::StyleResolver::checkForZoomChange): Deleted.
+        (WebCore::StyleResolver::checkForGenericFamilyChange): Deleted.
+        (WebCore::StyleResolver::setFontSize): Deleted.
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::State::setFontSizeHasViewportUnits): Deleted.
+        (WebCore::StyleResolver::State::fontSizeHasViewportUnits const): Deleted.
+        (WebCore::StyleResolver::State::useSVGZoomRules const): Deleted.
+        * css/parser/CSSParser.cpp:
+        (WebCore::CSSParser::parseValueWithVariableReferences):
+        * css/parser/CSSPropertyParser.cpp:
+        * style/PropertyCascade.cpp:
+        (WebCore::Style::PropertyCascade::PropertyCascade):
+        (WebCore::Style::PropertyCascade::set):
+        (WebCore::Style::PropertyCascade::propertyCascadeForRollback const):
+        (WebCore::Style::PropertyCascade::resolveDirectionAndWritingMode const):
+        (WebCore::Style::PropertyCascade::applyDeferredProperties): Deleted.
+        (WebCore::Style::PropertyCascade::applyProperties): Deleted.
+        (WebCore::Style::PropertyCascade::applyPropertiesImpl): Deleted.
+        (WebCore::Style::PropertyCascade::applyCustomProperties): Deleted.
+        (WebCore::Style::PropertyCascade::applyCustomProperty): Deleted.
+        (WebCore::Style::PropertyCascade::propertyCascadeForRollback): Deleted.
+        (WebCore::Style::PropertyCascade::applyProperty): Deleted.
+        (WebCore::Style::PropertyCascade::resolveValue): Deleted.
+        (WebCore::Style::PropertyCascade::resolvedVariableValue): Deleted.
+        (WebCore::Style::PropertyCascade::resolveDirectionAndWritingMode): Deleted.
+        * style/PropertyCascade.h:
+        (WebCore::Style::PropertyCascade::deferredProperties const):
+        (WebCore::Style::PropertyCascade::customProperties const):
+        (WebCore::Style::PropertyCascade::direction const):
+        (WebCore::Style::PropertyCascade::builderState): Deleted.
+        * style/StyleBuilder.cpp: Added.
+        (WebCore::Style::directionFromStyle):
+        (WebCore::Style::Builder::Builder):
+        (WebCore::Style::Builder::applyAllProperties):
+        (WebCore::Style::Builder::applyHighPriorityProperties):
+        (WebCore::Style::Builder::applyLowPriorityProperties):
+        (WebCore::Style::Builder::applyPropertyValue):
+        (WebCore::Style::Builder::applyDeferredProperties):
+        (WebCore::Style::Builder::applyProperties):
+        (WebCore::Style::Builder::applyPropertiesImpl):
+        (WebCore::Style::Builder::applyCustomProperties):
+        (WebCore::Style::Builder::applyCustomProperty):
+        (WebCore::Style::Builder::applyCascadeProperty):
+        (WebCore::Style::Builder::applyProperty):
+        (WebCore::Style::Builder::resolveValue):
+        (WebCore::Style::Builder::resolvedVariableValue):
+        * style/StyleBuilder.h: Added.
+        (WebCore::Style::Builder::applyProperty):
+        (WebCore::Style::Builder::state):
+        * style/StyleBuilderCustom.h:
+        (WebCore::Style::BuilderCustom::applyValueFontSize):
+        * style/StyleBuilderState.cpp:
+        (WebCore::Style::BuilderState::BuilderState):
+        (WebCore::Style::BuilderState::useSVGZoomRules const):
+        (WebCore::Style::BuilderState::useSVGZoomRulesForLength const):
+        (WebCore::Style::BuilderState::adjustStyleForInterCharacterRuby):
+        (WebCore::Style::BuilderState::updateFont):
+        (WebCore::Style::BuilderState::updateFontForTextSizeAdjust):
+        (WebCore::Style::BuilderState::updateFontForZoomChange):
+        (WebCore::Style::BuilderState::updateFontForGenericFamilyChange):
+        (WebCore::Style::BuilderState::updateFontForOrientationChange):
+        (WebCore::Style::BuilderState::setFontSize):
+        * style/StyleBuilderState.h:
+        (WebCore::Style::BuilderState::builder):
+        (WebCore::Style::BuilderState::setFontDirty):
+        (WebCore::Style::BuilderState::cascade): Deleted.
+        (WebCore::Style::BuilderState::clearFontDirty): Deleted.
+
 2019-10-31  Alex Christensen  <achristensen@webkit.org>
 
         Remove unneeded HAVE_TIMINGDATAOPTIONS
index 71b38cd..539491e 100644 (file)
@@ -2149,6 +2149,7 @@ $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/ServiceWorkerGlobalScopeConstructor
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/Settings.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/Settings.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/StreamInternalsBuiltins.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/StyleBuilder.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/StyleBuilderGenerated.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/StylePropertyShorthandFunctions.cpp
 $(BUILT_PRODUCTS_DIR)/DerivedSources/WebCore/StylePropertyShorthandFunctions.h
index 6e8ce74..9e437f0 100644 (file)
@@ -2345,6 +2345,7 @@ style/ClassChangeInvalidation.cpp
 style/IdChangeInvalidation.cpp
 style/InlineTextBoxStyle.cpp
 style/PropertyCascade.cpp
+style/StyleBuilder.cpp
 style/StyleBuilderState.cpp
 style/StyleChange.cpp
 style/StyleFontSizeFunctions.cpp
index 6cce558..949b09d 100644 (file)
                E4ABABF32368B95900FA4345 /* StyleBuilderState.h in Headers */ = {isa = PBXBuildFile; fileRef = E4ABABF22368B95800FA4345 /* StyleBuilderState.h */; };
                E4ABABF52368C6EF00FA4345 /* CascadeLevel.h in Headers */ = {isa = PBXBuildFile; fileRef = E4ABABF42368C6EF00FA4345 /* CascadeLevel.h */; };
                E4ABAC04236AE95900FA4345 /* StyleBuilderGenerated.h in Headers */ = {isa = PBXBuildFile; fileRef = E4ABAC02236AE95800FA4345 /* StyleBuilderGenerated.h */; };
+               E4ABAC06236B016D00FA4345 /* StyleBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = E4ABAC05236B016C00FA4345 /* StyleBuilder.h */; };
                E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
                E4ABABF22368B95800FA4345 /* StyleBuilderState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleBuilderState.h; sourceTree = "<group>"; };
                E4ABABF42368C6EF00FA4345 /* CascadeLevel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CascadeLevel.h; sourceTree = "<group>"; };
                E4ABAC02236AE95800FA4345 /* StyleBuilderGenerated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleBuilderGenerated.h; sourceTree = "<group>"; };
+               E4ABAC05236B016C00FA4345 /* StyleBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleBuilder.h; sourceTree = "<group>"; };
+               E4ABAC07236B018100FA4345 /* StyleBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = StyleBuilder.cpp; sourceTree = "<group>"; };
                E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; };
                E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; };
                E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; };
                                1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */,
                                E4ABABE52361A34200FA4345 /* PropertyCascade.cpp */,
                                E4ABABE22361A32900FA4345 /* PropertyCascade.h */,
+                               E4ABAC07236B018100FA4345 /* StyleBuilder.cpp */,
+                               E4ABAC05236B016C00FA4345 /* StyleBuilder.h */,
                                83B9687919F8AB83004EF7AF /* StyleBuilderConverter.h */,
                                835D363619FF6193004C93AB /* StyleBuilderCustom.h */,
                                E4ABAC02236AE95800FA4345 /* StyleBuilderGenerated.h */,
                                BCE1C43C0D9830D3003B02F2 /* JSLocation.h in Headers */,
                                93A806201E03B585008A1F26 /* JSLongRange.h in Headers */,
                                CDAB6D2E17C814EE00C60B34 /* JSMediaControlsHost.h in Headers */,
+                               E4ABAC06236B016D00FA4345 /* StyleBuilder.h in Headers */,
                                159741DB1B7D140100201C92 /* JSMediaDeviceInfo.h in Headers */,
                                15739BBB1B42012D00D258C1 /* JSMediaDevices.h in Headers */,
                                FD23A12613F5FA5900F67001 /* JSMediaElementAudioSourceNode.h in Headers */,
index fe60dcf..f9759be 100644 (file)
@@ -30,8 +30,8 @@
 #include "config.h"
 #include "CSSVariableReferenceValue.h"
 
-#include "PropertyCascade.h"
 #include "RenderStyle.h"
+#include "StyleBuilder.h"
 #include "StyleResolver.h"
 
 namespace WebCore {
@@ -67,7 +67,7 @@ static bool resolveVariableReference(CSSParserTokenRange range, Vector<CSSParser
     ASSERT(range.atEnd() || (range.peek().type() == CommaToken));
 
     // Apply this variable first, in case it is still unresolved
-    builderState.cascade().applyCustomProperty(variableName);
+    builderState.builder().applyCustomProperty(variableName);
 
     // Apply fallback to detect cycles
     Vector<CSSParserToken> fallbackResult;
index 1e7a53b..e0c9c86 100644 (file)
@@ -33,7 +33,7 @@
 #include "CSSTokenizer.h"
 #include "DOMCSSNamespace.h"
 #include "Document.h"
-#include "PropertyCascade.h"
+#include "StyleBuilder.h"
 #include "StyleBuilderConverter.h"
 #include <wtf/text/WTFString.h>
 
@@ -60,8 +60,8 @@ ExceptionOr<void> DOMCSSRegisterCustomProperty::registerProperty(Document& docum
             return Exception { SyntaxError, "The given initial value must be computationally independent." };
 
         MatchResult matchResult;
-        Style::PropertyCascade dummyCascade(styleResolver, matchResult, { });
-        initialValue = CSSPropertyParser::parseTypedCustomPropertyValue(descriptor.name, descriptor.syntax, tokenizer.tokenRange(), dummyCascade.builderState(), strictCSSParserContext());
+        Style::Builder dummyBuilder(styleResolver, matchResult, { });
+        initialValue = CSSPropertyParser::parseTypedCustomPropertyValue(descriptor.name, descriptor.syntax, tokenizer.tokenRange(), dummyBuilder.state(), strictCSSParserContext());
 
         if (!initialValue || !initialValue->isResolved())
             return Exception { SyntaxError, "The given initial value does not parse for the given syntax." };
index 20cc56b..f361386 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
- * Copyright (C) 2005-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
@@ -32,7 +32,6 @@
 
 #include "CSSCalculationValue.h"
 #include "CSSCursorImageValue.h"
-#include "CSSCustomPropertyValue.h"
 #include "CSSDefaultStyleSheets.h"
 #include "CSSFilterImageValue.h"
 #include "CSSFontSelector.h"
@@ -51,7 +50,6 @@
 #include "CSSStyleRule.h"
 #include "CSSStyleSheet.h"
 #include "CSSValueList.h"
-#include "CSSValuePool.h"
 #include "CachedResourceLoader.h"
 #include "ElementRuleCollector.h"
 #include "FilterOperation.h"
@@ -73,9 +71,7 @@
 #include "MediaQueryEvaluator.h"
 #include "NodeRenderStyle.h"
 #include "PageRuleCollector.h"
-#include "PaintWorkletGlobalScope.h"
 #include "Pair.h"
-#include "PropertyCascade.h"
 #include "Quirks.h"
 #include "RenderScrollbar.h"
 #include "RenderStyleConstants.h"
 #include "SVGDocumentExtensions.h"
 #include "SVGFontFaceElement.h"
 #include "SVGNames.h"
-#include "SVGSVGElement.h"
 #include "SVGURIReference.h"
 #include "Settings.h"
 #include "ShadowRoot.h"
 #include "SharedStringHash.h"
+#include "StyleBuilder.h"
 #include "StyleColor.h"
 #include "StyleCachedImage.h"
 #include "StyleFontSizeFunctions.h"
@@ -117,8 +113,6 @@ namespace WebCore {
 
 using namespace HTMLNames;
 
-static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
-
 inline void StyleResolver::State::cacheBorderAndBackground()
 {
     m_hasUAAppearance = m_style->hasAppearance();
@@ -363,22 +357,8 @@ std::unique_ptr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle*
     state.setStyle(RenderStyle::clonePtr(*elementStyle));
     state.setParentStyle(RenderStyle::clonePtr(*elementStyle));
 
-    Style::PropertyCascade cascade(*this, result, { Style::CascadeLevel::Author });
-
-    cascade.applyProperties(firstCSSProperty, lastHighPriorityProperty);
-
-    // If our font got dirtied, update it now.
-    updateFont(cascade);
-
-    // Now resolve remaining custom properties and the rest, in any order
-    cascade.applyCustomProperties();
-
-    cascade.applyProperties(firstLowPriorityProperty, lastCSSProperty);
-
-    // If our font got dirtied by one of the non-essential font props, update it a second time.
-    updateFont(cascade);
-
-    cascade.applyDeferredProperties();
+    Style::Builder builder(*this, result, { Style::CascadeLevel::Author });
+    builder.applyAllProperties();
 
     adjustRenderStyle(*state.style(), *state.parentStyle(), nullptr, nullptr);
 
@@ -563,19 +543,8 @@ std::unique_ptr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
 
     auto& result = collector.matchResult();
 
-    Style::PropertyCascade cascade(*this, result, { Style::CascadeLevel::Author });
-
-    cascade.applyProperties(firstCSSProperty, lastHighPriorityProperty);
-
-    // If our font got dirtied, update it now.
-    updateFont(cascade);
-
-    // Now resolve remaining custom properties and the rest, in any order
-    cascade.applyCustomProperties();
-
-    cascade.applyProperties(firstLowPriorityProperty, lastCSSProperty);
-
-    cascade.applyDeferredProperties();
+    Style::Builder builder(*this, result, { Style::CascadeLevel::Author });
+    builder.applyAllProperties();
 
     // Now return the style.
     return m_state.takeStyle();
@@ -679,16 +648,6 @@ static bool isScrollableOverflow(Overflow overflow)
 }
 #endif
 
-void StyleResolver::adjustStyleForInterCharacterRuby()
-{
-    RenderStyle* style = m_state.style();
-    if (style->rubyPosition() != RubyPosition::InterCharacter || !m_state.element() || !m_state.element()->hasTagName(rtTag))
-        return;
-    style->setTextAlign(TextAlignMode::Center);
-    if (style->isHorizontalWritingMode())
-        style->setWritingMode(LeftToRightWritingMode);
-}
-
 static bool hasEffectiveDisplayNoneForDisplayContents(const Element& element)
 {
     // https://drafts.csswg.org/css-display-3/#unbox-html
@@ -1141,38 +1100,6 @@ void StyleResolver::adjustRenderStyleForSiteSpecificQuirks(RenderStyle& style, c
     }
 }
 
-static void checkForOrientationChange(RenderStyle& style)
-{
-    auto [fontOrientation, glyphOrientation] = style.fontAndGlyphOrientation();
-
-    const auto& fontDescription = style.fontDescription();
-    if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
-        return;
-
-    auto newFontDescription = fontDescription;
-    newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
-    newFontDescription.setOrientation(fontOrientation);
-    style.setFontDescription(WTFMove(newFontDescription));
-}
-
-void StyleResolver::updateFont(Style::PropertyCascade& cascade)
-{
-    auto& style = *m_state.style();
-    if (!cascade.builderState().fontDirty() && style.fontCascade().fonts())
-        return;
-
-#if ENABLE(TEXT_AUTOSIZING)
-    checkForTextSizeAdjust(style);
-#endif
-    checkForGenericFamilyChange(style, m_state.parentStyle());
-    checkForZoomChange(style, m_state.parentStyle());
-    checkForOrientationChange(style);
-    style.fontCascade().update(&document().fontSelector());
-    if (m_state.fontSizeHasViewportUnits())
-        style.setHasViewportUnits(true);
-
-    cascade.builderState().clearFontDirty();
-}
 
 Vector<RefPtr<StyleRule>> StyleResolver::styleRulesForElement(const Element* element, unsigned rulesToInclude)
 {
@@ -1325,63 +1252,26 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
         // Find out if there's a -webkit-appearance property in effect from the UA sheet.
         // If so, we cache the border and background styles so that RenderTheme::adjustStyle()
         // can look at them later to figure out if this is a styled form control or not.
-        Style::PropertyCascade cascade(*this, matchResult, { Style::CascadeLevel::UserAgent }, includedProperties);
-
-        cascade.applyProperties(CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
-        adjustStyleForInterCharacterRuby();
-
-#if ENABLE(DARK_MODE_CSS)
-        // Supported color schemes can affect resolved colors, so we need to apply that property before any color properties.
-        cascade.applyProperties(CSSPropertyColorScheme, CSSPropertyColorScheme);
-#endif
-
-        cascade.applyProperties(firstCSSProperty, lastHighPriorityProperty);
-
-        // If our font got dirtied, update it now.
-        updateFont(cascade);
-
-        // Now resolve remaining custom properties and the rest, in any order
-        cascade.applyCustomProperties();
-
-        cascade.applyProperties(firstLowPriorityProperty, lastCSSProperty);
+        Style::Builder builder(*this, matchResult, { Style::CascadeLevel::UserAgent }, includedProperties);
+        builder.applyAllProperties();
 
         state.cacheBorderAndBackground();
     }
 
-    Style::PropertyCascade cascade(*this, matchResult, Style::allCascadeLevels(), includedProperties);
-
-    cascade.applyProperties(CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
-    adjustStyleForInterCharacterRuby();
+    Style::Builder builder(*this, matchResult, Style::allCascadeLevels(), includedProperties);
 
-#if ENABLE(DARK_MODE_CSS)
-    // Supported color schemes can affect resolved colors, so we need to apply that property before any color properties.
-    cascade.applyProperties(CSSPropertyColorScheme, CSSPropertyColorScheme);
-#endif
-
-    cascade.applyProperties(firstCSSProperty, lastHighPriorityProperty);
+    // High priority properties may affect resolution of other properties (they are mostly font related).
+    builder.applyHighPriorityProperties();
 
     // If the effective zoom value changes, we can't use the matched properties cache. Start over.
     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom())
         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
 
-    // If our font got dirtied, update it now.
-    updateFont(cascade);
-
     // If the font changed, we can't use the matched properties cache. Start over.
     if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
 
-    // Now resolve remaining custom properties and the rest, in any order
-    cascade.applyCustomProperties();
-
-    cascade.applyProperties(firstLowPriorityProperty, lastCSSProperty);
-
-    // Finally, some properties must be applied in the order they were parsed.
-    // There are some CSS properties that affect the same RenderStyle values,
-    // so to preserve behavior, we queue them up during cascade and flush here.
-    cascade.applyDeferredProperties();
-
-    ASSERT(!cascade.builderState().fontDirty());
+    builder.applyLowPriorityProperties();
 
     if (cacheItem || !cacheHash)
         return;
@@ -1404,28 +1294,8 @@ void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* valu
         return;
 
     MatchResult matchResult;
-    Style::PropertyCascade cascade(*this, matchResult, { });
-    cascade.applyProperty(id, *value);
-    updateFont(cascade);
-}
-
-// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
-// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
-// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
-// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
-// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
-// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
-// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
-// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
-bool StyleResolver::useSVGZoomRules() const
-{
-    return m_state.element() && m_state.element()->isSVGElement();
-}
-
-// Scale with/height properties on inline SVG root.
-bool StyleResolver::useSVGZoomRulesForLength() const
-{
-    return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
+    Style::Builder builder(*this, matchResult, { });
+    builder.applyPropertyValue(id, *value);
 }
 
 RefPtr<StyleImage> StyleResolver::styleImage(CSSValue& value)
@@ -1447,83 +1317,19 @@ RefPtr<StyleImage> StyleResolver::styleImage(CSSValue& value)
     return nullptr;
 }
 
-#if ENABLE(TEXT_AUTOSIZING)
-void StyleResolver::checkForTextSizeAdjust(RenderStyle& style)
-{
-    if (style.textSizeAdjust().isAuto()
-        || !settings().textAutosizingEnabled()
-        || (settings().textAutosizingUsesIdempotentMode() && !style.textSizeAdjust().isNone()))
-        return;
-
-    auto newFontDescription = style.fontDescription();
-    if (!style.textSizeAdjust().isNone())
-        newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style.textSizeAdjust().multiplier());
-    else
-        newFontDescription.setComputedSize(newFontDescription.specifiedSize());
-    style.setFontDescription(WTFMove(newFontDescription));
-}
-#endif
-
-void StyleResolver::checkForZoomChange(RenderStyle& style, const RenderStyle* parentStyle)
-{
-    if (!parentStyle)
-        return;
-
-    if (style.effectiveZoom() == parentStyle->effectiveZoom() && style.textZoom() == parentStyle->textZoom())
-        return;
-
-    const auto& childFont = style.fontDescription();
-    auto newFontDescription = childFont;
-    setFontSize(newFontDescription, childFont.specifiedSize());
-    style.setFontDescription(WTFMove(newFontDescription));
-}
-
-void StyleResolver::checkForGenericFamilyChange(RenderStyle& style, const RenderStyle* parentStyle)
-{
-    const auto& childFont = style.fontDescription();
-
-    if (childFont.isAbsoluteSize() || !parentStyle)
-        return;
-
-    const auto& parentFont = parentStyle->fontDescription();
-    if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
-        return;
-    // We know the parent is monospace or the child is monospace, and that font
-    // size was unspecified. We want to scale our font size as appropriate.
-    // If the font uses a keyword size, then we refetch from the table rather than
-    // multiplying by our scale factor.
-    float size;
-    if (CSSValueID sizeIdentifier = childFont.keywordSizeAsIdentifier())
-        size = Style::fontSizeForKeyword(sizeIdentifier, childFont.useFixedDefaultSize(), document());
-    else {
-        float fixedScaleFactor = (settings().defaultFixedFontSize() && settings().defaultFontSize())
-            ? static_cast<float>(settings().defaultFixedFontSize()) / settings().defaultFontSize()
-            : 1;
-        size = parentFont.useFixedDefaultSize() ?
-                childFont.specifiedSize() / fixedScaleFactor :
-                childFont.specifiedSize() * fixedScaleFactor;
-    }
-
-    auto newFontDescription = childFont;
-    setFontSize(newFontDescription, size);
-    style.setFontDescription(WTFMove(newFontDescription));
-}
-
 void StyleResolver::initializeFontStyle()
 {
     FontCascadeDescription fontDescription;
     fontDescription.setRenderingMode(settings().fontRenderingMode());
     fontDescription.setOneFamily(standardFamily);
     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
-    setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
-    fontDescription.setShouldAllowUserInstalledFonts(settings().shouldAllowUserInstalledFonts() ? AllowUserInstalledFonts::Yes : AllowUserInstalledFonts::No);
-    style()->setFontDescription(WTFMove(fontDescription));
-}
 
-void StyleResolver::setFontSize(FontCascadeDescription& fontDescription, float size)
-{
+    auto size = Style::fontSizeForKeyword(CSSValueMedium, false, document());
     fontDescription.setSpecifiedSize(size);
-    fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
+    fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), is<SVGElement>(m_state.element()), m_state.style(), document()));
+
+    fontDescription.setShouldAllowUserInstalledFonts(settings().shouldAllowUserInstalledFonts() ? AllowUserInstalledFonts::Yes : AllowUserInstalledFonts::No);
+    style()->setFontDescription(WTFMove(fontDescription));
 }
 
 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimitiveValue& value)
index d64c2ce..f9fc374 100644 (file)
@@ -63,7 +63,6 @@ class KeyframeList;
 class KeyframeValue;
 class MediaQueryEvaluator;
 class Node;
-class RenderScrollbar;
 class RuleData;
 class RuleSet;
 class SelectorFilter;
@@ -80,14 +79,9 @@ class StyleSheet;
 class StyleSheetList;
 class StyledElement;
 class SVGElement;
-class SVGSVGElement;
 class ViewportStyleResolver;
 struct ResourceLoaderOptions;
 
-namespace Style {
-class PropertyCascade;
-}
-
 // MatchOnlyUserAgentRules is used in media queries, where relative units
 // are interpreted according to the document root element style, and styled only
 // from the User Agent Stylesheet rules.
@@ -163,14 +157,8 @@ public:
     void applyPropertyToStyle(CSSPropertyID, CSSValue*, std::unique_ptr<RenderStyle>);
     void applyPropertyToCurrentStyle(CSSPropertyID, CSSValue*);
 
-    void updateFont(Style::PropertyCascade&);
     void initializeFontStyle();
 
-    void setFontSize(FontCascadeDescription&, float size);
-
-    bool useSVGZoomRules() const;
-    bool useSVGZoomRulesForLength() const;
-
     static bool colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimitiveValue&);
     Color colorFromPrimitiveValue(const CSSPrimitiveValue&, bool forVisitedLink = false) const;
 
@@ -205,13 +193,6 @@ public:
     bool createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations);
 
 private:
-    // This function fixes up the default font size if it detects that the current generic font family has changed. -dwh
-    void checkForGenericFamilyChange(RenderStyle&, const RenderStyle* parentStyle);
-    void checkForZoomChange(RenderStyle&, const RenderStyle* parentStyle);
-#if ENABLE(TEXT_AUTOSIZING)
-    void checkForTextSizeAdjust(RenderStyle&);
-#endif
-
     void adjustRenderStyle(RenderStyle&, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const Element*);
     void adjustRenderStyleForSiteSpecificQuirks(RenderStyle&, const Element&);
     
@@ -246,17 +227,12 @@ public:
         const RenderStyle* parentStyle() const { return m_parentStyle; }
         const RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
 
-        void setFontSizeHasViewportUnits(bool hasViewportUnits) { m_fontSizeHasViewportUnits = hasViewportUnits; }
-        bool fontSizeHasViewportUnits() const { return m_fontSizeHasViewportUnits; }
-
         void cacheBorderAndBackground();
         bool hasUAAppearance() const { return m_hasUAAppearance; }
         BorderData borderData() const { return m_borderData; }
         FillLayer backgroundData() const { return m_backgroundData; }
         const Color& backgroundColor() const { return m_backgroundColor; }
 
-        bool useSVGZoomRules() const { return m_element && m_element->isSVGElement(); }
-
         const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; }
 
         const SelectorFilter* selectorFilter() const { return m_selectorFilter; }
@@ -278,7 +254,6 @@ public:
 
         CSSToLengthConversionData m_cssToLengthConversionData;
 
-        bool m_fontSizeHasViewportUnits { false };
         bool m_hasUAAppearance { false };
     };
 
index 39b9f65..6b8cb72 100644 (file)
 #include "Document.h"
 #include "Element.h"
 #include "Page.h"
-#include "PropertyCascade.h"
 #include "RenderStyle.h"
 #include "RenderTheme.h"
 #include "Settings.h"
+#include "StyleBuilder.h"
 #include "StyleColor.h"
 #include "StyleResolver.h"
 #include "StyleRule.h"
@@ -234,7 +234,7 @@ RefPtr<CSSValue> CSSParser::parseValueWithVariableReferences(CSSPropertyID propI
     CSSPropertyParser::collectParsedCustomPropertyValueDependencies(syntax, false, dependencies, resolvedData->tokens(), m_context);
 
     for (auto id : dependencies)
-        builderState.cascade().applyProperties(id, id);
+        builderState.builder().applyProperty(id);
 
     return CSSPropertyParser::parseTypedCustomPropertyValue(name, syntax, resolvedData->tokens(), builderState, m_context);
 }
index 5d40726..4ba0c1c 100644 (file)
 #include "HashTools.h"
 // FIXME-NEWPARSER: Replace Pair and Rect with actual CSSValue subclasses (CSSValuePair and CSSQuadValue).
 #include "Pair.h"
-#include "PropertyCascade.h"
 #include "Rect.h"
 #include "RenderTheme.h"
 #include "RuntimeEnabledFeatures.h"
 #include "SVGPathByteStream.h"
 #include "SVGPathUtilities.h"
+#include "StyleBuilder.h"
 #include "StyleBuilderConverter.h"
 #include "StylePropertyShorthand.h"
 #include "StylePropertyShorthandFunctions.h"
index c3833d4..453eaa1 100644 (file)
@@ -32,7 +32,6 @@
 #include "PaintWorkletGlobalScope.h"
 #include "StyleBuilderGenerated.h"
 #include "StylePropertyShorthand.h"
-#include "StyleResolver.h"
 
 namespace WebCore {
 namespace Style {
@@ -173,23 +172,18 @@ static inline bool isValidCueStyleProperty(CSSPropertyID id)
 }
 #endif
 
-PropertyCascade::PropertyCascade(StyleResolver& styleResolver, const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, IncludedProperties includedProperties)
+PropertyCascade::PropertyCascade(const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, IncludedProperties includedProperties, Direction direction)
     : m_matchResult(matchResult)
     , m_includedProperties(includedProperties)
-    , m_builderState(std::in_place, *this, styleResolver)
+    , m_direction(resolveDirectionAndWritingMode(direction))
 {
-    // Directional properties (*-before/after) are aliases that depend on the TextDirection and WritingMode.
-    // These must be resolved before we can begin building the property cascade.
-    resolveDirectionAndWritingMode();
-
     buildCascade(cascadeLevels);
 }
 
 PropertyCascade::PropertyCascade(const PropertyCascade& parent, OptionSet<CascadeLevel> cascadeLevels)
-    :  m_matchResult(parent.m_matchResult)
+    : m_matchResult(parent.m_matchResult)
     , m_includedProperties(parent.m_includedProperties)
     , m_direction(parent.m_direction)
-    , m_writingMode(parent.m_writingMode)
 {
     buildCascade(cascadeLevels);
 }
@@ -230,7 +224,7 @@ void PropertyCascade::setPropertyInternal(Property& property, CSSPropertyID id,
 void PropertyCascade::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel, ScopeOrdinal styleScopeOrdinal)
 {
     if (CSSProperty::isDirectionAwareProperty(id))
-        id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
+        id = CSSProperty::resolveDirectionAwareProperty(id, m_direction.textDirection, m_direction.writingMode);
 
     ASSERT(!shouldApplyPropertyInParseOrder(id));
 
@@ -377,120 +371,7 @@ void PropertyCascade::addImportantMatches(CascadeLevel cascadeLevel)
         addMatch(matchedDeclarations[match.index], cascadeLevel, true);
 }
 
-void PropertyCascade::applyDeferredProperties()
-{
-    for (auto& property : m_deferredProperties)
-        applyProperty(property);
-}
-
-void PropertyCascade::applyProperties(int firstProperty, int lastProperty)
-{
-    if (LIKELY(m_customProperties.isEmpty()))
-        return applyPropertiesImpl<CustomPropertyCycleTracking::Disabled>(firstProperty, lastProperty);
-
-    return applyPropertiesImpl<CustomPropertyCycleTracking::Enabled>(firstProperty, lastProperty);
-}
-
-template<PropertyCascade::CustomPropertyCycleTracking trackCycles>
-inline void PropertyCascade::applyPropertiesImpl(int firstProperty, int lastProperty)
-{
-    for (int id = firstProperty; id <= lastProperty; ++id) {
-        CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
-        if (!hasProperty(propertyID))
-            continue;
-        ASSERT(propertyID != CSSPropertyCustom);
-        auto& property = m_properties[propertyID];
-
-        if (trackCycles == CustomPropertyCycleTracking::Enabled) {
-            if (UNLIKELY(builderState().m_inProgressProperties.get(propertyID))) {
-                // We are in a cycle (eg. setting font size using registered custom property value containing em).
-                // So this value should be unset.
-                builderState().m_appliedProperties.set(propertyID);
-                // This property is in a cycle, and only the root of the call stack will have firstProperty != lastProperty.
-                ASSERT(firstProperty == lastProperty);
-                continue;
-            }
-            auto& builderState = *m_builderState;
-            builderState.m_inProgressProperties.set(propertyID);
-            applyProperty(property);
-            builderState.m_appliedProperties.set(propertyID);
-            builderState.m_inProgressProperties.set(propertyID, false);
-            continue;
-        }
-
-        // If we don't have any custom properties, then there can't be any cycles.
-        applyProperty(property);
-    }
-}
-
-void PropertyCascade::applyCustomProperties()
-{
-    for (auto& name : m_customProperties.keys())
-        applyCustomProperty(name);
-}
-
-void PropertyCascade::applyCustomProperty(const String& name)
-{
-    auto& builderState = *m_builderState;
-    if (builderState.m_appliedCustomProperties.contains(name) || !m_customProperties.contains(name))
-        return;
-
-    auto property = customProperty(name);
-    bool inCycle = builderState.m_inProgressPropertiesCustom.contains(name);
-
-    for (auto index : { SelectorChecker::MatchDefault, SelectorChecker::MatchLink, SelectorChecker::MatchVisited }) {
-        if (!property.cssValue[index])
-            continue;
-        if (index != SelectorChecker::MatchDefault && builderState.style().insideLink() == InsideLink::NotInside)
-            continue;
-
-        Ref<CSSCustomPropertyValue> valueToApply = CSSCustomPropertyValue::create(downcast<CSSCustomPropertyValue>(*property.cssValue[index]));
-
-        if (inCycle) {
-            builderState.m_appliedCustomProperties.add(name); // Make sure we do not try to apply this property again while resolving it.
-            valueToApply = CSSCustomPropertyValue::createWithID(name, CSSValueInvalid);
-        }
-
-        builderState.m_inProgressPropertiesCustom.add(name);
-
-        if (WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value())) {
-            RefPtr<CSSValue> parsedValue = resolvedVariableValue(CSSPropertyCustom, valueToApply.get());
-
-            if (builderState.m_appliedCustomProperties.contains(name))
-                return; // There was a cycle and the value was reset, so bail.
-
-            if (!parsedValue)
-                parsedValue = CSSCustomPropertyValue::createWithID(name, CSSValueUnset);
-
-            valueToApply = downcast<CSSCustomPropertyValue>(*parsedValue);
-        }
-
-        if (builderState.m_inProgressPropertiesCustom.contains(name)) {
-            builderState.m_linkMatch = index;
-            applyProperty(CSSPropertyCustom, valueToApply.get(), index);
-        }
-    }
-
-    builderState.m_linkMatch = SelectorChecker::MatchDefault;
-    builderState.m_inProgressPropertiesCustom.remove(name);
-    builderState.m_appliedCustomProperties.add(name);
-
-    for (auto index : { SelectorChecker::MatchDefault, SelectorChecker::MatchLink, SelectorChecker::MatchVisited }) {
-        if (!property.cssValue[index])
-            continue;
-        if (index != SelectorChecker::MatchDefault && builderState.style().insideLink() == InsideLink::NotInside)
-            continue;
-
-        Ref<CSSCustomPropertyValue> valueToApply = CSSCustomPropertyValue::create(downcast<CSSCustomPropertyValue>(*property.cssValue[index]));
-
-        if (inCycle && WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value())) {
-            // Resolve this value so that we reset its dependencies.
-            resolvedVariableValue(CSSPropertyCustom, valueToApply.get());
-        }
-    }
-}
-
-const PropertyCascade* PropertyCascade::propertyCascadeForRollback(CascadeLevel cascadeLevel)
+const PropertyCascade* PropertyCascade::propertyCascadeForRollback(CascadeLevel cascadeLevel) const
 {
     switch (cascadeLevel) {
     case CascadeLevel::Author:
@@ -514,147 +395,9 @@ const PropertyCascade* PropertyCascade::propertyCascadeForRollback(CascadeLevel
     return nullptr;
 }
 
-inline void PropertyCascade::applyProperty(const Property& property)
-{
-    auto& builderState = *m_builderState;
-    builderState.m_cascadeLevel = property.level;
-    builderState.m_styleScopeOrdinal = property.styleScopeOrdinal;
-
-    auto applyWithLinkMatch = [&](SelectorChecker::LinkMatchMask linkMatch) {
-        if (property.cssValue[linkMatch]) {
-            builderState.m_linkMatch = linkMatch;
-            applyProperty(property.id, *property.cssValue[linkMatch], linkMatch);
-        }
-    };
-
-    applyWithLinkMatch(SelectorChecker::MatchDefault);
-
-    if (builderState.style().insideLink() == InsideLink::NotInside)
-        return;
-
-    applyWithLinkMatch(SelectorChecker::MatchLink);
-    applyWithLinkMatch(SelectorChecker::MatchVisited);
-
-    builderState.m_linkMatch = SelectorChecker::MatchDefault;
-}
-
-void PropertyCascade::applyProperty(CSSPropertyID id, CSSValue& value, SelectorChecker::LinkMatchMask linkMatchMask)
+PropertyCascade::Direction PropertyCascade::resolveDirectionAndWritingMode(Direction inheritedDirection) const
 {
-    ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
-
-    auto valueToApply = resolveValue(id, value);
-
-    if (CSSProperty::isDirectionAwareProperty(id)) {
-        CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
-        ASSERT(newId != id);
-        return applyProperty(newId, valueToApply.get(), linkMatchMask);
-    }
-
-    auto& builderState = *m_builderState;
-
-    CSSCustomPropertyValue* customPropertyValue = nullptr;
-    CSSValueID customPropertyValueID = CSSValueInvalid;
-    CSSRegisteredCustomProperty* customPropertyRegistered = nullptr;
-
-    if (id == CSSPropertyCustom) {
-        customPropertyValue = downcast<CSSCustomPropertyValue>(valueToApply.ptr());
-        ASSERT(customPropertyValue->isResolved());
-        if (WTF::holds_alternative<CSSValueID>(customPropertyValue->value()))
-            customPropertyValueID = WTF::get<CSSValueID>(customPropertyValue->value());
-        auto& name = customPropertyValue->name();
-        customPropertyRegistered = builderState.document().getCSSRegisteredCustomPropertySet().get(name);
-    }
-
-    bool isInherit = valueToApply->isInheritedValue() || customPropertyValueID == CSSValueInherit;
-    bool isInitial = valueToApply->isInitialValue() || customPropertyValueID == CSSValueInitial;
-
-    bool isUnset = valueToApply->isUnsetValue() || customPropertyValueID == CSSValueUnset;
-    bool isRevert = valueToApply->isRevertValue() || customPropertyValueID == CSSValueRevert;
-
-    if (isRevert) {
-        if (auto* rollback = propertyCascadeForRollback(builderState.m_cascadeLevel)) {
-            // With the rollback cascade built, we need to obtain the property and apply it. If the property is
-            // not present, then we behave like "unset." Otherwise we apply the property instead of
-            // our own.
-            if (customPropertyValue) {
-                if (customPropertyRegistered && customPropertyRegistered->inherits && rollback->hasCustomProperty(customPropertyValue->name())) {
-                    auto property = rollback->customProperty(customPropertyValue->name());
-                    if (property.cssValue[linkMatchMask])
-                        applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
-                    return;
-                }
-            } else if (rollback->hasProperty(id)) {
-                auto& property = rollback->property(id);
-                if (property.cssValue[linkMatchMask])
-                    applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
-                return;
-            }
-        }
-
-        isUnset = true;
-    }
-
-    if (isUnset) {
-        if (CSSProperty::isInheritedProperty(id))
-            isInherit = true;
-        else
-            isInitial = true;
-    }
-
-    ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
-
-    if (builderState.applyPropertyToVisitedLinkStyle() && !isValidVisitedLinkProperty(id)) {
-        // Limit the properties that can be applied to only the ones honored by :visited.
-        return;
-    }
-
-    if (isInherit && !CSSProperty::isInheritedProperty(id))
-        builderState.style().setHasExplicitlyInheritedProperties();
-
-#if ENABLE(CSS_PAINTING_API)
-    if (is<CSSPaintImageValue>(valueToApply)) {
-        auto& name = downcast<CSSPaintImageValue>(valueToApply.get()).name();
-        if (auto* paintWorklet = const_cast<Document&>(builderState.document()).paintWorkletGlobalScopeForName(name)) {
-            auto locker = holdLock(paintWorklet->paintDefinitionLock());
-            if (auto* registration = paintWorklet->paintDefinitionMap().get(name)) {
-                for (auto& property : registration->inputProperties)
-                    builderState.style().addCustomPaintWatchProperty(property);
-            }
-        }
-    }
-#endif
-
-    BuilderGenerated::applyProperty(id, builderState, valueToApply.get(), isInitial, isInherit, customPropertyRegistered);
-}
-
-Ref<CSSValue> PropertyCascade::resolveValue(CSSPropertyID propertyID, CSSValue& value)
-{
-    if (!value.hasVariableReferences())
-        return value;
-    
-    auto variableValue = resolvedVariableValue(propertyID, value);
-    // If the cascade has already applied this id, then we detected a cycle, and this value should be unset.
-    if (!variableValue || builderState().m_appliedProperties.get(propertyID)) {
-        if (CSSProperty::isInheritedProperty(propertyID))
-            return CSSValuePool::singleton().createInheritedValue();
-        return CSSValuePool::singleton().createExplicitInitialValue();
-    }
-
-    return *variableValue;
-}
-
-RefPtr<CSSValue> PropertyCascade::resolvedVariableValue(CSSPropertyID propID, const CSSValue& value)
-{
-    CSSParser parser(builderState().document());
-    return parser.parseValueWithVariableReferences(propID, value, builderState());
-}
-
-void PropertyCascade::resolveDirectionAndWritingMode()
-{
-    auto& style = builderState().style();
-
-    m_direction = style.direction();
-    m_writingMode = style.writingMode();
+    Direction result = inheritedDirection;
 
     bool hadImportantWritingMode = false;
     bool hadImportantDirection = false;
@@ -668,13 +411,13 @@ void PropertyCascade::resolveDirectionAndWritingMode()
                 switch (property.id()) {
                 case CSSPropertyWritingMode:
                     if (!hadImportantWritingMode || property.isImportant()) {
-                        m_writingMode = downcast<CSSPrimitiveValue>(*property.value());
+                        result.writingMode = downcast<CSSPrimitiveValue>(*property.value());
                         hadImportantWritingMode = property.isImportant();
                     }
                     break;
                 case CSSPropertyDirection:
                     if (!hadImportantDirection || property.isImportant()) {
-                        m_direction = downcast<CSSPrimitiveValue>(*property.value());
+                        result.textDirection = downcast<CSSPrimitiveValue>(*property.value());
                         hadImportantDirection = property.isImportant();
                     }
                     break;
@@ -684,6 +427,8 @@ void PropertyCascade::resolveDirectionAndWritingMode()
             }
         }
     }
+
+    return result;
 }
 
 }
index 9f55cff..548c9de 100644 (file)
@@ -40,7 +40,13 @@ class PropertyCascade {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     enum IncludedProperties { All, InheritedOnly };
-    PropertyCascade(StyleResolver&, const MatchResult&, OptionSet<CascadeLevel>, IncludedProperties = IncludedProperties::All);
+
+    struct Direction {
+        TextDirection textDirection;
+        WritingMode writingMode;
+    };
+
+    PropertyCascade(const MatchResult&, OptionSet<CascadeLevel>, IncludedProperties, Direction);
     PropertyCascade(const PropertyCascade&, OptionSet<CascadeLevel>);
 
     ~PropertyCascade();
@@ -58,13 +64,12 @@ public:
     bool hasCustomProperty(const String&) const;
     Property customProperty(const String&) const;
 
-    void applyProperties(int firstProperty, int lastProperty);
-    void applyDeferredProperties();
-    void applyCustomProperties();
-    void applyCustomProperty(const String& name);
-    void applyProperty(CSSPropertyID, CSSValue&, SelectorChecker::LinkMatchMask = SelectorChecker::MatchDefault);
+    const Vector<Property, 8>& deferredProperties() const { return m_deferredProperties; }
+    const HashMap<AtomString, Property>& customProperties() const { return m_customProperties; }
 
-    BuilderState& builderState() { return *m_builderState; }
+    Direction direction() const { return m_direction; }
+
+    const PropertyCascade* propertyCascadeForRollback(CascadeLevel) const;
 
 private:
     void buildCascade(OptionSet<CascadeLevel>);
@@ -76,23 +81,11 @@ private:
     void setDeferred(CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, ScopeOrdinal);
     static void setPropertyInternal(Property&, CSSPropertyID, CSSValue&, unsigned linkMatchType, CascadeLevel, ScopeOrdinal);
 
-    const PropertyCascade* propertyCascadeForRollback(CascadeLevel);
-
-    enum CustomPropertyCycleTracking { Enabled = 0, Disabled };
-    template<CustomPropertyCycleTracking trackCycles>
-    void applyPropertiesImpl(int firstProperty, int lastProperty);
-    void applyProperty(const Property&);
-
-    Ref<CSSValue> resolveValue(CSSPropertyID, CSSValue&);
-    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&);
-
-    void resolveDirectionAndWritingMode();
+    Direction resolveDirectionAndWritingMode(Direction inheritedDirection) const;
 
     const MatchResult& m_matchResult;
     const IncludedProperties m_includedProperties;
-
-    TextDirection m_direction;
-    WritingMode m_writingMode;
+    const Direction m_direction;
 
     Property m_properties[numCSSProperties + 2];
     std::bitset<numCSSProperties + 2> m_propertyIsPresent;
@@ -100,10 +93,8 @@ private:
     Vector<Property, 8> m_deferredProperties;
     HashMap<AtomString, Property> m_customProperties;
 
-    std::unique_ptr<const PropertyCascade> m_authorRollbackCascade;
-    std::unique_ptr<const PropertyCascade> m_userRollbackCascade;
-
-    Optional<BuilderState> m_builderState;
+    mutable std::unique_ptr<const PropertyCascade> m_authorRollbackCascade;
+    mutable std::unique_ptr<const PropertyCascade> m_userRollbackCascade;
 };
 
 inline bool PropertyCascade::hasProperty(CSSPropertyID id) const
diff --git a/Source/WebCore/style/StyleBuilder.cpp b/Source/WebCore/style/StyleBuilder.cpp
new file mode 100644 (file)
index 0000000..9c7107a
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012, 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2014 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "StyleBuilder.h"
+
+#include "CSSFontSelector.h"
+#include "Settings.h"
+#include "StyleBuilderGenerated.h"
+#include "StyleFontSizeFunctions.h"
+
+namespace WebCore {
+namespace Style {
+
+static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
+
+static PropertyCascade::Direction directionFromStyle(const RenderStyle& style)
+{
+    return { style.direction(), style.writingMode() };
+}
+
+Builder::Builder(StyleResolver& resolver, const MatchResult& matchResult, OptionSet<CascadeLevel> cascadeLevels, PropertyCascade::IncludedProperties includedProperties)
+    : m_cascade(matchResult, cascadeLevels, includedProperties, directionFromStyle(*resolver.style()))
+    , m_state(*this, resolver)
+{
+}
+
+Builder::~Builder() = default;
+
+void Builder::applyAllProperties()
+{
+    applyHighPriorityProperties();
+    applyLowPriorityProperties();
+}
+
+// High priority properties may affect resolution of other properties (they are mostly font related).
+void Builder::applyHighPriorityProperties()
+{
+    applyProperties(CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
+    m_state.adjustStyleForInterCharacterRuby();
+
+#if ENABLE(DARK_MODE_CSS)
+    // Supported color schemes can affect resolved colors, so we need to apply that property before any color properties.
+    applyProperties(CSSPropertyColorScheme, CSSPropertyColorScheme);
+#endif
+
+    applyProperties(firstCSSProperty, lastHighPriorityProperty);
+
+    m_state.updateFont();
+}
+
+void Builder::applyLowPriorityProperties()
+{
+    ASSERT(!m_state.fontDirty());
+
+    applyCustomProperties();
+    applyProperties(firstLowPriorityProperty, lastCSSProperty);
+    applyDeferredProperties();
+
+    ASSERT(!m_state.fontDirty());
+}
+
+void Builder::applyPropertyValue(CSSPropertyID propertyID, CSSValue& value)
+{
+    applyProperty(propertyID, value, SelectorChecker::MatchDefault);
+
+    m_state.updateFont();
+}
+
+void Builder::applyDeferredProperties()
+{
+    for (auto& property : m_cascade.deferredProperties())
+        applyCascadeProperty(property);
+}
+
+void Builder::applyProperties(int firstProperty, int lastProperty)
+{
+    if (LIKELY(m_cascade.customProperties().isEmpty()))
+        return applyPropertiesImpl<CustomPropertyCycleTracking::Disabled>(firstProperty, lastProperty);
+
+    return applyPropertiesImpl<CustomPropertyCycleTracking::Enabled>(firstProperty, lastProperty);
+}
+
+template<Builder::CustomPropertyCycleTracking trackCycles>
+inline void Builder::applyPropertiesImpl(int firstProperty, int lastProperty)
+{
+    for (int id = firstProperty; id <= lastProperty; ++id) {
+        CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
+        if (!m_cascade.hasProperty(propertyID))
+            continue;
+        ASSERT(propertyID != CSSPropertyCustom);
+        auto& property = m_cascade.property(propertyID);
+
+        if (trackCycles == CustomPropertyCycleTracking::Enabled) {
+            if (UNLIKELY(m_state.m_inProgressProperties.get(propertyID))) {
+                // We are in a cycle (eg. setting font size using registered custom property value containing em).
+                // So this value should be unset.
+                m_state.m_appliedProperties.set(propertyID);
+                // This property is in a cycle, and only the root of the call stack will have firstProperty != lastProperty.
+                ASSERT(firstProperty == lastProperty);
+                continue;
+            }
+            m_state.m_inProgressProperties.set(propertyID);
+            applyCascadeProperty(property);
+            m_state.m_appliedProperties.set(propertyID);
+            m_state.m_inProgressProperties.set(propertyID, false);
+            continue;
+        }
+
+        // If we don't have any custom properties, then there can't be any cycles.
+        applyCascadeProperty(property);
+    }
+}
+
+void Builder::applyCustomProperties()
+{
+    for (auto& name : m_cascade.customProperties().keys())
+        applyCustomProperty(name);
+}
+
+void Builder::applyCustomProperty(const String& name)
+{
+    if (m_state.m_appliedCustomProperties.contains(name) || !m_cascade.customProperties().contains(name))
+        return;
+
+    auto property = m_cascade.customProperty(name);
+    bool inCycle = m_state.m_inProgressPropertiesCustom.contains(name);
+
+    for (auto index : { SelectorChecker::MatchDefault, SelectorChecker::MatchLink, SelectorChecker::MatchVisited }) {
+        if (!property.cssValue[index])
+            continue;
+        if (index != SelectorChecker::MatchDefault && m_state.style().insideLink() == InsideLink::NotInside)
+            continue;
+
+        Ref<CSSCustomPropertyValue> valueToApply = CSSCustomPropertyValue::create(downcast<CSSCustomPropertyValue>(*property.cssValue[index]));
+
+        if (inCycle) {
+            m_state.m_appliedCustomProperties.add(name); // Make sure we do not try to apply this property again while resolving it.
+            valueToApply = CSSCustomPropertyValue::createWithID(name, CSSValueInvalid);
+        }
+
+        m_state.m_inProgressPropertiesCustom.add(name);
+
+        if (WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value())) {
+            RefPtr<CSSValue> parsedValue = resolvedVariableValue(CSSPropertyCustom, valueToApply.get());
+
+            if (m_state.m_appliedCustomProperties.contains(name))
+                return; // There was a cycle and the value was reset, so bail.
+
+            if (!parsedValue)
+                parsedValue = CSSCustomPropertyValue::createWithID(name, CSSValueUnset);
+
+            valueToApply = downcast<CSSCustomPropertyValue>(*parsedValue);
+        }
+
+        if (m_state.m_inProgressPropertiesCustom.contains(name)) {
+            m_state.m_linkMatch = index;
+            applyProperty(CSSPropertyCustom, valueToApply.get(), index);
+        }
+    }
+
+    m_state.m_linkMatch = SelectorChecker::MatchDefault;
+    m_state.m_inProgressPropertiesCustom.remove(name);
+    m_state.m_appliedCustomProperties.add(name);
+
+    for (auto index : { SelectorChecker::MatchDefault, SelectorChecker::MatchLink, SelectorChecker::MatchVisited }) {
+        if (!property.cssValue[index])
+            continue;
+        if (index != SelectorChecker::MatchDefault && m_state.style().insideLink() == InsideLink::NotInside)
+            continue;
+
+        Ref<CSSCustomPropertyValue> valueToApply = CSSCustomPropertyValue::create(downcast<CSSCustomPropertyValue>(*property.cssValue[index]));
+
+        if (inCycle && WTF::holds_alternative<Ref<CSSVariableReferenceValue>>(valueToApply->value())) {
+            // Resolve this value so that we reset its dependencies.
+            resolvedVariableValue(CSSPropertyCustom, valueToApply.get());
+        }
+    }
+}
+
+inline void Builder::applyCascadeProperty(const PropertyCascade::Property& property)
+{
+    m_state.m_cascadeLevel = property.level;
+    m_state.m_styleScopeOrdinal = property.styleScopeOrdinal;
+
+    auto applyWithLinkMatch = [&](SelectorChecker::LinkMatchMask linkMatch) {
+        if (property.cssValue[linkMatch]) {
+            m_state.m_linkMatch = linkMatch;
+            applyProperty(property.id, *property.cssValue[linkMatch], linkMatch);
+        }
+    };
+
+    applyWithLinkMatch(SelectorChecker::MatchDefault);
+
+    if (m_state.style().insideLink() == InsideLink::NotInside)
+        return;
+
+    applyWithLinkMatch(SelectorChecker::MatchLink);
+    applyWithLinkMatch(SelectorChecker::MatchVisited);
+
+    m_state.m_linkMatch = SelectorChecker::MatchDefault;
+}
+
+void Builder::applyProperty(CSSPropertyID id, CSSValue& value, SelectorChecker::LinkMatchMask linkMatchMask)
+{
+    ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
+
+    auto valueToApply = resolveValue(id, value);
+
+    if (CSSProperty::isDirectionAwareProperty(id)) {
+        auto direction = m_cascade.direction();
+        CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, direction.textDirection, direction.writingMode);
+        ASSERT(newId != id);
+        return applyProperty(newId, valueToApply.get(), linkMatchMask);
+    }
+
+    CSSCustomPropertyValue* customPropertyValue = nullptr;
+    CSSValueID customPropertyValueID = CSSValueInvalid;
+    CSSRegisteredCustomProperty* customPropertyRegistered = nullptr;
+
+    if (id == CSSPropertyCustom) {
+        customPropertyValue = downcast<CSSCustomPropertyValue>(valueToApply.ptr());
+        ASSERT(customPropertyValue->isResolved());
+        if (WTF::holds_alternative<CSSValueID>(customPropertyValue->value()))
+            customPropertyValueID = WTF::get<CSSValueID>(customPropertyValue->value());
+        auto& name = customPropertyValue->name();
+        customPropertyRegistered = m_state.document().getCSSRegisteredCustomPropertySet().get(name);
+    }
+
+    bool isInherit = valueToApply->isInheritedValue() || customPropertyValueID == CSSValueInherit;
+    bool isInitial = valueToApply->isInitialValue() || customPropertyValueID == CSSValueInitial;
+
+    bool isUnset = valueToApply->isUnsetValue() || customPropertyValueID == CSSValueUnset;
+    bool isRevert = valueToApply->isRevertValue() || customPropertyValueID == CSSValueRevert;
+
+    if (isRevert) {
+        if (auto* rollback = m_cascade.propertyCascadeForRollback(m_state.m_cascadeLevel)) {
+            // With the rollback cascade built, we need to obtain the property and apply it. If the property is
+            // not present, then we behave like "unset." Otherwise we apply the property instead of
+            // our own.
+            if (customPropertyValue) {
+                if (customPropertyRegistered && customPropertyRegistered->inherits && rollback->hasCustomProperty(customPropertyValue->name())) {
+                    auto property = rollback->customProperty(customPropertyValue->name());
+                    if (property.cssValue[linkMatchMask])
+                        applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
+                    return;
+                }
+            } else if (rollback->hasProperty(id)) {
+                auto& property = rollback->property(id);
+                if (property.cssValue[linkMatchMask])
+                    applyProperty(property.id, *property.cssValue[linkMatchMask], linkMatchMask);
+                return;
+            }
+        }
+
+        isUnset = true;
+    }
+
+    if (isUnset) {
+        if (CSSProperty::isInheritedProperty(id))
+            isInherit = true;
+        else
+            isInitial = true;
+    }
+
+    ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
+
+    if (m_state.applyPropertyToVisitedLinkStyle() && !isValidVisitedLinkProperty(id)) {
+        // Limit the properties that can be applied to only the ones honored by :visited.
+        return;
+    }
+
+    if (isInherit && !CSSProperty::isInheritedProperty(id))
+        m_state.style().setHasExplicitlyInheritedProperties();
+
+#if ENABLE(CSS_PAINTING_API)
+    if (is<CSSPaintImageValue>(valueToApply)) {
+        auto& name = downcast<CSSPaintImageValue>(valueToApply.get()).name();
+        if (auto* paintWorklet = const_cast<Document&>(m_state.document()).paintWorkletGlobalScopeForName(name)) {
+            auto locker = holdLock(paintWorklet->paintDefinitionLock());
+            if (auto* registration = paintWorklet->paintDefinitionMap().get(name)) {
+                for (auto& property : registration->inputProperties)
+                    m_state.style().addCustomPaintWatchProperty(property);
+            }
+        }
+    }
+#endif
+
+    BuilderGenerated::applyProperty(id, m_state, valueToApply.get(), isInitial, isInherit, customPropertyRegistered);
+}
+
+Ref<CSSValue> Builder::resolveValue(CSSPropertyID propertyID, CSSValue& value)
+{
+    if (!value.hasVariableReferences())
+        return value;
+
+    auto variableValue = resolvedVariableValue(propertyID, value);
+    // If the cascade has already applied this id, then we detected a cycle, and this value should be unset.
+    if (!variableValue || m_state.m_appliedProperties.get(propertyID)) {
+        if (CSSProperty::isInheritedProperty(propertyID))
+            return CSSValuePool::singleton().createInheritedValue();
+        return CSSValuePool::singleton().createExplicitInitialValue();
+    }
+
+    return *variableValue;
+}
+
+RefPtr<CSSValue> Builder::resolvedVariableValue(CSSPropertyID propID, const CSSValue& value)
+{
+    CSSParser parser(m_state.document());
+    return parser.parseValueWithVariableReferences(propID, value, m_state);
+}
+
+}
+}
diff --git a/Source/WebCore/style/StyleBuilder.h b/Source/WebCore/style/StyleBuilder.h
new file mode 100644 (file)
index 0000000..9fc080b
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "PropertyCascade.h"
+#include "StyleBuilderState.h"
+
+namespace WebCore {
+
+namespace Style {
+
+class Builder {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    Builder(StyleResolver&, const MatchResult&, OptionSet<CascadeLevel>, PropertyCascade::IncludedProperties = PropertyCascade::IncludedProperties::All);
+    ~Builder();
+
+    void applyAllProperties();
+    void applyHighPriorityProperties();
+    void applyLowPriorityProperties();
+
+    void applyProperty(CSSPropertyID propertyID) { applyProperties(propertyID, propertyID); }
+    void applyCustomProperty(const String& name);
+
+    void applyPropertyValue(CSSPropertyID, CSSValue&);
+
+    BuilderState& state() { return m_state; }
+
+private:
+    void applyProperties(int firstProperty, int lastProperty);
+    void applyDeferredProperties();
+    void applyCustomProperties();
+
+    enum CustomPropertyCycleTracking { Enabled = 0, Disabled };
+    template<CustomPropertyCycleTracking trackCycles>
+    void applyPropertiesImpl(int firstProperty, int lastProperty);
+    void applyCascadeProperty(const PropertyCascade::Property&);
+    void applyProperty(CSSPropertyID, CSSValue&, SelectorChecker::LinkMatchMask);
+
+    Ref<CSSValue> resolveValue(CSSPropertyID, CSSValue&);
+    RefPtr<CSSValue> resolvedVariableValue(CSSPropertyID, const CSSValue&);
+
+    const PropertyCascade m_cascade;
+    BuilderState m_state;
+};
+
+}
+}
index 904cd03..ed0976b 100644 (file)
@@ -1612,7 +1612,8 @@ inline void BuilderCustom::applyValueFontSize(BuilderState& builderState, CSSVal
         fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize || !(primitiveValue.isPercentage() || primitiveValue.isFontRelativeLength()));
         if (primitiveValue.isLength()) {
             size = primitiveValue.computeLength<float>(CSSToLengthConversionData(&builderState.parentStyle(), &builderState.rootElementStyle(), builderState.document().renderView(), 1.0f, true));
-            builderState.styleResolver().state().setFontSizeHasViewportUnits(primitiveValue.isViewportPercentageLength());
+            if (primitiveValue.isViewportPercentageLength())
+                builderState.style().setHasViewportUnits();
         } else if (primitiveValue.isPercentage())
             size = (primitiveValue.floatValue() * parentSize) / 100.0f;
         else if (primitiveValue.isCalculatedPercentageWithLength()) {
index 1841d27..9356df1 100644 (file)
@@ -1,38 +1,45 @@
 /*
- * Copyright (C) 2019 Apple Inc. All rights reserved.
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
+ * Copyright (C) 2005-2019 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
+ * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. All rights reserved.
+ * Copyright (C) 2012, 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2014 Igalia S.L.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
  *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 
 #include "config.h"
 #include "StyleBuilderState.h"
 
+#include "SVGElement.h"
+#include "SVGSVGElement.h"
+#include "StyleBuilder.h"
 #include "StyleResolver.h"
 
 namespace WebCore {
 namespace Style {
 
-BuilderState::BuilderState(PropertyCascade& cascade, StyleResolver& styleResolver)
-    : m_cascade(cascade)
+BuilderState::BuilderState(Builder& builder, StyleResolver& styleResolver)
+    : m_builder(builder)
     , m_styleMap(*this)
     , m_cssToLengthConversionData(styleResolver.state().cssToLengthConversionData())
     , m_styleResolver(styleResolver)
@@ -46,14 +53,22 @@ BuilderState::BuilderState(PropertyCascade& cascade, StyleResolver& styleResolve
     ASSERT(styleResolver.parentStyle());
 }
 
+// SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
+// of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
+// multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
+// Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
+// need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
+// width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
+// if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
+// properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
 bool BuilderState::useSVGZoomRules() const
 {
-    return m_styleResolver.useSVGZoomRules();
+    return is<SVGElement>(element());
 }
 
 bool BuilderState::useSVGZoomRulesForLength() const
 {
-    return m_styleResolver.useSVGZoomRulesForLength();
+    return is<SVGElement>(element()) && !(is<SVGSVGElement>(*element()) && element()->parentNode());
 }
 
 RefPtr<StyleImage> BuilderState::createStyleImage(CSSValue& value)
@@ -71,9 +86,111 @@ Color BuilderState::colorFromPrimitiveValue(const CSSPrimitiveValue& value, bool
     return m_styleResolver.colorFromPrimitiveValue(value, forVisitedLink);
 }
 
-void BuilderState::setFontSize(FontCascadeDescription& description, float size)
+void BuilderState::adjustStyleForInterCharacterRuby()
+{
+    if (m_style.rubyPosition() != RubyPosition::InterCharacter || !element() || !element()->hasTagName(HTMLNames::rtTag))
+        return;
+
+    m_style.setTextAlign(TextAlignMode::Center);
+    if (m_style.isHorizontalWritingMode())
+        m_style.setWritingMode(LeftToRightWritingMode);
+}
+
+void BuilderState::updateFont()
+{
+    if (!m_fontDirty && m_style.fontCascade().fonts())
+        return;
+
+#if ENABLE(TEXT_AUTOSIZING)
+    updateFontForTextSizeAdjust();
+#endif
+    updateFontForGenericFamilyChange();
+    updateFontForZoomChange();
+    updateFontForOrientationChange();
+
+    m_style.fontCascade().update(&const_cast<Document&>(document()).fontSelector());
+
+    m_fontDirty = false;
+}
+
+#if ENABLE(TEXT_AUTOSIZING)
+void BuilderState::updateFontForTextSizeAdjust()
+{
+    if (m_style.textSizeAdjust().isAuto()
+        || !document().settings().textAutosizingEnabled()
+        || (document().settings().textAutosizingUsesIdempotentMode() && !m_style.textSizeAdjust().isNone()))
+        return;
+
+    auto newFontDescription = m_style.fontDescription();
+    if (!m_style.textSizeAdjust().isNone())
+        newFontDescription.setComputedSize(newFontDescription.specifiedSize() * m_style.textSizeAdjust().multiplier());
+    else
+        newFontDescription.setComputedSize(newFontDescription.specifiedSize());
+
+    m_style.setFontDescription(WTFMove(newFontDescription));
+}
+#endif
+
+void BuilderState::updateFontForZoomChange()
+{
+    if (m_style.effectiveZoom() == m_parentStyle.effectiveZoom() && m_style.textZoom() == m_parentStyle.textZoom())
+        return;
+
+    const auto& childFont = m_style.fontDescription();
+    auto newFontDescription = childFont;
+    setFontSize(newFontDescription, childFont.specifiedSize());
+
+    m_style.setFontDescription(WTFMove(newFontDescription));
+}
+
+void BuilderState::updateFontForGenericFamilyChange()
+{
+    const auto& childFont = m_style.fontDescription();
+
+    if (childFont.isAbsoluteSize())
+        return;
+
+    const auto& parentFont = m_parentStyle.fontDescription();
+    if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
+        return;
+
+    // We know the parent is monospace or the child is monospace, and that font
+    // size was unspecified. We want to scale our font size as appropriate.
+    // If the font uses a keyword size, then we refetch from the table rather than
+    // multiplying by our scale factor.
+    float size = [&] {
+        if (CSSValueID sizeIdentifier = childFont.keywordSizeAsIdentifier())
+            return Style::fontSizeForKeyword(sizeIdentifier, childFont.useFixedDefaultSize(), document());
+
+        auto fixedSize =  document().settings().defaultFixedFontSize();
+        auto defaultSize =  document().settings().defaultFontSize();
+        float fixedScaleFactor = (fixedSize && defaultSize) ? static_cast<float>(fixedSize) / defaultSize : 1;
+        return parentFont.useFixedDefaultSize() ? childFont.specifiedSize() / fixedScaleFactor : childFont.specifiedSize() * fixedScaleFactor;
+    }();
+
+    auto newFontDescription = childFont;
+    setFontSize(newFontDescription, size);
+    m_style.setFontDescription(WTFMove(newFontDescription));
+}
+
+void BuilderState::updateFontForOrientationChange()
+{
+    auto [fontOrientation, glyphOrientation] = m_style.fontAndGlyphOrientation();
+
+    const auto& fontDescription = m_style.fontDescription();
+    if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
+        return;
+
+    auto newFontDescription = fontDescription;
+    newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
+    newFontDescription.setOrientation(fontOrientation);
+    m_style.setFontDescription(WTFMove(newFontDescription));
+}
+
+void BuilderState::setFontSize(FontCascadeDescription& fontDescription, float size)
 {
-    m_styleResolver.setFontSize(description, size);
+    fontDescription.setSpecifiedSize(size);
+    fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), &style(), document()));
 }
 
 }
index f273814..e7b99ca 100644 (file)
@@ -39,13 +39,13 @@ class StyleResolver;
 
 namespace Style {
 
-class PropertyCascade;
+class Builder;
 
 class BuilderState {
 public:
-    BuilderState(PropertyCascade&, StyleResolver&);
+    BuilderState(Builder&, StyleResolver&);
 
-    PropertyCascade& cascade() { return m_cascade; }
+    Builder& builder() { return m_builder; }
     StyleResolver& styleResolver() { return m_styleResolver; }
 
     RenderStyle& style() { return m_style; }
@@ -64,7 +64,6 @@ public:
 
     bool fontDirty() const { return m_fontDirty; }
     void setFontDirty() { m_fontDirty = true; }
-    void clearFontDirty() { m_fontDirty = false; }
 
     const FontCascadeDescription& fontDescription() { return m_style.fontDescription(); }
     const FontCascadeDescription& parentFontDescription() { return m_parentStyle.fontDescription(); }
@@ -85,9 +84,19 @@ public:
     CSSToStyleMap& styleMap() { return m_styleMap; }
 
 private:
-    friend class PropertyCascade;
+    friend class Builder;
 
-    PropertyCascade& m_cascade;
+    void adjustStyleForInterCharacterRuby();
+
+    void updateFont();
+#if ENABLE(TEXT_AUTOSIZING)
+    void updateFontForTextSizeAdjust();
+#endif
+    void updateFontForZoomChange();
+    void updateFontForGenericFamilyChange();
+    void updateFontForOrientationChange();
+
+    Builder& m_builder;
 
     CSSToStyleMap m_styleMap;
     CSSToLengthConversionData m_cssToLengthConversionData;