Title: [226373] trunk
Revision
226373
Author
[email protected]
Date
2018-01-03 13:56:00 -0800 (Wed, 03 Jan 2018)

Log Message

feLighting is broken with primitiveUnits="objectBoundingBox"
https://bugs.webkit.org/show_bug.cgi?id=181197

Reviewed by Tim Horton.
Source/WebCore:

With <filter primitiveUnits="objectBoundingBox"> we need to convert the coordinates
of fePointLights and feSpotLights into user space coordinates. Following
https://www.w3.org/TR/SVG/filters.html#FilterElementPrimitiveUnitsAttribute
this is done by treating them as fractions of the bounding box on the referencing
element, with treatment for z following https://www.w3.org/TR/SVG/coords.html#Units_viewport_percentage

To do this, store the bounds of the referencing elemenet on SVGFilterBuilder as
targetBoundingBox, and store the primitiveUnits type. Then do the conversion of lighting
coordinates in SVGFESpecularLightingElement::build() and SVGFEDiffuseLightingElement::build().

Remove SVGFELightElement::findLightSource(), since we need to be able to pass the SVGFilterBuilder
to the lightSource() function so hoist the code up.

Tests: svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg
       svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg
       svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg
       svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg
       svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg
       svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg

* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::buildPrimitives const):
* svg/SVGFEDiffuseLightingElement.cpp:
(WebCore::SVGFEDiffuseLightingElement::build):
* svg/SVGFEDistantLightElement.cpp:
(WebCore::SVGFEDistantLightElement::lightSource const):
* svg/SVGFEDistantLightElement.h:
* svg/SVGFELightElement.cpp:
(WebCore::SVGFELightElement::findLightSource): Deleted.
* svg/SVGFELightElement.h:
* svg/SVGFEPointLightElement.cpp:
(WebCore::SVGFEPointLightElement::lightSource const):
* svg/SVGFEPointLightElement.h:
* svg/SVGFESpecularLightingElement.cpp:
(WebCore::SVGFESpecularLightingElement::build):
* svg/SVGFESpotLightElement.cpp:
(WebCore::SVGFESpotLightElement::lightSource const):
* svg/SVGFESpotLightElement.h:
* svg/graphics/filters/SVGFilterBuilder.h:
(WebCore::SVGFilterBuilder::setTargetBoundingBox):
(WebCore::SVGFilterBuilder::targetBoundingBox const):
(WebCore::SVGFilterBuilder::primitiveUnits const):
(WebCore::SVGFilterBuilder::setPrimitiveUnits):

LayoutTests:

Ref tests with primitiveUnits=objectBoundingBox for feSpotLight and fePointLight.

* svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
* svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg: Added.
* svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
* svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg: Added.
* svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
* svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (226372 => 226373)


--- trunk/LayoutTests/ChangeLog	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/LayoutTests/ChangeLog	2018-01-03 21:56:00 UTC (rev 226373)
@@ -1,3 +1,19 @@
+2018-01-03  Simon Fraser  <[email protected]>
+
+        feLighting is broken with primitiveUnits="objectBoundingBox"
+        https://bugs.webkit.org/show_bug.cgi?id=181197
+
+        Reviewed by Tim Horton.
+        
+        Ref tests with primitiveUnits=objectBoundingBox for feSpotLight and fePointLight.
+
+        * svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
+        * svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg: Added.
+        * svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
+        * svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg: Added.
+        * svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg: Added.
+        * svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg: Added.
+
 2018-01-03  Antti Koivisto  <[email protected]>
 
         Crash beneath CSSValue::equals @ csas.cz

Added: trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,11 @@
+<svg width="500px" height="580px" xmlns="http://www.w3.org/2000/svg">
+<defs>
+    <filter id="filter" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
+        <feFlood x="-0.1" y="-0.16"/>
+    </filter>
+</defs>
+<rect x="110" y="150" width="400" height="320" fill="none" filter="url(#filter)"/>
+<circle cx="250" cy="310" r="123" fill="rgb(0, 255, 0)"/>
+<!-- Mask off slight differences in point light radius -->
+<circle cx="250" cy="310" r="123" fill="none" stroke="gray" stroke-width="20"/>
+</svg>

