Title: [225018] trunk
Revision
225018
Author
[email protected]
Date
2017-11-18 12:37:33 -0800 (Sat, 18 Nov 2017)

Log Message

feTurbulence with stitchTiles is broken
https://bugs.webkit.org/show_bug.cgi?id=179862

Reviewed by Zalan Bujtas.

Source/WebCore:

The "stitchTiles" logic was broken, and not equivalent to the spec sample code,
because it didn't compute and wrap the bx1 and by1 equivalents separately from
bx0 and by0.

Annotated the code with the equivalent sample code from the spec for ease of
comparison.

Also make some functions const.

Test: svg/filters/feTurbulence-stitchTiles.html

* platform/graphics/filters/FETurbulence.cpp:
(WebCore::FETurbulence::noise2D const):
(WebCore::FETurbulence::calculateTurbulenceValueForPoint const):
(WebCore::FETurbulence::fillRegion const):
(WebCore::checkNoise): Deleted.
(WebCore::FETurbulence::noise2D): Deleted.
(WebCore::FETurbulence::calculateTurbulenceValueForPoint): Deleted.
(WebCore::FETurbulence::fillRegion): Deleted.
* platform/graphics/filters/FETurbulence.h:
* platform/graphics/filters/FilterEffect.h:
(WebCore::FilterEffect::filter const):

LayoutTests:

Ref test that masks out an empty area of the filter and compares with a green rectangle.

* svg/filters/feTurbulence-stitchTiles-expected.html: Added.
* svg/filters/feTurbulence-stitchTiles.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (225017 => 225018)


--- trunk/LayoutTests/ChangeLog	2017-11-18 17:25:28 UTC (rev 225017)
+++ trunk/LayoutTests/ChangeLog	2017-11-18 20:37:33 UTC (rev 225018)
@@ -1,3 +1,15 @@
+2017-11-18  Simon Fraser  <[email protected]>
+
+        feTurbulence with stitchTiles is broken
+        https://bugs.webkit.org/show_bug.cgi?id=179862
+
+        Reviewed by Zalan Bujtas.
+        
+        Ref test that masks out an empty area of the filter and compares with a green rectangle.
+
+        * svg/filters/feTurbulence-stitchTiles-expected.html: Added.
+        * svg/filters/feTurbulence-stitchTiles.html: Added.
+
 2017-11-18  Antti Koivisto  <[email protected]>
 
         Add test for a multicolumn render tree update issue

Added: trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles-expected.html (0 => 225018)


--- trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles-expected.html	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles-expected.html	2017-11-18 20:37:33 UTC (rev 225018)
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+    <body>
+        <p>You should see a solid green square below</p>
+        <svg width="800px" height="800px" xmlns="http://www.w3.org/2000/svg">
+            <defs>
+                <clipPath id="clip-out-middle">
+                  <rect x="160" y="160" width="80" height="80" />
+                </clipPath>
+            </defs>
+            <rect x="160" y="160" width="80" height="80" fill="green" clip-path="url(#clip-out-middle)"/>
+        </svg>
+        </div>
+    </body>
+</html>

Added: trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles.html (0 => 225018)


--- trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles.html	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/feTurbulence-stitchTiles.html	2017-11-18 20:37:33 UTC (rev 225018)
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+    <body>
+        <p>You should see a solid green square below</p>
+        <svg width="800px" height="800px" xmlns="http://www.w3.org/2000/svg">
+            <defs>
+                <filter id="light" filterUnits="userSpaceOnUse" x="100" y="100" width="200" height="200">
+                    <feTurbulence  seed="1" type="turbulence" baseFrequency="0.01" numOctaves="1" stitchTiles="stitch" />
+                    <feComponentTransfer>
+                      <feFuncR type="discrete" tableValues="0 0.5 0.5 0.5 1" />
+                      <feFuncG type="discrete" tableValues="0 0.5 0.5 0.5 1" />
+                      <feFuncB type="discrete" tableValues="0 0.5 0.5 0.5 1" />
+                      <feFuncA type="discrete" tableValues="0 1 1 1 1" />
+                    </feComponentTransfer>
+                </filter>
+                <clipPath id="clip-out-middle">
+                  <rect x="160" y="160" width="80" height="80" />
+                </clipPath>
+            </defs>
+            <rect x="160" y="160" width="80" height="80" fill="green" />
+            <rect x="0" y="0" width="400" height="400" filter="url(#light)" clip-path="url(#clip-out-middle)"/>
+        </svg>
+        </div>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (225017 => 225018)


