Style::Builder should not depend on StyleResolver
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Nov 2019 15:20:19 +0000 (15:20 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 1 Nov 2019 15:20:19 +0000 (15:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203729

Reviewed by Zalan Bujtas.

With all style building state in builder, we can remove the back-reference to style resolver.

* css/CSSFilterImageValue.cpp:
(WebCore::CSSFilterImageValue::createFilterOperations):
* css/CSSFilterImageValue.h:
* css/CSSGradientValue.cpp:
(WebCore::CSSGradientValue::gradientWithStylesResolved):
(WebCore::CSSGradientValue::resolveRGBColors):

Add helper for resolving basic colors without style builder.

* css/CSSGradientValue.h:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::State::clear):
(WebCore::StyleResolver::State::State):
(WebCore::StyleResolver::State::setStyle):
(WebCore::StyleResolver::applyMatchedProperties):

Register content attributes encountered during style building.

(WebCore::StyleResolver::State::updateConversionData): Deleted.

This is now created by BuilderState constructor.

(WebCore::StyleResolver::styleImage): Deleted.
(WebCore::StyleResolver::colorFromPrimitiveValueIsDerivedFromElement): Deleted.
(WebCore::StyleResolver::colorFromPrimitiveValue const): Deleted.
(WebCore::filterOperationForType): Deleted.
(WebCore::StyleResolver::createFilterOperations): Deleted.

Move image mapping functions to BuilderState.

* css/StyleResolver.h:
(WebCore::StyleResolver::State::cssToLengthConversionData const): Deleted.
* html/HTMLInputElement.cpp:
(WebCore::autoFillStrongPasswordMaskImage):
(WebCore::HTMLInputElement::createInnerTextStyle):

Create mask image without requiring style resolver.

* style/StyleBuilder.cpp:
(WebCore::Style::Builder::Builder):
* style/StyleBuilderCustom.h:
(WebCore::Style::BuilderCustom::applyValueZoom):
(WebCore::Style::BuilderCustom::applyValueContent):
(WebCore::Style::BuilderCustom::applyValueFontSize):
(WebCore::Style::BuilderCustom::applyValueAlt):
* style/StyleBuilderState.cpp:
(WebCore::Style::BuilderState::BuilderState):

No more m_styleResolver.

(WebCore::Style::BuilderState::createStyleImage):
(WebCore::Style::filterOperationForType):
(WebCore::Style::BuilderState::createFilterOperations):
(WebCore::Style::BuilderState::isColorFromPrimitiveValueDerivedFromElement):
(WebCore::Style::BuilderState::colorFromPrimitiveValue const):
(WebCore::Style::BuilderState::registerContentAttribute):

Collect content attributes so they can be applied later by StyleResolver.

* style/StyleBuilderState.h:
(WebCore::Style::BuilderState::builder):
(WebCore::Style::BuilderState::rootElementStyle const):

Restore this to be nullable for simplicity.

(WebCore::Style::BuilderState::registeredContentAttributes const):
(WebCore::Style::BuilderState::styleResolver): Deleted.

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

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/css/CSSFilterImageValue.cpp
Source/WebCore/css/CSSFilterImageValue.h
Source/WebCore/css/CSSGradientValue.cpp
Source/WebCore/css/CSSGradientValue.h
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/style/StyleBuilder.cpp
Source/WebCore/style/StyleBuilderCustom.h
Source/WebCore/style/StyleBuilderState.cpp
Source/WebCore/style/StyleBuilderState.h

index dd9e8e2..ac3b0b5 100644 (file)
@@ -1,3 +1,80 @@
+2019-11-01  Antti Koivisto  <antti@apple.com>
+
+        Style::Builder should not depend on StyleResolver
+        https://bugs.webkit.org/show_bug.cgi?id=203729
+
+        Reviewed by Zalan Bujtas.
+
+        With all style building state in builder, we can remove the back-reference to style resolver.
+
+        * css/CSSFilterImageValue.cpp:
+        (WebCore::CSSFilterImageValue::createFilterOperations):
+        * css/CSSFilterImageValue.h:
+        * css/CSSGradientValue.cpp:
+        (WebCore::CSSGradientValue::gradientWithStylesResolved):
+        (WebCore::CSSGradientValue::resolveRGBColors):
+
+        Add helper for resolving basic colors without style builder.
+
+        * css/CSSGradientValue.h:
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::State::clear):
+        (WebCore::StyleResolver::State::State):
+        (WebCore::StyleResolver::State::setStyle):
+        (WebCore::StyleResolver::applyMatchedProperties):
+
+        Register content attributes encountered during style building.
+
+        (WebCore::StyleResolver::State::updateConversionData): Deleted.
+
+        This is now created by BuilderState constructor.
+
+        (WebCore::StyleResolver::styleImage): Deleted.
+        (WebCore::StyleResolver::colorFromPrimitiveValueIsDerivedFromElement): Deleted.
+        (WebCore::StyleResolver::colorFromPrimitiveValue const): Deleted.
+        (WebCore::filterOperationForType): Deleted.
+        (WebCore::StyleResolver::createFilterOperations): Deleted.
+
+        Move image mapping functions to BuilderState.
+
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::State::cssToLengthConversionData const): Deleted.
+        * html/HTMLInputElement.cpp:
+        (WebCore::autoFillStrongPasswordMaskImage):
+        (WebCore::HTMLInputElement::createInnerTextStyle):
+
+        Create mask image without requiring style resolver.
+
+        * style/StyleBuilder.cpp:
+        (WebCore::Style::Builder::Builder):
+        * style/StyleBuilderCustom.h:
+        (WebCore::Style::BuilderCustom::applyValueZoom):
+        (WebCore::Style::BuilderCustom::applyValueContent):
+        (WebCore::Style::BuilderCustom::applyValueFontSize):
+        (WebCore::Style::BuilderCustom::applyValueAlt):
+        * style/StyleBuilderState.cpp:
+        (WebCore::Style::BuilderState::BuilderState):
+
+        No more m_styleResolver.
+
+        (WebCore::Style::BuilderState::createStyleImage):
+        (WebCore::Style::filterOperationForType):
+        (WebCore::Style::BuilderState::createFilterOperations):
+        (WebCore::Style::BuilderState::isColorFromPrimitiveValueDerivedFromElement):
+        (WebCore::Style::BuilderState::colorFromPrimitiveValue const):
+        (WebCore::Style::BuilderState::registerContentAttribute):
+
+        Collect content attributes so they can be applied later by StyleResolver.
+
+        * style/StyleBuilderState.h:
+        (WebCore::Style::BuilderState::builder):
+        (WebCore::Style::BuilderState::rootElementStyle const):
+
+        Restore this to be nullable for simplicity.
+
+        (WebCore::Style::BuilderState::registeredContentAttributes const):
+        (WebCore::Style::BuilderState::styleResolver): Deleted.
+
 2019-11-01  Zan Dobersek  <zdobersek@igalia.com>  and  Chris Lord  <clord@igalia.com>
 
         CanvasRenderingContext2DBase: use CanvasBase more extensively
