Skip to content

Commit

Permalink
Move BuilderState::createFilterOperations() to a separate file
Browse files Browse the repository at this point in the history
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
  • Loading branch information
shallawa authored and Said Abou-Hallawa committed Oct 19, 2022
1 parent 1eb4751 commit ea05e83
Show file tree
Hide file tree
Showing 10 changed files with 391 additions and 196 deletions.
2 changes: 2 additions & 0 deletions Source/WebCore/Sources.txt
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions Source/WebCore/WebCore.xcodeproj/project.pbxproj
Expand Up @@ -11829,6 +11829,10 @@
72C11DAB28492A9200E826DD /* ByteArrayPixelBuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ByteArrayPixelBuffer.cpp; sourceTree = "<group>"; };
72C11DAC28492A9200E826DD /* ByteArrayPixelBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ByteArrayPixelBuffer.h; sourceTree = "<group>"; };
72C18A3F230B04B7006847C7 /* ImagePaintingOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImagePaintingOptions.h; sourceTree = "<group>"; };
72CDE0DF28FE21700059719E /* FilterOperationsBuilder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FilterOperationsBuilder.cpp; sourceTree = "<group>"; };
72CDE0E028FE21700059719E /* FilterOperationsBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FilterOperationsBuilder.h; sourceTree = "<group>"; };
72CDE0E128FE23000059719E /* ColorFromPrimitiveValue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ColorFromPrimitiveValue.cpp; sourceTree = "<group>"; };
72CDE0E228FE23000059719E /* ColorFromPrimitiveValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ColorFromPrimitiveValue.h; sourceTree = "<group>"; };
72E417611A2E8D2F004C562A /* JSEXTsRGB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSEXTsRGB.cpp; sourceTree = "<group>"; };
72E417621A2E8D2F004C562A /* JSEXTsRGB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSEXTsRGB.h; sourceTree = "<group>"; };
72E5768A281B292600A75432 /* CopyImageOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CopyImageOptions.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -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 */,
Expand Down
6 changes: 4 additions & 2 deletions Source/WebCore/css/CSSFilterImageValue.cpp
Expand Up @@ -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)
Expand Down
77 changes: 77 additions & 0 deletions 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
46 changes: 46 additions & 0 deletions 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
201 changes: 201 additions & 0 deletions 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<FilterOperations> createFilterOperations(const Document& document, RenderStyle& style, const CSSToLengthConversionData& cssToLengthConversionData, const CSSValue& inValue)
{
FilterOperations operations;

if (is<CSSPrimitiveValue>(inValue)) {
auto& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
if (primitiveValue.valueID() == CSSValueNone)
return operations;
}

if (!is<CSSValueList>(inValue))
return std::nullopt;

for (auto& currentValue : downcast<CSSValueList>(inValue)) {
if (is<CSSPrimitiveValue>(currentValue)) {
auto& primitiveValue = downcast<CSSPrimitiveValue>(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<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, 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<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;
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

0 comments on commit ea05e83

Please sign in to comment.