Added: trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,16 @@
+<svg width="500px" height="580px" xmlns="http://www.w3.org/2000/svg">
+<defs>
+    <filter id="filter" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
+        <feFlood/>
+        <feDiffuseLighting lighting-color="rgb(0, 255, 0)" x="-0.1" y="-0.16">
+            <fePointLight x="0.35" y="0.5" z="0.2"/>
+        </feDiffuseLighting>
+        <feComponentTransfer>
+            <feFuncG type="discrete" tableValues="0 1"/>
+        </feComponentTransfer>
+    </filter>
+</defs>
+<rect x="110" y="150" width="400" height="320" fill="none" filter="url(#filter)"/>
+<!-- Mask off slight differences in point light radius -->
+<circle cx="250" cy="310" r="123" fill="none" stroke="gray" stroke-width="20"/>
+</svg>

Added: trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,11 @@
+<svg width="500px" height="610px" xmlns="http://www.w3.org/2000/svg">
+<defs>
+    <filter id="filter" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
+        <feFlood  x="-0.1" y="-0.16"/>
+    </filter>
+</defs>
+<rect x="110" y="150" width="400" height="320" fill="none" filter="url(#filter)"/>
+<ellipse cx="298" cy="328" rx="152" ry="117" fill="rgb(0, 255, 0)" style="transform: rotate(48deg); transform-origin: 50% 50%; transform-box: fill-box;"/>
+<!-- Mask off slight differences in point light radius -->
+<ellipse cx="298" cy="328" rx="152" ry="117" fill="none" stroke="gray" stroke-width="20" style="transform: rotate(48deg); transform-origin: 50% 50%; transform-box: fill-box;"/>
+</svg>

Added: trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,16 @@
+<svg width="500px" height="610px" xmlns="http://www.w3.org/2000/svg">
+<defs>
+    <filter id="filter" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
+        <feFlood/>
+        <feDiffuseLighting lighting-color="rgb(0, 255, 0)" x="-0.1" y="-0.16">
+            <feSpotLight x="-0.4" y="-0.6" z="1.7" pointsAtX="0.2" pointsAtY="0.2" pointsAtZ="0.5" limitingConeAngle="12" />
+        </feDiffuseLighting>
+        <feComponentTransfer>
+            <feFuncG type="discrete" tableValues="0 1"/>
+        </feComponentTransfer>
+    </filter>
+</defs>
+<rect x="110" y="150" width="400" height="320" fill="none" filter="url(#filter)"/>
+<!-- Mask off slight differences in point light radius -->
+<ellipse cx="298" cy="328" rx="152" ry="117" fill="none" stroke="gray" stroke-width="20" style="transform: rotate(48deg); transform-origin: 50% 50%; transform-box: fill-box;"/>
+</svg>

Added: trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,4 @@
+<svg width="500px" height="580px" xmlns="http://www.w3.org/2000/svg">
+<circle cx="250" cy="310" r="112" fill="rgb(0, 255, 0)"/>
+<circle cx="250" cy="310" r="112" fill="none" stroke="gray" stroke-width="20"/>
+</svg>

Added: trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg (0 => 226373)


--- trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg	2018-01-03 21:56:00 UTC (rev 226373)
@@ -0,0 +1,17 @@
+<svg width="500px" height="580px" xmlns="http://www.w3.org/2000/svg">
+<defs>
+    <filter id="filter" filterUnits="objectBoundingBox" primitiveUnits="objectBoundingBox">
+        <feFlood/>
+        <feSpecularLighting surfaceScale="10" specularExponent="10" specularConstant="2" lighting-color="rgb(0, 255, 0)">
+            <fePointLight x="0.35" y="0.5" z="0.2"/>
+        </feSpecularLighting>
+        <feComponentTransfer>
+            <feFuncG type="discrete" tableValues="0 1"/>
+            <feFuncA type="discrete" tableValues="0 1"/>
+        </feComponentTransfer>
+    </filter>
+</defs>
+<rect x="110" y="150" width="400" height="320" fill="none" filter="url(#filter)"/>
+<!-- Mask off slight differences in point light radius -->
+<circle cx="250" cy="310" r="112" fill="none" stroke="gray" stroke-width="20"/>
+</svg>