index dfccf14..e5b8ab4 100644 (file)
@@ -33,8 +33,8 @@
 #include "GraphicsContext.h"
 #include "ImageBuffer.h"
 #include "RenderElement.h"
+#include "StyleBuilderState.h"
 #include "StyleCachedImage.h"
-#include "StyleResolver.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
@@ -140,10 +140,10 @@ void CSSFilterImageValue::filterImageChanged(const IntRect&)
         client.key->imageChanged(static_cast<WrappedImagePtr>(this));
 }
 
-void CSSFilterImageValue::createFilterOperations(StyleResolver* resolver)
+void CSSFilterImageValue::createFilterOperations(Style::BuilderState& builderState)
 {
     m_filterOperations.clear();
-    resolver->createFilterOperations(m_filterValue, m_filterOperations);
+    builderState.createFilterOperations(m_filterValue, m_filterOperations);
 }
 
 void CSSFilterImageValue::FilterSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect)
index d7a486b..3a7b437 100644 (file)
@@ -39,7 +39,10 @@ class CachedImage;
 class FilterSubimageObserverProxy;
 class RenderElement;
 class Document;
-class StyleResolver;
+
+namespace Style {
+class BuilderState;
+}
 
 class CSSFilterImageValue final : public CSSImageGeneratorValue {
     friend class FilterSubimageObserverProxy;
@@ -68,7 +71,7 @@ public:
 
     bool equalInputImages(const CSSFilterImageValue&) const;
 
-    void createFilterOperations(StyleResolver*);
+    void createFilterOperations(Style::BuilderState&);
 
     const FilterOperations& filterOperations() const { return m_filterOperations; }
     void setFilterOperations(const FilterOperations& filterOperations)
index 73298cd..7ace1c5 100644 (file)
@@ -36,7 +36,7 @@
 #include "Pair.h"
 #include "RenderElement.h"
 #include "RenderView.h"
-#include "StyleResolver.h"
+#include "StyleBuilderState.h"
 #include <wtf/text/StringBuilder.h>
 
 namespace WebCore {
@@ -103,33 +103,49 @@ static inline Ref<CSSGradientValue> clone(CSSGradientValue& value)
     return downcast<CSSConicGradientValue>(value).clone();
 }
 
-Ref<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(const StyleResolver& styleResolver)
+template<typename Function>
+void resolveStopColors(Vector<CSSGradientColorStop, 2>& stops, Function&& colorResolveFunction)
 {
-    bool colorIsDerivedFromElement = false;
-    for (auto& stop : m_stops) {
-        if (!stop.isMidpoint && stop.m_color && styleResolver.colorFromPrimitiveValueIsDerivedFromElement(*stop.m_color)) {
-            stop.m_colorIsDerivedFromElement = true;
-            colorIsDerivedFromElement = true;
-            break;
-        }
-    }
-    auto result = colorIsDerivedFromElement ? clone(*this) : makeRef(*this);
-    for (size_t i = 0; i < result->m_stops.size(); ++i) {
-        auto& stop = result->m_stops[i];
+    for (size_t i = 0; i < stops.size(); ++i) {
+        auto& stop = stops[i];
         if (stop.isMidpoint)
             continue;
         if (stop.m_color)
-            stop.m_resolvedColor = styleResolver.colorFromPrimitiveValue(*stop.m_color);
+            stop.m_resolvedColor = colorResolveFunction(*stop.m_color);
         else if (i) {
-            auto& previousStop = result->m_stops[i - 1];
+            auto& previousStop = stops[i - 1];
             ASSERT(previousStop.m_color);
             stop.m_color = previousStop.m_color;
             stop.m_resolvedColor = previousStop.m_resolvedColor;
         }
     }
+}
+
+Ref<CSSGradientValue> CSSGradientValue::gradientWithStylesResolved(Style::BuilderState& builderState)
+{
+    bool colorIsDerivedFromElement = false;
+    for (auto& stop : m_stops) {
+        if (!stop.isMidpoint && stop.m_color && Style::BuilderState::isColorFromPrimitiveValueDerivedFromElement(*stop.m_color)) {
+            stop.m_colorIsDerivedFromElement = true;
+            colorIsDerivedFromElement = true;
+            break;
+        }
+    }
+    auto result = colorIsDerivedFromElement ? clone(*this) : makeRef(*this);
+    resolveStopColors(result->m_stops, [&](const CSSPrimitiveValue& colorValue) {
+        return builderState.colorFromPrimitiveValue(colorValue);
+    });
     return result;
 }
 
+void CSSGradientValue::resolveRGBColors()
+{
+    resolveStopColors(m_stops, [&](const CSSPrimitiveValue& colorValue) {
+        ASSERT(colorValue.isRGBColor());
+        return colorValue.color();
+    });
+}
+
 class LinearGradientAdapter {
 public:
     explicit LinearGradientAdapter(Gradient::LinearData& data)
index 0b6cea7..d75442e 100644 (file)
@@ -35,6 +35,10 @@ namespace WebCore {
 class FloatPoint;
 class StyleResolver;
 
+namespace Style {
+class BuilderState;
+}
+
 enum CSSGradientType {
     CSSDeprecatedLinearGradient,
     CSSDeprecatedRadialGradient,
@@ -86,7 +90,8 @@ public:
     bool knownToBeOpaque(const RenderElement&) const;
 
     void loadSubimages(CachedResourceLoader&, const ResourceLoaderOptions&) { }
-    Ref<CSSGradientValue> gradientWithStylesResolved(const StyleResolver&);
+    Ref<CSSGradientValue> gradientWithStylesResolved(Style::BuilderState&);
+    void resolveRGBColors();
 
 protected:
     CSSGradientValue(ClassType classType, CSSGradientRepeat repeat, CSSGradientType gradientType)
index f361386..d0ffd07 100644 (file)
 #include "config.h"
 #include "StyleResolver.h"
 
-#include "CSSCalculationValue.h"
-#include "CSSCursorImageValue.h"
 #include "CSSDefaultStyleSheets.h"
-#include "CSSFilterImageValue.h"
 #include "CSSFontSelector.h"
-#include "CSSFunctionValue.h"
-#include "CSSGradientValue.h"
-#include "CSSImageSetValue.h"
-#include "CSSImageValue.h"
 #include "CSSKeyframeRule.h"
 #include "CSSKeyframesRule.h"
 #include "CSSParser.h"
 #include "CSSPrimitiveValueMappings.h"
 #include "CSSPropertyNames.h"
-#include "CSSReflectValue.h"
 #include "CSSSelector.h"
-#include "CSSShadowValue.h"
 #include "CSSStyleRule.h"
 #include "CSSStyleSheet.h"
-#include "CSSValueList.h"
 #include "CachedResourceLoader.h"
 #include "ElementRuleCollector.h"
-#include "FilterOperation.h"
 #include "Frame.h"
 #include "FrameSelection.h"
 #include "FrameView.h"
 #include "ShadowRoot.h"
 #include "SharedStringHash.h"
 #include "StyleBuilder.h"
-#include "StyleColor.h"
-#include "StyleCachedImage.h"
 #include "StyleFontSizeFunctions.h"
-#include "StyleGeneratedImage.h"
 #include "StyleProperties.h"
 #include "StylePropertyShorthand.h"
 #include "StyleResolveForDocument.h"
 #include "StyleRule.h"
 #include "StyleSheetContents.h"
-#include "TransformFunctions.h"
-#include "TransformOperations.h"
 #include "UserAgentStyleSheets.h"
 #include "ViewportStyleResolver.h"
 #include "VisitedLinkState.h"
@@ -128,7 +112,6 @@ inline void StyleResolver::State::clear()
     m_element = nullptr;
     m_parentStyle = nullptr;
     m_ownedParentStyle = nullptr;
-    m_cssToLengthConversionData = CSSToLengthConversionData();
 }
 
 StyleResolver::StyleResolver(Document& document)
@@ -249,19 +232,11 @@ StyleResolver::State::State(const Element& element, const RenderStyle* parentSty
         m_rootElementStyle = document.renderStyle();
     else
         m_rootElementStyle = documentElementStyle ? documentElementStyle : documentElement->renderStyle();
-
-    updateConversionData();
-}
-
-inline void StyleResolver::State::updateConversionData()
-{
-    m_cssToLengthConversionData = CSSToLengthConversionData(m_style.get(), m_rootElementStyle, m_element ? m_element->document().renderView() : nullptr);
 }
 
 inline void StyleResolver::State::setStyle(std::unique_ptr<RenderStyle> style)
 {
     m_style = WTFMove(style);
-    updateConversionData();
 }
 
 inline void StyleResolver::State::setParentStyle(std::unique_ptr<RenderStyle> parentStyle)
@@ -1273,6 +1248,9 @@ void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const
 
     builder.applyLowPriorityProperties();
 
+    for (auto& contentAttribute : builder.state().registeredContentAttributes())
+        ruleSets().mutableFeatures().registerContentAttribute(contentAttribute);
+
     if (cacheItem || !cacheHash)
         return;
     if (!isCacheableInMatchedPropertiesCache(*state.element(), state.style(), state.parentStyle()))
@@ -1298,25 +1276,6 @@ void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* valu
     builder.applyPropertyValue(id, *value);
 }
 
-RefPtr<StyleImage> StyleResolver::styleImage(CSSValue& value)
-{
-    if (is<CSSImageGeneratorValue>(value)) {
-        if (is<CSSGradientValue>(value))
-            return StyleGeneratedImage::create(downcast<CSSGradientValue>(value).gradientWithStylesResolved(*this));
-
-        if (is<CSSFilterImageValue>(value)) {
-            // FilterImage needs to calculate FilterOperations.
-            downcast<CSSFilterImageValue>(value).createFilterOperations(this);
-        }
-        return StyleGeneratedImage::create(downcast<CSSImageGeneratorValue>(value));
-    }
-
-    if (is<CSSImageValue>(value) || is<CSSImageSetValue>(value) || is<CSSCursorImageValue>(value))
-        return StyleCachedImage::create(value);
-
-    return nullptr;
-}
-
 void StyleResolver::initializeFontStyle()
 {
     FontCascadeDescription fontDescription;
@@ -1332,44 +1291,6 @@ void StyleResolver::initializeFontStyle()
     style()->setFontDescription(WTFMove(fontDescription));
 }
 
-bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimitiveValue& value)
-{
-    switch (value.valueID()) {
-    case CSSValueWebkitText:
-    case CSSValueWebkitLink:
-    case CSSValueWebkitActivelink:
-    case CSSValueCurrentcolor:
-        return true;
-    default:
-        return false;
-    }
-}
-
-Color StyleResolver::colorFromPrimitiveValue(const CSSPrimitiveValue& value, bool forVisitedLink) const
-{
-    if (value.isRGBColor())
-        return value.color();
-
-    auto identifier = value.valueID();
-    switch (identifier) {
-    case CSSValueWebkitText:
-        return document().textColor();
-    case CSSValueWebkitLink:
-        return (m_state.element()->isLink() && forVisitedLink) ? document().visitedLinkColor() : document().linkColor();
-    case CSSValueWebkitActivelink:
-        return document().activeLinkColor();
-    case CSSValueWebkitFocusRingColor:
-        return RenderTheme::singleton().focusRingColor(document().styleColorOptions(m_state.style()));
-    case CSSValueCurrentcolor:
-        // Color is an inherited property so depending on it effectively makes the property inherited.
-        // FIXME: Setting the flag as a side effect of calling this function is a bit oblique. Can we do better?
-        m_state.style()->setHasExplicitlyInheritedProperties();
-        return m_state.style()->color();
-    default:
-        return StyleColor::colorFromKeyword(identifier, document().styleColorOptions(m_state.style()));
-    }
-}
-
 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExpression& expression, bool result)
 {
     m_viewportDependentMediaQueryResults.append(MediaQueryResult { expression, result });
@@ -1415,171 +1336,4 @@ bool StyleResolver::hasMediaQueriesAffectedByAppearanceChange() const
     return false;
 }
 
-static FilterOperation::OperationType filterOperationForType(CSSValueID type)
-{
-    switch (type) {
-    case CSSValueUrl:
-        return FilterOperation::REFERENCE;
-    case CSSValueGrayscale:
-        return FilterOperation::GRAYSCALE;
-    case CSSValueSepia:
-        return FilterOperation::SEPIA;
-    case CSSValueSaturate:
-        return FilterOperation::SATURATE;
-    case CSSValueHueRotate:
-        return FilterOperation::HUE_ROTATE;
-    case CSSValueInvert:
-        return FilterOperation::INVERT;
-    case CSSValueAppleInvertLightness:
-        return FilterOperation::APPLE_INVERT_LIGHTNESS;
-    case CSSValueOpacity:
-        return FilterOperation::OPACITY;
-    case CSSValueBrightness:
-        return FilterOperation::BRIGHTNESS;
-    case CSSValueContrast:
-        return FilterOperation::CONTRAST;
-    case CSSValueBlur:
-        return FilterOperation::BLUR;
-    case CSSValueDropShadow:
-        return FilterOperation::DROP_SHADOW;
-    default:
-        break;
-    }
-    ASSERT_NOT_REACHED();
-    return FilterOperation::NONE;
-}
-
-bool StyleResolver::createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations)
-{
-    State& state = m_state;
-    ASSERT(outOperations.isEmpty());
-
-    if (is<CSSPrimitiveValue>(inValue)) {
-        auto& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
-        if (primitiveValue.valueID() == CSSValueNone)
-            return true;
-    }
-
-    if (!is<CSSValueList>(inValue))
-        return false;
-
-    FilterOperations operations;
-    for (auto& currentValue : downcast<CSSValueList>(inValue)) {
-
-        if (is<CSSPrimitiveValue>(currentValue)) {
-            auto& primitiveValue = downcast<CSSPrimitiveValue>(currentValue.get());
-            if (!primitiveValue.isURI())
-                continue;
-
-            String cssUrl = primitiveValue.stringValue();
-            URL url = document().completeURL(cssUrl);
-
-            auto operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
-            operations.operations().append(WTFMove(operation));
-            continue;
-        }
-
-        if (!is<CSSFunctionValue>(currentValue))
-            continue;
-
-        auto& filterValue = downcast<CSSFunctionValue>(currentValue.get());
-        FilterOperation::OperationType operationType = filterOperationForType(filterValue.name());
-
-        // Check that all parameters are primitive values, with the
-        // exception of drop shadow which has a CSSShadowValue parameter.
-        const CSSPrimitiveValue* firstValue = nullptr;
-        if (operationType != FilterOperation::DROP_SHADOW) {
-            bool haveNonPrimitiveValue = false;
-            for (unsigned j = 0; j < filterValue.length(); ++j) {
-                if (!is<CSSPrimitiveValue>(*filterValue.itemWithoutBoundsCheck(j))) {
-                    haveNonPrimitiveValue = true;
-                    break;
-                }
-            }
-            if (haveNonPrimitiveValue)
-                continue;
-            if (filterValue.length())
-                firstValue = downcast<CSSPrimitiveValue>(filterValue.itemWithoutBoundsCheck(0));
-        }
-
-        switch (operationType) {
-        case FilterOperation::GRAYSCALE:
-        case FilterOperation::SEPIA:
-        case FilterOperation::SATURATE: {
-            double amount = 1;
-            if (filterValue.length() == 1) {
-                amount = firstValue->doubleValue();
-                if (firstValue->isPercentage())
-                    amount /= 100;
-            }
-
-            operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
-            break;
-        }
-        case FilterOperation::HUE_ROTATE: {
-            double angle = 0;
-            if (filterValue.length() == 1)
-                angle = firstValue->computeDegrees();
-
-            operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
-            break;
-        }
-        case FilterOperation::INVERT:
-        case FilterOperation::BRIGHTNESS:
-        case FilterOperation::CONTRAST:
-        case FilterOperation::OPACITY: {
-            double amount = 1;
-            if (filterValue.length() == 1) {
-                amount = firstValue->doubleValue();
-                if (firstValue->isPercentage())
-                    amount /= 100;
-            }
-
-            operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
-            break;
-        }
-        case FilterOperation::APPLE_INVERT_LIGHTNESS: {
-            operations.operations().append(InvertLightnessFilterOperation::create());
-            break;
-        }
-        case FilterOperation::BLUR: {
-            Length stdDeviation = Length(0, Fixed);
-            if (filterValue.length() >= 1)
-                stdDeviation = convertToFloatLength(firstValue, state.cssToLengthConversionData());
-            if (stdDeviation.isUndefined())
-                return false;
-
-            operations.operations().append(BlurFilterOperation::create(stdDeviation));
-            break;
-        }
-        case FilterOperation::DROP_SHADOW: {
-            if (filterValue.length() != 1)
-                return false;
-
-            const auto* cssValue = filterValue.itemWithoutBoundsCheck(0);
-            if (!is<CSSShadowValue>(cssValue))
-                continue;
-
-            const auto& item = downcast<CSSShadowValue>(*cssValue);
-            int x = item.x->computeLength<int>(state.cssToLengthConversionData());
-            int y = item.y->computeLength<int>(state.cssToLengthConversionData());
-            IntPoint location(x, y);
-            int blur = item.blur ? item.blur->computeLength<int>(state.cssToLengthConversionData()) : 0;
-            Color color;
-            if (item.color)
-                color = colorFromPrimitiveValue(*item.color);
-
-            operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent));
-            break;
-        }
-        default:
-            ASSERT_NOT_REACHED();
-            break;
-        }
-    }
-
-    outOperations = operations;
-    return true;
-}
-
 } // namespace WebCore