--- trunk/Source/WebCore/ChangeLog	2017-11-18 17:25:28 UTC (rev 225017)
+++ trunk/Source/WebCore/ChangeLog	2017-11-18 20:37:33 UTC (rev 225018)
@@ -1,3 +1,33 @@
+2017-11-18  Simon Fraser  <[email protected]>
+
+        feTurbulence with stitchTiles is broken
+        https://bugs.webkit.org/show_bug.cgi?id=179862
+
+        Reviewed by Zalan Bujtas.
+        
+        The "stitchTiles" logic was broken, and not equivalent to the spec sample code,
+        because it didn't compute and wrap the bx1 and by1 equivalents separately from
+        bx0 and by0.
+        
+        Annotated the code with the equivalent sample code from the spec for ease of
+        comparison.
+        
+        Also make some functions const.
+
+        Test: svg/filters/feTurbulence-stitchTiles.html
+
+        * platform/graphics/filters/FETurbulence.cpp:
+        (WebCore::FETurbulence::noise2D const):
+        (WebCore::FETurbulence::calculateTurbulenceValueForPoint const):
+        (WebCore::FETurbulence::fillRegion const):
+        (WebCore::checkNoise): Deleted.
+        (WebCore::FETurbulence::noise2D): Deleted.
+        (WebCore::FETurbulence::calculateTurbulenceValueForPoint): Deleted.
+        (WebCore::FETurbulence::fillRegion): Deleted.
+        * platform/graphics/filters/FETurbulence.h:
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::filter const):
+
 2017-11-18  Antti Koivisto  <[email protected]>
 
         REGRESSION (r220646): REGRESSION (r220646): RenderTreePosition::computeNextSibling hits assertion with certain first-letter mutations

Modified: trunk/Source/WebCore/platform/graphics/filters/FETurbulence.cpp (225017 => 225018)


--- trunk/Source/WebCore/platform/graphics/filters/FETurbulence.cpp	2017-11-18 17:25:28 UTC (rev 225017)
+++ trunk/Source/WebCore/platform/graphics/filters/FETurbulence.cpp	2017-11-18 20:37:33 UTC (rev 225018)
@@ -179,63 +179,100 @@
     }
 }
 