Modified: trunk/Source/WebCore/ChangeLog (226372 => 226373)


--- trunk/Source/WebCore/ChangeLog	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/ChangeLog	2018-01-03 21:56:00 UTC (rev 226373)
@@ -1,3 +1,54 @@
+2018-01-03  Simon Fraser  <[email protected]>
+
+        feLighting is broken with primitiveUnits="objectBoundingBox"
+        https://bugs.webkit.org/show_bug.cgi?id=181197
+
+        Reviewed by Tim Horton.
+
+        With <filter primitiveUnits="objectBoundingBox"> we need to convert the coordinates
+        of fePointLights and feSpotLights into user space coordinates. Following
+        https://www.w3.org/TR/SVG/filters.html#FilterElementPrimitiveUnitsAttribute
+        this is done by treating them as fractions of the bounding box on the referencing
+        element, with treatment for z following https://www.w3.org/TR/SVG/coords.html#Units_viewport_percentage
+        
+        To do this, store the bounds of the referencing elemenet on SVGFilterBuilder as
+        targetBoundingBox, and store the primitiveUnits type. Then do the conversion of lighting
+        coordinates in SVGFESpecularLightingElement::build() and SVGFEDiffuseLightingElement::build().
+
+        Remove SVGFELightElement::findLightSource(), since we need to be able to pass the SVGFilterBuilder
+        to the lightSource() function so hoist the code up.
+
+        Tests: svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg
+               svg/filters/feDiffuseLighting-fePointLight-primitiveUnits-objectBoundingBox.svg
+               svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox-expected.svg
+               svg/filters/feDiffuseLighting-feSpotLight-primitiveUnits-objectBoundingBox.svg
+               svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox-expected.svg
+               svg/filters/feSpecularLighting-fePointLight-primitiveUnits-objectBoundingBox.svg
+
+        * rendering/svg/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::buildPrimitives const):
+        * svg/SVGFEDiffuseLightingElement.cpp:
+        (WebCore::SVGFEDiffuseLightingElement::build):
+        * svg/SVGFEDistantLightElement.cpp:
+        (WebCore::SVGFEDistantLightElement::lightSource const):
+        * svg/SVGFEDistantLightElement.h:
+        * svg/SVGFELightElement.cpp:
+        (WebCore::SVGFELightElement::findLightSource): Deleted.
+        * svg/SVGFELightElement.h:
+        * svg/SVGFEPointLightElement.cpp:
+        (WebCore::SVGFEPointLightElement::lightSource const):
+        * svg/SVGFEPointLightElement.h:
+        * svg/SVGFESpecularLightingElement.cpp:
+        (WebCore::SVGFESpecularLightingElement::build):
+        * svg/SVGFESpotLightElement.cpp:
+        (WebCore::SVGFESpotLightElement::lightSource const):
+        * svg/SVGFESpotLightElement.h:
+        * svg/graphics/filters/SVGFilterBuilder.h:
+        (WebCore::SVGFilterBuilder::setTargetBoundingBox):
+        (WebCore::SVGFilterBuilder::targetBoundingBox const):
+        (WebCore::SVGFilterBuilder::primitiveUnits const):
+        (WebCore::SVGFilterBuilder::setPrimitiveUnits):
+
 2018-01-03  Antti Koivisto  <[email protected]>
 
         Crash beneath CSSValue::equals @ csas.cz

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (226372 => 226373)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -89,6 +89,9 @@
 
     // Add effects to the builder
     auto builder = std::make_unique<SVGFilterBuilder>(SourceGraphic::create(filter));
