From ea05e83e61422ff0c4a68c659f9a99aa14064121 Mon Sep 17 00:00:00 2001 From: Said Abou-Hallawa Date: Tue, 18 Oct 2022 17:26:50 -0700 Subject: [PATCH] Move BuilderState::createFilterOperations() to a separate file https://bugs.webkit.org/show_bug.cgi?id=246675 Reviewed by Antti Koivisto. Make this function a stand-alone function and make used by the CSS style builder. The plan is to use this function the 2D canvas for the filter API. * Source/WebCore/Sources.txt: * Source/WebCore/WebCore.xcodeproj/project.pbxproj: * Source/WebCore/css/CSSFilterImageValue.cpp: (WebCore::CSSFilterImageValue::createFilterOperations): * Source/WebCore/style/ColorFromPrimitiveValue.cpp: Added. (WebCore::colorFromPrimitiveValue): (WebCore::colorFromPrimitiveValueWithResolvedCurrentColor): * Source/WebCore/style/ColorFromPrimitiveValue.h: Added. * Source/WebCore/style/FilterOperationsBuilder.cpp: Added. (WebCore::filterOperationForType): (WebCore::createFilterOperations): * Source/WebCore/style/FilterOperationsBuilder.h: Added. * Source/WebCore/style/StyleBuilderConverter.h: (WebCore::Style::BuilderConverter::convertFilterOperations): * Source/WebCore/style/StyleBuilderState.cpp: (WebCore::Style::BuilderState::createFilterOperations): (WebCore::Style::BuilderState::colorFromPrimitiveValue const): (WebCore::Style::BuilderState::colorFromPrimitiveValueWithResolvedCurrentColor const): (WebCore::Style::filterOperationForType): Deleted. * Source/WebCore/style/StyleBuilderState.h: Canonical link: https://commits.webkit.org/255706@main --- Source/WebCore/Sources.txt | 2 + .../WebCore/WebCore.xcodeproj/project.pbxproj | 8 + Source/WebCore/css/CSSFilterImageValue.cpp | 6 +- .../WebCore/style/ColorFromPrimitiveValue.cpp | 77 +++++++ .../WebCore/style/ColorFromPrimitiveValue.h | 46 ++++ .../WebCore/style/FilterOperationsBuilder.cpp | 201 ++++++++++++++++++ .../WebCore/style/FilterOperationsBuilder.h | 41 ++++ Source/WebCore/style/StyleBuilderConverter.h | 5 +- Source/WebCore/style/StyleBuilderState.cpp | 197 +---------------- Source/WebCore/style/StyleBuilderState.h | 4 +- 10 files changed, 391 insertions(+), 196 deletions(-) create mode 100644 Source/WebCore/style/ColorFromPrimitiveValue.cpp create mode 100644 Source/WebCore/style/ColorFromPrimitiveValue.h create mode 100644 Source/WebCore/style/FilterOperationsBuilder.cpp create mode 100644 Source/WebCore/style/FilterOperationsBuilder.h diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt index 93da2e18d76c..daa4637dca20 100644 --- a/Source/WebCore/Sources.txt +++ b/Source/WebCore/Sources.txt @@ -2674,8 +2674,10 @@ storage/StorageQuotaManager.cpp style/AttributeChangeInvalidation.cpp style/ChildChangeInvalidation.cpp style/ClassChangeInvalidation.cpp +style/ColorFromPrimitiveValue.cpp style/ContainerQueryEvaluator.cpp style/ElementRuleCollector.cpp +style/FilterOperationsBuilder.cpp style/HasSelectorFilter.cpp style/IdChangeInvalidation.cpp style/InlineTextBoxStyle.cpp diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj index 98d4034a9045..861910a53f65 100644 --- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj @@ -11829,6 +11829,10 @@ 72C11DAB28492A9200E826DD /* ByteArrayPixelBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ByteArrayPixelBuffer.cpp; sourceTree = ""; }; 72C11DAC28492A9200E826DD /* ByteArrayPixelBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ByteArrayPixelBuffer.h; sourceTree = ""; }; 72C18A3F230B04B7006847C7 /* ImagePaintingOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImagePaintingOptions.h; sourceTree = ""; }; + 72CDE0DF28FE21700059719E /* FilterOperationsBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FilterOperationsBuilder.cpp; sourceTree = ""; }; + 72CDE0E028FE21700059719E /* FilterOperationsBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterOperationsBuilder.h; sourceTree = ""; }; + 72CDE0E128FE23000059719E /* ColorFromPrimitiveValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorFromPrimitiveValue.cpp; sourceTree = ""; }; + 72CDE0E228FE23000059719E /* ColorFromPrimitiveValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorFromPrimitiveValue.h; sourceTree = ""; }; 72E417611A2E8D2F004C562A /* JSEXTsRGB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEXTsRGB.cpp; sourceTree = ""; }; 72E417621A2E8D2F004C562A /* JSEXTsRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEXTsRGB.h; sourceTree = ""; }; 72E5768A281B292600A75432 /* CopyImageOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CopyImageOptions.h; sourceTree = ""; }; @@ -32355,10 +32359,14 @@ E4C4C61827452A7900A040E7 /* ChildChangeInvalidation.h */, E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */, E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */, + 72CDE0E128FE23000059719E /* ColorFromPrimitiveValue.cpp */, + 72CDE0E228FE23000059719E /* ColorFromPrimitiveValue.h */, E4AAB38827AA95E0009F5899 /* ContainerQueryEvaluator.cpp */, E4AAB38527AA95D7009F5899 /* ContainerQueryEvaluator.h */, FBDB619A16D6032A00BB3394 /* ElementRuleCollector.cpp */, FBDB619E16D6036500BB3394 /* ElementRuleCollector.h */, + 72CDE0DF28FE21700059719E /* FilterOperationsBuilder.cpp */, + 72CDE0E028FE21700059719E /* FilterOperationsBuilder.h */, E4ED3ECD2768A68800F17AC8 /* HasSelectorFilter.cpp */, E4ED3ECA2768A51C00F17AC8 /* HasSelectorFilter.h */, E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */, diff --git a/Source/WebCore/css/CSSFilterImageValue.cpp b/Source/WebCore/css/CSSFilterImageValue.cpp index 0cc979e73f2a..024cc727b2e7 100644 --- a/Source/WebCore/css/CSSFilterImageValue.cpp +++ b/Source/WebCore/css/CSSFilterImageValue.cpp @@ -142,8 +142,10 @@ void CSSFilterImageValue::filterImageChanged(const IntRect&) void CSSFilterImageValue::createFilterOperations(Style::BuilderState& builderState) { - m_filterOperations.clear(); - builderState.createFilterOperations(m_filterValue, m_filterOperations); + if (auto filterOperations = builderState.createFilterOperations(m_filterValue)) + m_filterOperations = WTFMove(*filterOperations); + else + m_filterOperations.clear(); } void CSSFilterImageValue::FilterSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect) diff --git a/Source/WebCore/style/ColorFromPrimitiveValue.cpp b/Source/WebCore/style/ColorFromPrimitiveValue.cpp new file mode 100644 index 000000000000..e5407a5b1979 --- /dev/null +++ b/Source/WebCore/style/ColorFromPrimitiveValue.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022 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. ``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 + * 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. + */ + +#include "config.h" +#include "ColorFromPrimitiveValue.h" + +#include "CSSPrimitiveValue.h" +#include "Document.h" +#include "RenderStyle.h" +#include "RenderTheme.h" +#include "StyleBuilderState.h" +#include "StyleColor.h" + +namespace WebCore { + +namespace Style { + +StyleColor colorFromPrimitiveValue(const Document& document, RenderStyle& style, const CSSPrimitiveValue& value, ForVisitedLink forVisitedLink) +{ + if (value.isRGBColor()) + return value.color(); + + auto identifier = value.valueID(); + switch (identifier) { + case CSSValueInternalDocumentTextColor: + return { document.textColor() }; + case CSSValueWebkitLink: + return { forVisitedLink == ForVisitedLink::Yes ? document.visitedLinkColor() : document.linkColor() }; + case CSSValueWebkitActivelink: + return { document.activeLinkColor() }; + case CSSValueWebkitFocusRingColor: + return { RenderTheme::singleton().focusRingColor(document.styleColorOptions(&style)) }; + case CSSValueCurrentcolor: + return StyleColor::currentColor(); + default: + return { StyleColor::colorFromKeyword(identifier, document.styleColorOptions(&style)) }; + } +} + +Color colorFromPrimitiveValueWithResolvedCurrentColor(const Document& document, RenderStyle& style, const CSSPrimitiveValue& value) +{ + // FIXME: 'currentcolor' should be resolved at use time to make it inherit correctly. https://bugs.webkit.org/show_bug.cgi?id=210005 + if (StyleColor::isCurrentColor(value)) { + // Color is an inherited property so depending on it effectively makes the property inherited. + style.setHasExplicitlyInheritedProperties(); + style.setDisallowsFastPathInheritance(); + return style.color(); + } + + return colorFromPrimitiveValue(document, style, value, ForVisitedLink::No).absoluteColor(); +} + +} // namespace Style + +} // namespace WebCore diff --git a/Source/WebCore/style/ColorFromPrimitiveValue.h b/Source/WebCore/style/ColorFromPrimitiveValue.h new file mode 100644 index 000000000000..c7326962a27b --- /dev/null +++ b/Source/WebCore/style/ColorFromPrimitiveValue.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 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. ``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 + * 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 "Color.h" +#include "StyleColor.h" + +namespace WebCore { + +class CSSPrimitiveValue; +class Document; +class RenderStyle; + +namespace Style { + +enum class ForVisitedLink : bool; + +StyleColor colorFromPrimitiveValue(const Document&, RenderStyle&, const CSSPrimitiveValue&, Style::ForVisitedLink); +Color colorFromPrimitiveValueWithResolvedCurrentColor(const Document&, RenderStyle&, const CSSPrimitiveValue&); + +} // namespace Style + +} // namespace WebCore diff --git a/Source/WebCore/style/FilterOperationsBuilder.cpp b/Source/WebCore/style/FilterOperationsBuilder.cpp new file mode 100644 index 000000000000..d2ff1328ae3c --- /dev/null +++ b/Source/WebCore/style/FilterOperationsBuilder.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2022 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. ``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 + * 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. + */ + +#include "config.h" +#include "FilterOperationsBuilder.h" + +#include "CSSFunctionValue.h" +#include "CSSShadowValue.h" +#include "CSSToLengthConversionData.h" +#include "ColorFromPrimitiveValue.h" +#include "Document.h" +#include "TransformFunctions.h" + +namespace WebCore { + +namespace Style { + +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; +} + +std::optional createFilterOperations(const Document& document, RenderStyle& style, const CSSToLengthConversionData& cssToLengthConversionData, const CSSValue& inValue) +{ + FilterOperations operations; + + if (is(inValue)) { + auto& primitiveValue = downcast(inValue); + if (primitiveValue.valueID() == CSSValueNone) + return operations; + } + + if (!is(inValue)) + return std::nullopt; + + for (auto& currentValue : downcast(inValue)) { + if (is(currentValue)) { + auto& primitiveValue = downcast(currentValue.get()); + if (!primitiveValue.isURI()) + continue; + + auto filterURL = primitiveValue.stringValue(); + auto fragment = document.completeURL(filterURL).fragmentIdentifier().toAtomString(); + operations.operations().append(ReferenceFilterOperation::create(filterURL, WTFMove(fragment))); + continue; + } + + if (!is(currentValue)) + continue; + + auto& filterValue = downcast(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(*filterValue.itemWithoutBoundsCheck(j))) { + haveNonPrimitiveValue = true; + break; + } + } + if (haveNonPrimitiveValue) + continue; + if (filterValue.length()) + firstValue = downcast(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, LengthType::Fixed); + if (filterValue.length() >= 1) + stdDeviation = convertToFloatLength(firstValue, cssToLengthConversionData); + if (stdDeviation.isUndefined()) + return std::nullopt; + + operations.operations().append(BlurFilterOperation::create(stdDeviation)); + break; + } + case FilterOperation::DROP_SHADOW: { + if (filterValue.length() != 1) + return std::nullopt; + + const auto* cssValue = filterValue.itemWithoutBoundsCheck(0); + if (!is(cssValue)) + continue; + + const auto& item = downcast(*cssValue); + int x = item.x->computeLength(cssToLengthConversionData); + int y = item.y->computeLength(cssToLengthConversionData); + IntPoint location(x, y); + int blur = item.blur ? item.blur->computeLength(cssToLengthConversionData) : 0; + auto color = item.color ? colorFromPrimitiveValueWithResolvedCurrentColor(document, style, *item.color) : style.color(); + + operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparentBlack)); + break; + } + default: + ASSERT_NOT_REACHED(); + break; + } + } + + return operations; +} + +} // namespace Style + +} // namespace WebCore diff --git a/Source/WebCore/style/FilterOperationsBuilder.h b/Source/WebCore/style/FilterOperationsBuilder.h new file mode 100644 index 000000000000..0e7475216ce1 --- /dev/null +++ b/Source/WebCore/style/FilterOperationsBuilder.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 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. ``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 + * 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 + +namespace WebCore { + +class CSSToLengthConversionData; +class CSSValue; +class Document; +class RenderStyle; + +namespace Style { + +std::optional createFilterOperations(const Document&, RenderStyle&, const CSSToLengthConversionData&, const CSSValue&); + +} // namespace Style + +} // namespace WebCore diff --git a/Source/WebCore/style/StyleBuilderConverter.h b/Source/WebCore/style/StyleBuilderConverter.h index 2981bad8511f..fa05e35adcac 100644 --- a/Source/WebCore/style/StyleBuilderConverter.h +++ b/Source/WebCore/style/StyleBuilderConverter.h @@ -1292,10 +1292,7 @@ inline std::optional BuilderConverter::convertMarqueeIncrement(BuilderSt inline std::optional BuilderConverter::convertFilterOperations(BuilderState& builderState, const CSSValue& value) { - FilterOperations operations; - if (builderState.createFilterOperations(value, operations)) - return operations; - return std::nullopt; + return builderState.createFilterOperations(value); } inline FontFeatureSettings BuilderConverter::convertFontFeatureSettings(BuilderState&, const CSSValue& value) diff --git a/Source/WebCore/style/StyleBuilderState.cpp b/Source/WebCore/style/StyleBuilderState.cpp index 12b75d922859..e039658f8716 100644 --- a/Source/WebCore/style/StyleBuilderState.cpp +++ b/Source/WebCore/style/StyleBuilderState.cpp @@ -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-2019 Apple Inc. All rights reserved. + * Copyright (C) 2005-2022 Apple Inc. All rights reserved. * Copyright (C) 2007 Alexey Proskuryakov * Copyright (C) 2007, 2008 Eric Seidel * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) @@ -42,8 +42,10 @@ #include "CSSNamedImageValue.h" #include "CSSPaintImageValue.h" #include "CSSShadowValue.h" +#include "ColorFromPrimitiveValue.h" #include "Document.h" #include "ElementInlines.h" +#include "FilterOperationsBuilder.h" #include "FontCache.h" #include "HTMLElement.h" #include "RenderTheme.h" @@ -144,167 +146,9 @@ RefPtr BuilderState::createStyleImage(CSSValue& value) return nullptr; } -static FilterOperation::OperationType filterOperationForType(CSSValueID type) +std::optional BuilderState::createFilterOperations(const CSSValue& inValue) { - 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& inValue, FilterOperations& outOperations) -{ - // FIXME: Move this code somewhere else. - - ASSERT(outOperations.isEmpty()); - - if (is(inValue)) { - auto& primitiveValue = downcast(inValue); - if (primitiveValue.valueID() == CSSValueNone) - return true; - } - - if (!is(inValue)) - return false; - - FilterOperations operations; - for (auto& currentValue : downcast(inValue)) { - if (is(currentValue)) { - auto& primitiveValue = downcast(currentValue.get()); - if (!primitiveValue.isURI()) - continue; - - auto filterURL = primitiveValue.stringValue(); - auto fragment = document().completeURL(filterURL).fragmentIdentifier().toAtomString(); - operations.operations().append(ReferenceFilterOperation::create(filterURL, WTFMove(fragment))); - continue; - } - - if (!is(currentValue)) - continue; - - auto& filterValue = downcast(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(*filterValue.itemWithoutBoundsCheck(j))) { - haveNonPrimitiveValue = true; - break; - } - } - if (haveNonPrimitiveValue) - continue; - if (filterValue.length()) - firstValue = downcast(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, LengthType::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(cssValue)) - continue; - - const auto& item = downcast(*cssValue); - int x = item.x->computeLength(cssToLengthConversionData()); - int y = item.y->computeLength(cssToLengthConversionData()); - IntPoint location(x, y); - int blur = item.blur ? item.blur->computeLength(cssToLengthConversionData()) : 0; - auto color = item.color ? colorFromPrimitiveValueWithResolvedCurrentColor(*item.color) : m_style.color(); - - operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparentBlack)); - break; - } - default: - ASSERT_NOT_REACHED(); - break; - } - } - - outOperations = operations; - return true; + return WebCore::Style::createFilterOperations(document(), m_style, m_cssToLengthConversionData, inValue); } bool BuilderState::isColorFromPrimitiveValueDerivedFromElement(const CSSPrimitiveValue& value) @@ -322,37 +166,14 @@ bool BuilderState::isColorFromPrimitiveValueDerivedFromElement(const CSSPrimitiv StyleColor BuilderState::colorFromPrimitiveValue(const CSSPrimitiveValue& value, ForVisitedLink forVisitedLink) const { - if (value.isRGBColor()) - return value.color(); - - auto identifier = value.valueID(); - switch (identifier) { - case CSSValueInternalDocumentTextColor: - return { document().textColor() }; - case CSSValueWebkitLink: - return { (element() && element()->isLink() && forVisitedLink == ForVisitedLink::Yes) ? document().visitedLinkColor() : document().linkColor() }; - case CSSValueWebkitActivelink: - return { document().activeLinkColor() }; - case CSSValueWebkitFocusRingColor: - return { RenderTheme::singleton().focusRingColor(document().styleColorOptions(&m_style)) }; - case CSSValueCurrentcolor: - return StyleColor::currentColor(); - default: - return { StyleColor::colorFromKeyword(identifier, document().styleColorOptions(&m_style)) }; - } + if (!element() || !element()->isLink()) + forVisitedLink = ForVisitedLink::No; + return { WebCore::Style::colorFromPrimitiveValue(document(), m_style, value, forVisitedLink) }; } Color BuilderState::colorFromPrimitiveValueWithResolvedCurrentColor(const CSSPrimitiveValue& value) const { - // FIXME: 'currentcolor' should be resolved at use time to make it inherit correctly. https://bugs.webkit.org/show_bug.cgi?id=210005 - if (StyleColor::isCurrentColor(value)) { - // Color is an inherited property so depending on it effectively makes the property inherited. - m_style.setHasExplicitlyInheritedProperties(); - m_style.setDisallowsFastPathInheritance(); - return m_style.color(); - } - - return colorFromPrimitiveValue(value).absoluteColor(); + return WebCore::Style::colorFromPrimitiveValueWithResolvedCurrentColor(document(), m_style, value); } void BuilderState::registerContentAttribute(const AtomString& attributeLocalName) diff --git a/Source/WebCore/style/StyleBuilderState.h b/Source/WebCore/style/StyleBuilderState.h index fc2bddd26a9c..ff54596fed1a 100644 --- a/Source/WebCore/style/StyleBuilderState.h +++ b/Source/WebCore/style/StyleBuilderState.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Apple Inc. All rights reserved. + * Copyright (C) 2019-2022 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -94,7 +94,7 @@ class BuilderState { Ref resolveImageStyles(CSSValue&); RefPtr createStyleImage(CSSValue&); - bool createFilterOperations(const CSSValue&, FilterOperations& outOperations); + std::optional createFilterOperations(const CSSValue&); static bool isColorFromPrimitiveValueDerivedFromElement(const CSSPrimitiveValue&); StyleColor colorFromPrimitiveValue(const CSSPrimitiveValue&, ForVisitedLink = ForVisitedLink::No) const;