index f9fc374..ddc5127 100644 (file)
@@ -22,8 +22,6 @@
 #pragma once
 
 #include "CSSSelector.h"
-#include "CSSToLengthConversionData.h"
-#include "CSSToStyleMap.h"
 #include "DocumentRuleSets.h"
 #include "ElementRuleCollector.h"
 #include "InspectorCSSOMWrappers.h"
@@ -159,9 +157,6 @@ public:
 
     void initializeFontStyle();
 
-    static bool colorFromPrimitiveValueIsDerivedFromElement(const CSSPrimitiveValue&);
-    Color colorFromPrimitiveValue(const CSSPrimitiveValue&, bool forVisitedLink = false) const;
-
     bool hasSelectorForId(const AtomString&) const;
     bool hasSelectorForAttribute(const Element&, const AtomString&) const;
 
@@ -190,14 +185,10 @@ public:
 
     void clearCachedPropertiesAffectedByViewportUnits();
 
-    bool createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations);
-
 private:
     void adjustRenderStyle(RenderStyle&, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const Element*);
     void adjustRenderStyleForSiteSpecificQuirks(RenderStyle&, const Element&);
-    
-    void adjustStyleForInterCharacterRuby();
-    
+        
     enum ShouldUseMatchedPropertiesCache { DoNotUseMatchedPropertiesCache = 0, UseMatchedPropertiesCache };
     void applyMatchedProperties(const MatchResult&, const Element&, ShouldUseMatchedPropertiesCache = UseMatchedPropertiesCache);
 