+    builder->setPrimitiveUnits(filterElement().primitiveUnits());
+    builder->setTargetBoundingBox(targetBoundingBox);
+    
     for (auto& element : childrenOfType<SVGFilterPrimitiveStandardAttributes>(filterElement())) {
         RefPtr<FilterEffect> effect = element.build(builder.get(), filter);
         if (!effect) {

Modified: trunk/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFEDiffuseLightingElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -177,9 +177,11 @@
     if (!input1)
         return nullptr;
 
-    auto lightSource = SVGFELightElement::findLightSource(this);
-    if (!lightSource)
+    auto lightElement = makeRefPtr(SVGFELightElement::findLightElement(this));
+    if (!lightElement)
         return nullptr;
+    
+    auto lightSource = lightElement->lightSource(*filterBuilder);
 
     RenderObject* renderer = this->renderer();
     if (!renderer)
@@ -187,7 +189,7 @@
 
     const Color& color = renderer->style().svgStyle().lightingColor();
 
-    RefPtr<FilterEffect> effect = FEDiffuseLighting::create(filter, color, surfaceScale(), diffuseConstant(), kernelUnitLengthX(), kernelUnitLengthY(), lightSource.releaseNonNull());
+    RefPtr<FilterEffect> effect = FEDiffuseLighting::create(filter, color, surfaceScale(), diffuseConstant(), kernelUnitLengthX(), kernelUnitLengthY(), WTFMove(lightSource));
     effect->inputEffects().append(input1);
     return effect;
 }

Modified: trunk/Source/WebCore/svg/SVGFEDistantLightElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFEDistantLightElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFEDistantLightElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -36,7 +36,7 @@
     return adoptRef(*new SVGFEDistantLightElement(tagName, document));
 }
 
-Ref<LightSource> SVGFEDistantLightElement::lightSource() const
+Ref<LightSource> SVGFEDistantLightElement::lightSource(SVGFilterBuilder&) const
 {
     return DistantLightSource::create(azimuth(), elevation());
 }

Modified: trunk/Source/WebCore/svg/SVGFEDistantLightElement.h (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFEDistantLightElement.h	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFEDistantLightElement.h	2018-01-03 21:56:00 UTC (rev 226373)
@@ -30,7 +30,7 @@
 private:
     SVGFEDistantLightElement(const QualifiedName&, Document&);
 
-    Ref<LightSource> lightSource() const override;
+    Ref<LightSource> lightSource(SVGFilterBuilder&) const override;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/svg/SVGFELightElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFELightElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFELightElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -77,14 +77,6 @@
     return nullptr;
 }
 
