Fix color-filter to apply to SVG colors
https://bugs.webkit.org/show_bug.cgi?id=185113
rdar://problem/39665082
Reviewed by Dean Jackson.
Source/WebCore:
Convert SVG colors through color-filter operations for the places in SVG
that use color, namely fill and stroke, gradients, lighting colors and
drop-shadow.
Test: css3/color-filters/svg/color-filter-inline-svg.html
* rendering/svg/RenderSVGResourceGradient.cpp:
(WebCore::RenderSVGResourceGradient::applyResource):
* rendering/svg/RenderSVGResourceGradient.h:
* rendering/svg/RenderSVGResourceLinearGradient.cpp:
(WebCore::RenderSVGResourceLinearGradient::buildGradient const):
* rendering/svg/RenderSVGResourceLinearGradient.h:
* rendering/svg/RenderSVGResourceRadialGradient.cpp:
(WebCore::RenderSVGResourceRadialGradient::buildGradient const):
* rendering/svg/RenderSVGResourceRadialGradient.h:
* rendering/svg/RenderSVGResourceSolidColor.cpp:
(WebCore::RenderSVGResourceSolidColor::applyResource):
* svg/SVGFEDiffuseLightingElement.cpp:
(WebCore::SVGFEDiffuseLightingElement::setFilterEffectAttribute):
(WebCore::SVGFEDiffuseLightingElement::build):
* svg/SVGFEDropShadowElement.cpp:
(WebCore::SVGFEDropShadowElement::build):
* svg/SVGFEFloodElement.cpp:
(WebCore::SVGFEFloodElement::build):
* svg/SVGFESpecularLightingElement.cpp:
(WebCore::SVGFESpecularLightingElement::setFilterEffectAttribute):
(WebCore::SVGFESpecularLightingElement::build):
LayoutTests:
* css3/color-filters/svg/color-filter-inline-svg-expected.html: Added.
* css3/color-filters/svg/color-filter-inline-svg.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@231153 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index c0b2e45..7534cf5 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2018-04-28 Simon Fraser <simon.fraser@apple.com>
+
+ Fix color-filter to apply to SVG colors
+ https://bugs.webkit.org/show_bug.cgi?id=185113
+ rdar://problem/39665082
+
+ Reviewed by Dean Jackson.
+
+ * css3/color-filters/svg/color-filter-inline-svg-expected.html: Added.
+ * css3/color-filters/svg/color-filter-inline-svg.html: Added.
+
2018-04-27 Ryan Haddad <ryanhaddad@apple.com>
Unreviewed test gardening for iOS and macOS.
diff --git a/LayoutTests/css3/color-filters/svg/color-filter-inline-svg-expected.html b/LayoutTests/css3/color-filters/svg/color-filter-inline-svg-expected.html
new file mode 100644
index 0000000..d08c182
--- /dev/null
+++ b/LayoutTests/css3/color-filters/svg/color-filter-inline-svg-expected.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>CSS Test: color-filter reference</title>
+ <link rel="author" title="Apple" href="http://www.apple.com/">
+
+ <style>
+ body {
+ margin: 0;
+ }
+ </style>
+ </head>
+<body>
+
+<svg viewBox="0 0 800 600" style="width: 800px; height: 600px">
+ <defs>
+ <radialGradient id="grad">
+ <stop offset="0" stop-color="cyan" />
+ <stop offset="0.5" stop-color="green" />
+ <stop offset="0.75" stop-color="blue" />
+ </radialGradient>
+
+ <filter id="flood" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feFlood flood-color="green" />
+ </filter>
+
+ <filter id="diffuse-light" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feDiffuseLighting lighting-color="green">
+ <feDistantLight azimuth="100" elevation="100"/>
+ </feDiffuseLighting>
+ </filter>
+
+ <filter id="specular-light" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feSpecularLighting surfaceScale="2" specularExponent="2" specularConstant="2" lighting-color="green">
+ <fePointLight x="20" y="20" z="2"/>
+ </feSpecularLighting>
+ </filter>
+
+ <filter id="shadow" x="0" y="0" width="160%" height="160%">
+ <feDropShadow dx="50" dy="50" stdDeviation="0" flood-color="green" flood-opacity="1" />
+ </filter>
+
+ <pattern id="pattern" patternUnits="userSpaceOnUse" x="20" y="0" width="50" height="50">
+ <rect x="5" y="5" width="30" height="30" fill="green"/>
+ </pattern>
+ </defs>
+
+ <rect x="20" y="10" width="150" height="150" fill="url(#grad)" />
+
+ <rect x="200" y="10" width="150" height="150" fill="green" />
+ <rect x="400" y="10" width="150" height="150" fill="green" stroke="blue" stroke-width="15" />
+
+ <rect x="20" y="200" width="150" height="150" filter="url(#flood)"/>
+ <rect x="200" y="200" width="150" height="150" filter="url(#diffuse-light)"/>
+ <rect x="400" y="200" width="150" height="150" filter="url(#specular-light)"/>
+
+ <rect x="20" y="400" width="150" height="150" fill="url(#pattern)"/>
+
+ <rect x="200" y="400" width="100" height="100" fill="blue" filter="url(#shadow)"/>
+</svg>
+
+</body>
+</html>
diff --git a/LayoutTests/css3/color-filters/svg/color-filter-inline-svg.html b/LayoutTests/css3/color-filters/svg/color-filter-inline-svg.html
new file mode 100644
index 0000000..57ae6af
--- /dev/null
+++ b/LayoutTests/css3/color-filters/svg/color-filter-inline-svg.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html >
+ <head>
+ <title>CSS Test: color-filter affects colors in inline SVG</title>
+ <link rel="author" title="Apple" href="http://www.apple.com/">
+ <link rel="match" href="color-filter-inline-svg-expected.html">
+
+ <meta name="assert" content="color-filter affects colors in inline SVG">
+ <style>
+ html {
+ color-filter: invert();
+ }
+
+ body {
+ margin: 0;
+ }
+ </style>
+ </head>
+<body>
+
+<svg viewBox="0 0 800 600" style="width: 800px; height: 600px">
+ <defs>
+ <radialGradient id="grad">
+ <stop offset="0" stop-color="red" />
+ <stop offset="0.5" stop-color="rgb(255, 128, 255)" />
+ <stop offset="0.75" stop-color="yellow" />
+ </radialGradient>
+
+ <filter id="flood" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feFlood flood-color="rgb(255, 128, 255)" />
+ </filter>
+
+ <filter id="diffuse-light" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feDiffuseLighting lighting-color="rgb(255, 128, 255)">
+ <feDistantLight azimuth="100" elevation="100"/>
+ </feDiffuseLighting>
+ </filter>
+
+ <filter id="specular-light" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
+ <feSpecularLighting surfaceScale="2" specularExponent="2" specularConstant="2" lighting-color="rgb(255, 128, 255)">
+ <fePointLight x="20" y="20" z="2"/>
+ </feSpecularLighting>
+ </filter>
+
+ <filter id="shadow" x="0" y="0" width="160%" height="160%">
+ <feDropShadow dx="50" dy="50" stdDeviation="0" flood-color="rgb(255, 128, 255)" flood-opacity="1" />
+ </filter>
+
+ <pattern id="pattern" patternUnits="userSpaceOnUse" x="20" y="0" width="50" height="50">
+ <rect x="5" y="5" width="30" height="30" fill="rgb(255, 128, 255)"/>
+ </pattern>
+ </defs>
+
+ <rect x="20" y="10" width="150" height="150" fill="url(#grad)" />
+
+ <rect x="200" y="10" width="150" height="150" fill="rgb(255, 128, 255)" />
+ <rect x="400" y="10" width="150" height="150" fill="rgb(255, 128, 255)" stroke="yellow" stroke-width="15" />
+
+ <rect x="20" y="200" width="150" height="150" filter="url(#flood)"/>
+ <rect x="200" y="200" width="150" height="150" filter="url(#diffuse-light)"/>
+ <rect x="400" y="200" width="150" height="150" filter="url(#specular-light)"/>
+
+ <rect x="20" y="400" width="150" height="150" fill="url(#pattern)"/>
+
+ <rect x="200" y="400" width="100" height="100" fill="yellow" filter="url(#shadow)"/>
+</svg>
+
+</body>
+</html>
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index b5a0741..c4facc4 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,39 @@
+2018-04-28 Simon Fraser <simon.fraser@apple.com>
+
+ Fix color-filter to apply to SVG colors
+ https://bugs.webkit.org/show_bug.cgi?id=185113
+ rdar://problem/39665082
+
+ Reviewed by Dean Jackson.
+
+ Convert SVG colors through color-filter operations for the places in SVG
+ that use color, namely fill and stroke, gradients, lighting colors and
+ drop-shadow.
+
+ Test: css3/color-filters/svg/color-filter-inline-svg.html
+
+ * rendering/svg/RenderSVGResourceGradient.cpp:
+ (WebCore::RenderSVGResourceGradient::applyResource):
+ * rendering/svg/RenderSVGResourceGradient.h:
+ * rendering/svg/RenderSVGResourceLinearGradient.cpp:
+ (WebCore::RenderSVGResourceLinearGradient::buildGradient const):
+ * rendering/svg/RenderSVGResourceLinearGradient.h:
+ * rendering/svg/RenderSVGResourceRadialGradient.cpp:
+ (WebCore::RenderSVGResourceRadialGradient::buildGradient const):
+ * rendering/svg/RenderSVGResourceRadialGradient.h:
+ * rendering/svg/RenderSVGResourceSolidColor.cpp:
+ (WebCore::RenderSVGResourceSolidColor::applyResource):
+ * svg/SVGFEDiffuseLightingElement.cpp:
+ (WebCore::SVGFEDiffuseLightingElement::setFilterEffectAttribute):
+ (WebCore::SVGFEDiffuseLightingElement::build):
+ * svg/SVGFEDropShadowElement.cpp:
+ (WebCore::SVGFEDropShadowElement::build):
+ * svg/SVGFEFloodElement.cpp:
+ (WebCore::SVGFEFloodElement::build):
+ * svg/SVGFESpecularLightingElement.cpp:
+ (WebCore::SVGFESpecularLightingElement::setFilterEffectAttribute):
+ (WebCore::SVGFESpecularLightingElement::build):
+
2018-04-29 Michael Catanzaro <mcatanzaro@igalia.com>
[CMake] Require GCC 6
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
index 0b5d9b6..9781c4e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
@@ -125,7 +125,7 @@
// Create gradient object
if (!gradientData->gradient) {
- buildGradient(gradientData.get());
+ buildGradient(gradientData.get(), style);
// CG platforms will handle the gradient space transform for text after applying the
// resource, so don't apply it here. For non-CG platforms, we want the text bounding
@@ -232,13 +232,14 @@
context->restore();
}
-void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops) const
+void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops, const RenderStyle& style) const
{
ASSERT(gradientData->gradient);
- const Vector<Gradient::ColorStop>::const_iterator end = stops.end();
- for (Vector<Gradient::ColorStop>::const_iterator it = stops.begin(); it != end; ++it)
- gradientData->gradient->addColorStop(*it);
+ for (Gradient::ColorStop stop : stops) {
+ stop.color = style.colorByApplyingColorFilter(stop.color);
+ gradientData->gradient->addColorStop(stop);
+ }
}
GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(SVGSpreadMethodType method) const
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
index cc360f4..140c70e 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceGradient.h
@@ -56,12 +56,12 @@
void element() const = delete;
- void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const;
+ void addStops(GradientData*, const Vector<Gradient::ColorStop>&, const RenderStyle&) const;
virtual SVGUnitTypes::SVGUnitType gradientUnits() const = 0;
virtual void calculateGradientTransform(AffineTransform&) = 0;
virtual bool collectGradientAttributes() = 0;
- virtual void buildGradient(GradientData*) const = 0;
+ virtual void buildGradient(GradientData*, const RenderStyle&) const = 0;
GradientSpreadMethod platformSpreadMethodFromSVGType(SVGSpreadMethodType) const;
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
index 457b20c..9dd3250 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.cpp
@@ -50,11 +50,11 @@
return SVGLengthContext::resolvePoint(&linearGradientElement(), attributes.gradientUnits(), attributes.x2(), attributes.y2());
}
-void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData) const
+void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData, const RenderStyle& style) const
{
gradientData->gradient = Gradient::create(Gradient::LinearData { startPoint(m_attributes), endPoint(m_attributes) });
gradientData->gradient->setSpreadMethod(platformSpreadMethodFromSVGType(m_attributes.spreadMethod()));
- addStops(gradientData, m_attributes.stops());
+ addStops(gradientData, m_attributes.stops(), style);
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
index ba2ab89..4b93c87 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceLinearGradient.h
@@ -39,7 +39,7 @@
SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); }
void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); }
bool collectGradientAttributes() override;
- void buildGradient(GradientData*) const override;
+ void buildGradient(GradientData*, const RenderStyle&) const override;
FloatPoint startPoint(const LinearGradientAttributes&) const;
FloatPoint endPoint(const LinearGradientAttributes&) const;
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
index 7af48c65..09a5cc2 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.cpp
@@ -61,12 +61,12 @@
return SVGLengthContext::resolveLength(&radialGradientElement(), attributes.gradientUnits(), attributes.fr());
}
-void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData) const
+void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData, const RenderStyle& style) const
{
gradientData->gradient = Gradient::create(Gradient::RadialData { this->focalPoint(m_attributes), this->centerPoint(m_attributes), this->focalRadius(m_attributes), this->radius(m_attributes), 1 });
gradientData->gradient->setSpreadMethod(platformSpreadMethodFromSVGType(m_attributes.spreadMethod()));
- addStops(gradientData, m_attributes.stops());
+ addStops(gradientData, m_attributes.stops(), style);
}
}
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
index fb3050b..809930c 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceRadialGradient.h
@@ -40,7 +40,7 @@
SVGUnitTypes::SVGUnitType gradientUnits() const override { return m_attributes.gradientUnits(); }
void calculateGradientTransform(AffineTransform& transform) override { transform = m_attributes.gradientTransform(); }
- void buildGradient(GradientData*) const override;
+ void buildGradient(GradientData*, const RenderStyle&) const override;
FloatPoint centerPoint(const RadialGradientAttributes&) const;
FloatPoint focalPoint(const RadialGradientAttributes&) const;
diff --git a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
index 09a6e0c..6520c41 100644
--- a/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
+++ b/Source/WebCore/rendering/svg/RenderSVGResourceSolidColor.cpp
@@ -46,7 +46,7 @@
context->setAlpha(svgStyle.fillOpacity());
else
context->setAlpha(1);
- context->setFillColor(m_color);
+ context->setFillColor(style.colorByApplyingColorFilter(m_color));
if (!isRenderingMask)
context->setFillRule(svgStyle.fillRule());
@@ -56,7 +56,7 @@
// When rendering the mask for a RenderSVGResourceClipper, the stroke code path is never hit.
ASSERT(!isRenderingMask);
context->setAlpha(svgStyle.strokeOpacity());
- context->setStrokeColor(m_color);
+ context->setStrokeColor(style.colorByApplyingColorFilter(m_color));
SVGRenderSupport::applyStrokeStyleToContext(context, style, renderer);
diff --git a/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp b/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp
index 66c5dbb..3ea3b16 100644
--- a/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp
+++ b/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp
@@ -111,7 +111,8 @@
if (attrName == SVGNames::lighting_colorAttr) {
RenderObject* renderer = this->renderer();
ASSERT(renderer);
- return diffuseLighting->setLightingColor(renderer->style().svgStyle().lightingColor());
+ Color color = renderer->style().colorByApplyingColorFilter(renderer->style().svgStyle().lightingColor());
+ return diffuseLighting->setLightingColor(color);
}
if (attrName == SVGNames::surfaceScaleAttr)
return diffuseLighting->setSurfaceScale(surfaceScale());
@@ -190,7 +191,7 @@
if (!renderer)
return nullptr;
- const Color& color = renderer->style().svgStyle().lightingColor();
+ Color color = renderer->style().colorByApplyingColorFilter(renderer->style().svgStyle().lightingColor());
RefPtr<FilterEffect> effect = FEDiffuseLighting::create(filter, color, surfaceScale(), diffuseConstant(), kernelUnitLengthX(), kernelUnitLengthY(), WTFMove(lightSource));
effect->inputEffects().append(input1);
diff --git a/Source/WebCore/svg/SVGFEDropShadowElement.cpp b/Source/WebCore/svg/SVGFEDropShadowElement.cpp
index ed53a54..cc4bba1 100644
--- a/Source/WebCore/svg/SVGFEDropShadowElement.cpp
+++ b/Source/WebCore/svg/SVGFEDropShadowElement.cpp
@@ -133,7 +133,7 @@
const SVGRenderStyle& svgStyle = renderer->style().svgStyle();
- const Color& color = svgStyle.floodColor();
+ Color color = renderer->style().colorByApplyingColorFilter(svgStyle.floodColor());
float opacity = svgStyle.floodOpacity();
auto input1 = filterBuilder->getEffectById(in1());
diff --git a/Source/WebCore/svg/SVGFEFloodElement.cpp b/Source/WebCore/svg/SVGFEFloodElement.cpp
index 7f7e0d4..cfe642a 100644
--- a/Source/WebCore/svg/SVGFEFloodElement.cpp
+++ b/Source/WebCore/svg/SVGFEFloodElement.cpp
@@ -66,7 +66,7 @@
const SVGRenderStyle& svgStyle = renderer->style().svgStyle();
- const Color& color = svgStyle.floodColor();
+ Color color = renderer->style().colorByApplyingColorFilter(svgStyle.floodColor());
float opacity = svgStyle.floodOpacity();
return FEFlood::create(filter, color, opacity);
diff --git a/Source/WebCore/svg/SVGFESpecularLightingElement.cpp b/Source/WebCore/svg/SVGFESpecularLightingElement.cpp
index 57510cf..b0454c2 100644
--- a/Source/WebCore/svg/SVGFESpecularLightingElement.cpp
+++ b/Source/WebCore/svg/SVGFESpecularLightingElement.cpp
@@ -120,7 +120,8 @@
if (attrName == SVGNames::lighting_colorAttr) {
RenderObject* renderer = this->renderer();
ASSERT(renderer);
- return specularLighting->setLightingColor(renderer->style().svgStyle().lightingColor());
+ Color color = renderer->style().colorByApplyingColorFilter(renderer->style().svgStyle().lightingColor());
+ return specularLighting->setLightingColor(color);
}
if (attrName == SVGNames::surfaceScaleAttr)
return specularLighting->setSurfaceScale(surfaceScale());
@@ -201,7 +202,7 @@
if (!renderer)
return nullptr;
- const Color& color = renderer->style().svgStyle().lightingColor();
+ Color color = renderer->style().colorByApplyingColorFilter(renderer->style().svgStyle().lightingColor());
RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, surfaceScale(), specularConstant(), specularExponent(), kernelUnitLengthX(), kernelUnitLengthY(), WTFMove(lightSource));
effect->inputEffects().append(input1);