@@ -233,13 +224,9 @@ public:
         FillLayer backgroundData() const { return m_backgroundData; }
         const Color& backgroundColor() const { return m_backgroundColor; }
 
-        const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; }
-
         const SelectorFilter* selectorFilter() const { return m_selectorFilter; }
         
     private:
-        void updateConversionData();
-
         const Element* m_element { nullptr };
         std::unique_ptr<RenderStyle> m_style;
         const RenderStyle* m_parentStyle { nullptr };
@@ -252,16 +239,12 @@ public:
         FillLayer m_backgroundData { FillLayerType::Background };
         Color m_backgroundColor;
 
-        CSSToLengthConversionData m_cssToLengthConversionData;
-
         bool m_hasUAAppearance { false };
     };
 
     State& state() { return m_state; }
     const State& state() const { return m_state; }
 
-    RefPtr<StyleImage> styleImage(CSSValue&);
-
     InspectorCSSOMWrappers& inspectorCSSOMWrappers() { return m_inspectorCSSOMWrappers; }
 
     bool adjustRenderStyleForTextAutosizing(RenderStyle&, const Element&);
@@ -269,8 +252,6 @@ public:
 private:
     void cacheBorderAndBackground();
 
-    void applySVGProperty(CSSPropertyID, CSSValue*);
-
     static unsigned computeMatchedPropertiesHash(const MatchResult&);
     struct MatchedPropertiesCacheItem {
         Vector<MatchedProperties> userAgentDeclarations;
index ddf55b7..4aff7f1 100644 (file)
@@ -62,7 +62,7 @@
 #include "ScopedEventQueue.h"
 #include "SearchInputType.h"
 #include "Settings.h"
-#include "StyleResolver.h"
+#include "StyleGeneratedImage.h"
 #include "TextControlInnerElements.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/Language.h>
@@ -2066,6 +2066,8 @@ static Ref<CSSLinearGradientValue> autoFillStrongPasswordMaskImage()
     gradient->setAngle(CSSValuePool::singleton().createValue(90, CSSPrimitiveValue::UnitType::CSS_DEG));
     gradient->addStop(firstStop);
     gradient->addStop(secondStop);
+    gradient->resolveRGBColors();
+
     return gradient;
 }
 