-RefPtr<LightSource> SVGFELightElement::findLightSource(const SVGElement* svgElement)
-{
-    auto lightNode = makeRefPtr(findLightElement(svgElement));
-    if (!lightNode)
-        return 0;
-    return lightNode->lightSource();
-}
-
 void SVGFELightElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
 {
     if (name == SVGNames::azimuthAttr) {

Modified: trunk/Source/WebCore/svg/SVGFELightElement.h (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFELightElement.h	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFELightElement.h	2018-01-03 21:56:00 UTC (rev 226373)
@@ -27,11 +27,12 @@
 
 namespace WebCore {
 
+class SVGFilterBuilder;
+
 class SVGFELightElement : public SVGElement {
 public:
-    virtual Ref<LightSource> lightSource() const = 0;
+    virtual Ref<LightSource> lightSource(SVGFilterBuilder&) const = 0;
     static SVGFELightElement* findLightElement(const SVGElement*);
-    static RefPtr<LightSource> findLightSource(const SVGElement*);
 
 protected:
     SVGFELightElement(const QualifiedName&, Document&);

Modified: trunk/Source/WebCore/svg/SVGFEPointLightElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFEPointLightElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFEPointLightElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -19,9 +19,12 @@
 
 #include "config.h"
 #include "SVGFEPointLightElement.h"
-#include "SVGNames.h"
 
+#include "GeometryUtilities.h"
 #include "PointLightSource.h"
+#include "SVGFilterBuilder.h"
+#include "SVGNames.h"
+#include <wtf/MathExtras.h>
 
 namespace WebCore {
 
@@ -36,9 +39,21 @@
     return adoptRef(*new SVGFEPointLightElement(tagName, document));
 }
 
-Ref<LightSource> SVGFEPointLightElement::lightSource() const
+Ref<LightSource> SVGFEPointLightElement::lightSource(SVGFilterBuilder& builder) const
 {
-    return PointLightSource::create(FloatPoint3D(x(), y(), z()));
+    FloatPoint3D position;
+    if (builder.primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        FloatRect referenceBox = builder.targetBoundingBox();
+        
+        position.setX(referenceBox.x() + x() * referenceBox.width());
+        position.setY(referenceBox.y() + y() * referenceBox.height());
+
+        // https://www.w3.org/TR/SVG/filters.html#fePointLightZAttribute and https://www.w3.org/TR/SVG/coords.html#Units_viewport_percentage
+        position.setZ(z() * euclidianDistance(referenceBox.minXMinYCorner(), referenceBox.maxXMaxYCorner()) / sqrtOfTwoFloat);
+    } else
+        position = FloatPoint3D(x(), y(), z());
+    
+    return PointLightSource::create(position);
 }
 
 }

Modified: trunk/Source/WebCore/svg/SVGFEPointLightElement.h (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFEPointLightElement.h	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFEPointLightElement.h	2018-01-03 21:56:00 UTC (rev 226373)
@@ -30,7 +30,7 @@
 private:
     SVGFEPointLightElement(const QualifiedName&, Document&);
 
-    Ref<LightSource> lightSource() const override;
+    Ref<LightSource> lightSource(SVGFilterBuilder&) const override;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/svg/SVGFESpecularLightingElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFESpecularLightingElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFESpecularLightingElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -188,9 +188,11 @@
     if (!input1)
         return nullptr;
 
-    auto lightSource = SVGFELightElement::findLightSource(this);
-    if (!lightSource)
+    auto lightElement = makeRefPtr(SVGFELightElement::findLightElement(this));
+    if (!lightElement)
         return nullptr;
+    
+    auto lightSource = lightElement->lightSource(*filterBuilder);
 
     RenderObject* renderer = this->renderer();
     if (!renderer)
@@ -198,7 +200,7 @@
     
     const Color& color = renderer->style().svgStyle().lightingColor();
 
-    RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, surfaceScale(), specularConstant(), specularExponent(), kernelUnitLengthX(), kernelUnitLengthY(), lightSource.releaseNonNull());
+    RefPtr<FilterEffect> effect = FESpecularLighting::create(filter, color, surfaceScale(), specularConstant(), specularExponent(), kernelUnitLengthX(), kernelUnitLengthY(), WTFMove(lightSource));
     effect->inputEffects().append(input1);
     return effect;
 }

Modified: trunk/Source/WebCore/svg/SVGFESpotLightElement.cpp (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFESpotLightElement.cpp	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFESpotLightElement.cpp	2018-01-03 21:56:00 UTC (rev 226373)
@@ -20,8 +20,11 @@
 #include "config.h"
 #include "SVGFESpotLightElement.h"
 
+#include "GeometryUtilities.h"
+#include "SVGFilterBuilder.h"
 #include "SVGNames.h"
 #include "SpotLightSource.h"
+#include <wtf/MathExtras.h>
 
 namespace WebCore {
 
@@ -36,12 +39,29 @@
     return adoptRef(*new SVGFESpotLightElement(tagName, document));
 }
 
-Ref<LightSource> SVGFESpotLightElement::lightSource() const
+Ref<LightSource> SVGFESpotLightElement::lightSource(SVGFilterBuilder& builder) const
 {
-    FloatPoint3D pos(x(), y(), z());
-    FloatPoint3D direction(pointsAtX(), pointsAtY(), pointsAtZ());
+    FloatPoint3D position;
+    FloatPoint3D pointsAt;
 
-    return SpotLightSource::create(pos, direction, specularExponent(), limitingConeAngle());
+    if (builder.primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        FloatRect referenceBox = builder.targetBoundingBox();
+        
+        position.setX(referenceBox.x() + x() * referenceBox.width());
+        position.setY(referenceBox.y() + y() * referenceBox.height());
+        // https://www.w3.org/TR/SVG/filters.html#fePointLightZAttribute and https://www.w3.org/TR/SVG/coords.html#Units_viewport_percentage
+        position.setZ(z() * euclidianDistance(referenceBox.minXMinYCorner(), referenceBox.maxXMaxYCorner()) / sqrtOfTwoFloat);
+
+        pointsAt.setX(referenceBox.x() + pointsAtX() * referenceBox.width());
+        pointsAt.setY(referenceBox.y() + pointsAtY() * referenceBox.height());
+        // https://www.w3.org/TR/SVG/filters.html#fePointLightZAttribute and https://www.w3.org/TR/SVG/coords.html#Units_viewport_percentage
+        pointsAt.setZ(pointsAtZ() * euclidianDistance(referenceBox.minXMinYCorner(), referenceBox.maxXMaxYCorner()) / sqrtOfTwoFloat);
+    } else {
+        position = FloatPoint3D(x(), y(), z());
+        pointsAt = FloatPoint3D(pointsAtX(), pointsAtY(), pointsAtZ());
+    }
+
+    return SpotLightSource::create(position, pointsAt, specularExponent(), limitingConeAngle());
 }
 
 }

Modified: trunk/Source/WebCore/svg/SVGFESpotLightElement.h (226372 => 226373)


--- trunk/Source/WebCore/svg/SVGFESpotLightElement.h	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/SVGFESpotLightElement.h	2018-01-03 21:56:00 UTC (rev 226373)
@@ -30,7 +30,7 @@
 private:
     SVGFESpotLightElement(const QualifiedName&, Document&);
 
-    Ref<LightSource> lightSource() const override;
+    Ref<LightSource> lightSource(SVGFilterBuilder&) const override;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h (226372 => 226373)


--- trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2018-01-03 21:21:09 UTC (rev 226372)
+++ trunk/Source/WebCore/svg/graphics/filters/SVGFilterBuilder.h	2018-01-03 21:56:00 UTC (rev 226373)
@@ -21,6 +21,7 @@
 #pragma once
 
 #include "FilterEffect.h"
+#include "SVGUnitTypes.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/text/AtomicStringHash.h>
@@ -29,6 +30,7 @@
 namespace WebCore {
 
 class RenderObject;
+class SVGFilterElement;
 
 class SVGFilterBuilder {
 public:
@@ -36,6 +38,12 @@
 
     SVGFilterBuilder(RefPtr<FilterEffect> sourceGraphic);
 
+    void setTargetBoundingBox(const FloatRect& r) { m_targetBoundingBox = r; }
+    FloatRect targetBoundingBox() const { return m_targetBoundingBox; }
+    
+    SVGUnitTypes::SVGUnitType primitiveUnits() const { return m_primitiveUnits; }
+    void setPrimitiveUnits(SVGUnitTypes::SVGUnitType units) { m_primitiveUnits = units; }
+
     void add(const AtomicString& id, RefPtr<FilterEffect>);
 
     RefPtr<FilterEffect> getEffectById(const AtomicString& id) const;
@@ -71,6 +79,8 @@
     HashMap<RenderObject*, FilterEffect*> m_effectRenderer;
 
     RefPtr<FilterEffect> m_lastEffect;
+    FloatRect m_targetBoundingBox;
+    SVGUnitTypes::SVGUnitType m_primitiveUnits { SVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE };
 };
     
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to