-inline void checkNoise(int& noiseValue, int limitValue, int newValue)
+// This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement.
+FloatComponents FETurbulence::noise2D(const PaintingData& paintingData, const StitchData& stitchData, const FloatPoint& noiseVector) const
 {
-    if (noiseValue >= limitValue)
-        noiseValue -= newValue;
-    if (noiseValue >= limitValue - 1)
-        noiseValue -= newValue - 1;
-}
+    struct NoisePosition {
+        int index; // bx0, by0 in the spec text.
+        int nextIndex; // bx1, by1 in the spec text.
+        float fraction; // rx0, ry0 in the spec text.
 
-FloatComponents FETurbulence::noise2D(const PaintingData& paintingData, StitchData& stitchData, const FloatPoint& noiseVector)
-{
-    struct Noise {
-        int noisePositionIntegerValue;
-        float noisePositionFractionValue;
-
-        Noise(float component)
+        NoisePosition(float component)
         {
+            //  t = vec[0] + PerlinN;
+            //  bx0 = (int)t;
+            //  bx1 = bx0+1;
+            //  rx0 = t - (int)t;
             float position = component + s_perlinNoise;
-            noisePositionIntegerValue = static_cast<int>(position);
-            noisePositionFractionValue = position - noisePositionIntegerValue;
+            index = static_cast<int>(position);
+            nextIndex = index + 1;
+            fraction = position - index;
         }
+        
+        void stitch(int size, int wrapSize)
+        {
+            // if (bx0 >= pStitchInfo->nWrapX)
+            //   bx0 -= pStitchInfo->nWidth;
+            if (index >= wrapSize)
+                index -= size;
+
+            // if (bx1 >= pStitchInfo->nWrapX)
+            //   bx1 -= pStitchInfo->nWidth;
+            if (nextIndex >= wrapSize)
+                nextIndex -= size;
+        }
     };
 
-    Noise noiseX(noiseVector.x());
-    Noise noiseY(noiseVector.y());
+    NoisePosition noiseX(noiseVector.x());
+    NoisePosition noiseY(noiseVector.y());
 
     // If stitching, adjust lattice points accordingly.
     if (m_stitchTiles) {
-        checkNoise(noiseX.noisePositionIntegerValue, stitchData.wrapX, stitchData.width);
-        checkNoise(noiseY.noisePositionIntegerValue, stitchData.wrapY, stitchData.height);
+        noiseX.stitch(stitchData.width, stitchData.wrapX);
+        noiseY.stitch(stitchData.height, stitchData.wrapY);
     }
 
-    noiseX.noisePositionIntegerValue &= s_blockMask;
-    noiseY.noisePositionIntegerValue &= s_blockMask;
-    int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue];
-    int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask];
+    // bx0 &= BM;
+    // bx1 &= BM;
+    // by0 &= BM;
+    // by1 &= BM;
+    noiseX.index &= s_blockMask;
+    noiseX.nextIndex &= s_blockMask;
+    noiseY.index &= s_blockMask;
+    noiseY.nextIndex &= s_blockMask;
 
-    float sx = smoothCurve(noiseX.noisePositionFractionValue);
-    float sy = smoothCurve(noiseY.noisePositionFractionValue);
+    // i = uLatticeSelector[bx0];
+    // j = uLatticeSelector[bx1];
+    int latticeIndex = paintingData.latticeSelector[noiseX.index];
+    int nextLatticeIndex = paintingData.latticeSelector[noiseX.nextIndex];
 
+    // sx = double(s_curve(rx0));
+    // sy = double(s_curve(ry0));
+    float sx = smoothCurve(noiseX.fraction);
+    float sy = smoothCurve(noiseY.fraction);
+
     auto noiseForChannel = [&](int channel) {
-        // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement.
-        int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue];
-        const float* q = paintingData.gradient[channel][temp];
+        // b00 = uLatticeSelector[i + by0]
+        int b00 = paintingData.latticeSelector[latticeIndex + noiseY.index];
+        // q = fGradient[nColorChannel][b00]; u = rx0 * q[0] + ry0 * q[1];
+        const float* q = paintingData.gradient[channel][b00];
+        float u = noiseX.fraction * q[0] + noiseY.fraction * q[1];
 
-        float u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1];
-        temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue];
-        q = paintingData.gradient[channel][temp];
-        float v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1];
+        // b10 = uLatticeSelector[j + by0];
+        int b10 = paintingData.latticeSelector[nextLatticeIndex + noiseY.index];
+        // rx1 = rx0 - 1.0f;
+        // q = fGradient[nColorChannel][b10]; v = rx1 * q[0] + ry0 * q[1];
+        q = paintingData.gradient[channel][b10];
+        float v = (noiseX.fraction - 1) * q[0] + noiseY.fraction * q[1];
+        // a = lerp(sx, u, v);
         float a = linearInterpolation(sx, u, v);