@@ -2088,7 +2090,7 @@ RenderStyle HTMLInputElement::createInnerTextStyle(const RenderStyle& style)
         textBlockStyle.setMaxWidth(Length { 100, Percent });
         textBlockStyle.setColor({ 0.0f, 0.0f, 0.0f, 0.6f });
         textBlockStyle.setTextOverflow(TextOverflow::Clip);
-        textBlockStyle.setMaskImage(styleResolver().styleImage(autoFillStrongPasswordMaskImage()));
+        textBlockStyle.setMaskImage(StyleGeneratedImage::create(autoFillStrongPasswordMaskImage()));
         // A stacking context is needed for the mask.
         if (textBlockStyle.hasAutoZIndex())
             textBlockStyle.setZIndex(0);
index 9c7107a..2b8ea9a 100644 (file)
@@ -34,6 +34,7 @@
 #include "Settings.h"
 #include "StyleBuilderGenerated.h"
 #include "StyleFontSizeFunctions.h"
+#include "StyleResolver.h"
 
 namespace WebCore {
 namespace Style {
@@ -47,8 +48,10 @@ static PropertyCascade::Direction directionFromStyle(const RenderStyle& style)
 
 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)
+    , m_state(*this, *resolver.style(), *resolver.parentStyle(), resolver.rootElementStyle(), resolver.document(), resolver.element())
 {
+    ASSERT(resolver.style());
+    ASSERT(resolver.parentStyle());
 }
 
 Builder::~Builder() = default;
index ed0976b..24e9751 100644 (file)
@@ -219,7 +219,7 @@ inline void BuilderCustom::applyValueZoom(BuilderState& builderState, CSSValue&
         builderState.setEffectiveZoom(RenderStyle::initialZoom());
         builderState.setZoom(RenderStyle::initialZoom());
     } else if (primitiveValue.valueID() == CSSValueDocument) {
-        float docZoom = builderState.rootElementStyle().zoom();
+        float docZoom = builderState.rootElementStyle() ? builderState.rootElementStyle()->zoom() : RenderStyle::initialZoom();
         builderState.setEffectiveZoom(docZoom);
         builderState.setZoom(docZoom);
     } else if (primitiveValue.isPercentage()) {
@@ -1320,7 +1320,7 @@ inline void BuilderCustom::applyValueContent(BuilderState& builderState, CSSValu
     for (auto& item : downcast<CSSValueList>(value)) {
         if (is<CSSImageGeneratorValue>(item)) {
             if (is<CSSGradientValue>(item))
-                builderState.style().setContent(StyleGeneratedImage::create(downcast<CSSGradientValue>(item.get()).gradientWithStylesResolved(builderState.styleResolver())), didSet);
+                builderState.style().setContent(StyleGeneratedImage::create(downcast<CSSGradientValue>(item.get()).gradientWithStylesResolved(builderState)), didSet);
             else
                 builderState.style().setContent(StyleGeneratedImage::create(downcast<CSSImageGeneratorValue>(item.get())), didSet);
             didSet = true;
@@ -1353,7 +1353,7 @@ inline void BuilderCustom::applyValueContent(BuilderState& builderState, CSSValu
             builderState.style().setContent(value.isNull() ? emptyAtom() : value.impl(), didSet);
             didSet = true;
             // Register the fact that the attribute value affects the style.
-            builderState.styleResolver().ruleSets().mutableFeatures().registerContentAttribute(attr.localName());
+            builderState.registerContentAttribute(attr.localName());
         } else if (contentValue.isCounter()) {
             auto* counterValue = contentValue.counterValue();
             ListStyleType listStyleType = ListStyleType::None;
@@ -1611,7 +1611,7 @@ inline void BuilderCustom::applyValueFontSize(BuilderState& builderState, CSSVal
     } else {
         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));
+            size = primitiveValue.computeLength<float>(CSSToLengthConversionData(&builderState.parentStyle(), builderState.rootElementStyle(), builderState.document().renderView(), 1.0f, true));
             if (primitiveValue.isViewportPercentageLength())
                 builderState.style().setHasViewportUnits();
         } else if (primitiveValue.isPercentage())
@@ -1747,7 +1747,7 @@ void BuilderCustom::applyValueAlt(BuilderState& builderState, CSSValue& value)
         builderState.style().setContentAltText(value.isNull() ? emptyAtom() : value);
 
         // Register the fact that the attribute value affects the style.
-        builderState.styleResolver().ruleSets().mutableFeatures().registerContentAttribute(attr.localName());
+        builderState.registerContentAttribute(attr.localName());
     } else
         builderState.style().setContentAltText(emptyAtom());
 }
index 9356df1..e7af1b9 100644 (file)
 #include "config.h"
 #include "StyleBuilderState.h"
 
+#include "CSSCursorImageValue.h"
+#include "CSSFilterImageValue.h"
+#include "CSSFunctionValue.h"
+#include "CSSGradientValue.h"
+#include "CSSImageSetValue.h"
+#include "CSSImageValue.h"
+#include "CSSShadowValue.h"
+#include "RenderTheme.h"
 #include "SVGElement.h"
 #include "SVGSVGElement.h"
 #include "StyleBuilder.h"
-#include "StyleResolver.h"
+#include "StyleCachedImage.h"
+#include "StyleGeneratedImage.h"
+#include "TransformFunctions.h"
 
 namespace WebCore {
 namespace Style {
 
-BuilderState::BuilderState(Builder& builder, StyleResolver& styleResolver)
+BuilderState::BuilderState(Builder& builder, RenderStyle& style, const RenderStyle& parentStyle, const RenderStyle* rootElementStyle, const Document& document, const Element* element)
     : m_builder(builder)
     , m_styleMap(*this)
-    , m_cssToLengthConversionData(styleResolver.state().cssToLengthConversionData())
-    , m_styleResolver(styleResolver)
-    , m_style(*styleResolver.style())
-    , m_parentStyle(*styleResolver.parentStyle())
-    , m_rootElementStyle(styleResolver.rootElementStyle() ? *styleResolver.rootElementStyle() : RenderStyle::defaultStyle())
-    , m_document(m_styleResolver.document())
-    , m_element(m_styleResolver.element())
+    , m_style(style)
+    , m_parentStyle(parentStyle)
+    , m_rootElementStyle(rootElementStyle)
+    , m_cssToLengthConversionData(&style, rootElementStyle, document.renderView())
+    , m_document(document)
+    , m_element(element)
 {
-    ASSERT(styleResolver.style());
-    ASSERT(styleResolver.parentStyle());
 }
 
 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
@@ -73,17 +80,233 @@ bool BuilderState::useSVGZoomRulesForLength() const
 
 RefPtr<StyleImage> BuilderState::createStyleImage(CSSValue& value)
 {
-    return m_styleResolver.styleImage(value);
+    if (is<CSSImageGeneratorValue>(value)) {
+        if (is<CSSGradientValue>(value))
+            return StyleGeneratedImage::create(downcast<CSSGradientValue>(value).gradientWithStylesResolved(*this));
+
+        if (is<CSSFilterImageValue>(value)) {
+            // FilterImage needs to calculate FilterOperations.
+            downcast<CSSFilterImageValue>(value).createFilterOperations(*this);
+        }
+        return StyleGeneratedImage::create(downcast<CSSImageGeneratorValue>(value));
+    }
+
+    if (is<CSSImageValue>(value) || is<CSSImageSetValue>(value) || is<CSSCursorImageValue>(value))
+        return StyleCachedImage::create(value);
+
+    return nullptr;
+}
+
+static FilterOperation::OperationType filterOperationForType(CSSValueID type)
+{
+    switch (type) {
+    case CSSValueUrl:
+        return FilterOperation::REFERENCE;
+    case CSSValueGrayscale:
+        return FilterOperation::GRAYSCALE;
+    case CSSValueSepia:
+        return FilterOperation::SEPIA;
+    case CSSValueSaturate:
+        return FilterOperation::SATURATE;
+    case CSSValueHueRotate:
+        return FilterOperation::HUE_ROTATE;
+    case CSSValueInvert:
+        return FilterOperation::INVERT;
+    case CSSValueAppleInvertLightness:
+        return FilterOperation::APPLE_INVERT_LIGHTNESS;
+    case CSSValueOpacity:
+        return FilterOperation::OPACITY;
+    case CSSValueBrightness:
+        return FilterOperation::BRIGHTNESS;
+    case CSSValueContrast:
+        return FilterOperation::CONTRAST;
+    case CSSValueBlur:
+        return FilterOperation::BLUR;
+    case CSSValueDropShadow:
+        return FilterOperation::DROP_SHADOW;
+    default:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return FilterOperation::NONE;
 }
 
-bool BuilderState::createFilterOperations(const CSSValue& value, FilterOperations& outOperations)
+bool BuilderState::createFilterOperations(const CSSValue& inValue, FilterOperations& outOperations)
 {
-    return m_styleResolver.createFilterOperations(value, outOperations);
+    // FIXME: Move this code somewhere else.
+
+    ASSERT(outOperations.isEmpty());
+
+    if (is<CSSPrimitiveValue>(inValue)) {
+        auto& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
+        if (primitiveValue.valueID() == CSSValueNone)
+            return true;
+    }
+
+    if (!is<CSSValueList>(inValue))
+        return false;
+
+    FilterOperations operations;
+    for (auto& currentValue : downcast<CSSValueList>(inValue)) {
+
+        if (is<CSSPrimitiveValue>(currentValue)) {
+            auto& primitiveValue = downcast<CSSPrimitiveValue>(currentValue.get());
+            if (!primitiveValue.isURI())
+                continue;
+
+            String cssUrl = primitiveValue.stringValue();
+            URL url = document().completeURL(cssUrl);
+
+            auto operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
+            operations.operations().append(WTFMove(operation));
+            continue;
+        }
+
+        if (!is<CSSFunctionValue>(currentValue))
+            continue;
+
+        auto& filterValue = downcast<CSSFunctionValue>(currentValue.get());
+        FilterOperation::OperationType operationType = filterOperationForType(filterValue.name());
+
+        // Check that all parameters are primitive values, with the
+        // exception of drop shadow which has a CSSShadowValue parameter.
+        const CSSPrimitiveValue* firstValue = nullptr;
+        if (operationType != FilterOperation::DROP_SHADOW) {
+            bool haveNonPrimitiveValue = false;
+            for (unsigned j = 0; j < filterValue.length(); ++j) {
+                if (!is<CSSPrimitiveValue>(*filterValue.itemWithoutBoundsCheck(j))) {
+                    haveNonPrimitiveValue = true;
+                    break;
+                }
+            }
+            if (haveNonPrimitiveValue)
+                continue;
+            if (filterValue.length())
+                firstValue = downcast<CSSPrimitiveValue>(filterValue.itemWithoutBoundsCheck(0));
+        }
+
+        switch (operationType) {
+        case FilterOperation::GRAYSCALE:
+        case FilterOperation::SEPIA:
+        case FilterOperation::SATURATE: {
+            double amount = 1;
+            if (filterValue.length() == 1) {
+                amount = firstValue->doubleValue();
+                if (firstValue->isPercentage())
+                    amount /= 100;
+            }
+
+            operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
+            break;
+        }
+        case FilterOperation::HUE_ROTATE: {
+            double angle = 0;
+            if (filterValue.length() == 1)
+                angle = firstValue->computeDegrees();
+
+            operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
+            break;
+        }
+        case FilterOperation::INVERT:
+        case FilterOperation::BRIGHTNESS:
+        case FilterOperation::CONTRAST:
+        case FilterOperation::OPACITY: {
+            double amount = 1;
+            if (filterValue.length() == 1) {
+                amount = firstValue->doubleValue();
+                if (firstValue->isPercentage())
+                    amount /= 100;
+            }
+
+            operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
+            break;
+        }
+        case FilterOperation::APPLE_INVERT_LIGHTNESS: {
+            operations.operations().append(InvertLightnessFilterOperation::create());
+            break;
+        }
+        case FilterOperation::BLUR: {
+            Length stdDeviation = Length(0, Fixed);
+            if (filterValue.length() >= 1)
+                stdDeviation = convertToFloatLength(firstValue, cssToLengthConversionData());
+            if (stdDeviation.isUndefined())
+                return false;
+
+            operations.operations().append(BlurFilterOperation::create(stdDeviation));
+            break;
+        }
+        case FilterOperation::DROP_SHADOW: {
+            if (filterValue.length() != 1)
+                return false;
+
+            const auto* cssValue = filterValue.itemWithoutBoundsCheck(0);
+            if (!is<CSSShadowValue>(cssValue))
+                continue;
+
+            const auto& item = downcast<CSSShadowValue>(*cssValue);
+            int x = item.x->computeLength<int>(cssToLengthConversionData());
+            int y = item.y->computeLength<int>(cssToLengthConversionData());
+            IntPoint location(x, y);
+            int blur = item.blur ? item.blur->computeLength<int>(cssToLengthConversionData()) : 0;
+            Color color;
+            if (item.color)
+                color = colorFromPrimitiveValue(*item.color);
+
+            operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent));
+            break;
+        }
+        default:
+            ASSERT_NOT_REACHED();
+            break;
+        }
+    }
+
+    outOperations = operations;
+    return true;
+}
+
+bool BuilderState::isColorFromPrimitiveValueDerivedFromElement(const CSSPrimitiveValue& value)
+{
+    switch (value.valueID()) {
+    case CSSValueWebkitText:
+    case CSSValueWebkitLink:
+    case CSSValueWebkitActivelink:
+    case CSSValueCurrentcolor:
+        return true;
+    default:
+        return false;
+    }
 }
 
 Color BuilderState::colorFromPrimitiveValue(const CSSPrimitiveValue& value, bool forVisitedLink) const
 {
-    return m_styleResolver.colorFromPrimitiveValue(value, forVisitedLink);
+    if (value.isRGBColor())
+        return value.color();
+
+    auto identifier = value.valueID();
+    switch (identifier) {
+    case CSSValueWebkitText:
+        return document().textColor();
+    case CSSValueWebkitLink:
+        return (element() && element()->isLink() && forVisitedLink) ? document().visitedLinkColor() : document().linkColor();
+    case CSSValueWebkitActivelink:
+        return document().activeLinkColor();
+    case CSSValueWebkitFocusRingColor:
+        return RenderTheme::singleton().focusRingColor(document().styleColorOptions(&m_style));
+    case CSSValueCurrentcolor:
+        // Color is an inherited property so depending on it effectively makes the property inherited.
+        // FIXME: Setting the flag as a side effect of calling this function is a bit oblique. Can we do better?
+        m_style.setHasExplicitlyInheritedProperties();
+        return m_style.color();
+    default:
+        return StyleColor::colorFromKeyword(identifier, document().styleColorOptions(&m_style));
+    }
+}
+
+void BuilderState::registerContentAttribute(const AtomString& attributeLocalName)
+{
+    if (style().styleType() == PseudoId::Before || style().styleType() == PseudoId::After)
+        m_registeredContentAttributes.append(attributeLocalName);
 }
 
 void BuilderState::adjustStyleForInterCharacterRuby()
index e7b99ca..e5864ef 100644 (file)
@@ -43,14 +43,13 @@ class Builder;
 
 class BuilderState {
 public:
-    BuilderState(Builder&, StyleResolver&);
+    BuilderState(Builder&, RenderStyle&, const RenderStyle& parentStyle, const RenderStyle* rootElementStyle, const Document&, const Element*);
 
     Builder& builder() { return m_builder; }
-    StyleResolver& styleResolver() { return m_styleResolver; }
 
     RenderStyle& style() { return m_style; }
     const RenderStyle& parentStyle() const { return m_parentStyle; }
-    const RenderStyle& rootElementStyle() const { return m_rootElementStyle; }
+    const RenderStyle* rootElementStyle() const { return m_rootElementStyle; }
 
     const Document& document() const { return m_document.get(); }
     const Element* element() const { return m_element.get(); }
@@ -78,8 +77,13 @@ public:
 
     RefPtr<StyleImage> createStyleImage(CSSValue&);
     bool createFilterOperations(const CSSValue&, FilterOperations& outOperations);
+
+    static bool isColorFromPrimitiveValueDerivedFromElement(const CSSPrimitiveValue&);
     Color colorFromPrimitiveValue(const CSSPrimitiveValue&, bool forVisitedLink = false) const;
 
+    const Vector<AtomString>& registeredContentAttributes() const { return m_registeredContentAttributes; }
+    void registerContentAttribute(const AtomString& attributeLocalName);
+
     const CSSToLengthConversionData& cssToLengthConversionData() const { return m_cssToLengthConversionData; }
     CSSToStyleMap& styleMap() { return m_styleMap; }
 
@@ -99,14 +103,12 @@ private:
     Builder& m_builder;
 
     CSSToStyleMap m_styleMap;
-    CSSToLengthConversionData m_cssToLengthConversionData;
-
-    // FIXME: Remove.
-    StyleResolver& m_styleResolver;
 
     RenderStyle& m_style;
     const RenderStyle& m_parentStyle;
-    const RenderStyle& m_rootElementStyle;
+    const RenderStyle* m_rootElementStyle;
+
+    const CSSToLengthConversionData m_cssToLengthConversionData;
 
     Ref<const Document> m_document;
     RefPtr<const Element> m_element;
@@ -121,6 +123,7 @@ private:
     SelectorChecker::LinkMatchMask m_linkMatch { };
 
     bool m_fontDirty { false };
+    Vector<AtomString> m_registeredContentAttributes;
 };
 
 }