-        temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1];
-        q = paintingData.gradient[channel][temp];
-        u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1];
-        temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1];
-        q = paintingData.gradient[channel][temp];
-        v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1];
+
+        // b01 = uLatticeSelector[i + by1];
+        int b01 = paintingData.latticeSelector[latticeIndex + noiseY.nextIndex];
+        // ry1 = ry0 - 1.0f;
+        // q = fGradient[nColorChannel][b01]; u = rx0 * q[0] + ry1 * q[1];
+        q = paintingData.gradient[channel][b01];
+        u = noiseX.fraction * q[0] + (noiseY.fraction - 1) * q[1];
+
+        // b11 = uLatticeSelector[j + by1];
+        int b11 = paintingData.latticeSelector[nextLatticeIndex + noiseY.nextIndex];
+        // q = fGradient[nColorChannel][b11]; v = rx1 * q[0] + ry1 * q[1];
+        q = paintingData.gradient[channel][b11];
+        v = (noiseX.fraction - 1) * q[0] + (noiseY.fraction - 1) * q[1];
+        // b = lerp(sx, u, v);
         float b = linearInterpolation(sx, u, v);
 
+        // return lerp(sy, a, b);
         return linearInterpolation(sy, a, b);
     };
 
@@ -247,11 +284,12 @@
     };
 }
 
-ColorComponents FETurbulence::calculateTurbulenceValueForPoint(const PaintingData& paintingData, StitchData& stitchData, const FloatPoint& point)
+ColorComponents FETurbulence::calculateTurbulenceValueForPoint(const PaintingData& paintingData, StitchData& stitchData, const FloatPoint& point) const
 {
     float tileWidth = paintingData.filterSize.width();
     float tileHeight = paintingData.filterSize.height();
     ASSERT(tileWidth > 0 && tileHeight > 0);
+    
     float baseFrequencyX = m_baseFrequencyX;
     float baseFrequencyY = m_baseFrequencyY;
 
@@ -314,7 +352,7 @@
     return turbulenceFunctionResult;
 }
 
-void FETurbulence::fillRegion(Uint8ClampedArray* pixelArray, const PaintingData& paintingData, int startY, int endY)
+void FETurbulence::fillRegion(Uint8ClampedArray* pixelArray, const PaintingData& paintingData, int startY, int endY) const
 {
     IntRect filterRegion = absolutePaintRect();
     FloatPoint point(0, filterRegion.y() + startY);

Modified: trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h (225017 => 225018)


--- trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h	2017-11-18 17:25:28 UTC (rev 225017)
+++ trunk/Source/WebCore/platform/graphics/filters/FETurbulence.h	2017-11-18 20:37:33 UTC (rev 225018)
@@ -119,9 +119,9 @@
     FETurbulence(Filter&, TurbulenceType, float, float, int, float, bool);
 
     void initPaint(PaintingData&);
-    FloatComponents noise2D(const PaintingData&, StitchData&, const FloatPoint&);
-    ColorComponents calculateTurbulenceValueForPoint(const PaintingData&, StitchData&, const FloatPoint&);
-    void fillRegion(Uint8ClampedArray*, const PaintingData&, int, int);
+    FloatComponents noise2D(const PaintingData&, const StitchData&, const FloatPoint&) const;
+    ColorComponents calculateTurbulenceValueForPoint(const PaintingData&, StitchData&, const FloatPoint&) const;
+    void fillRegion(Uint8ClampedArray*, const PaintingData&, int startY, int endY) const;
 
     TurbulenceType m_type;
     float m_baseFrequencyX;

Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (225017 => 225018)


--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2017-11-18 17:25:28 UTC (rev 225017)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h	2017-11-18 20:37:33 UTC (rev 225018)
@@ -144,6 +144,7 @@
     void setEffectBoundaries(const FloatRect& effectBoundaries) { m_effectBoundaries = effectBoundaries; }
 
     Filter& filter() { return m_filter; }
+    const Filter& filter() const { return m_filter; }
 
     bool clipsToBounds() const { return m_clipsToBounds; }
     void setClipsToBounds(bool value) { m_clipsToBounds = value; }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to