Title: [154948] trunk
Revision
154948
Author
[email protected]
Date
2013-09-01 21:53:46 -0700 (Sun, 01 Sep 2013)

Log Message

Source/WebCore: Add 'edgeMode' attribute to SVGFEGaussianBlur
https://bugs.webkit.org/show_bug.cgi?id=120582

Add 'edgeMode' attribute to the SVGFEGaussianBlur element. This attribute
allows users to define the behavior on edges with the values 'none' where
pixel values outside the input image are treated as transparent black. (The
current blurring behavior.) 'duplicate' which repeats the values on the
nearest edge and 'warp', which takes the pixel of the opposite site of
the input image.
Beside the attribute, this patch implements the behavior of 'duplicate'.

http://dev.w3.org/fxtf/filters/#feGaussianBlurEdgeModeAttribute

Reviewed by Rob Buis.

Tests: svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html
       svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html
       svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg
       svg/filters/svg-gaussianblur-edgeMode-duplicate.svg

* platform/graphics/filters/FEGaussianBlur.cpp:
(WebCore::FEGaussianBlur::FEGaussianBlur):
(WebCore::FEGaussianBlur::create):
(WebCore::FEGaussianBlur::edgeMode):
(WebCore::FEGaussianBlur::setEdgeMode):
(WebCore::boxBlur):
(WebCore::FEGaussianBlur::platformApplyGeneric):
(WebCore::FEGaussianBlur::determineAbsolutePaintRect):
* platform/graphics/filters/FEGaussianBlur.h:
* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRenderer::build):
* svg/SVGFEGaussianBlurElement.cpp:
(WebCore::SVGFEGaussianBlurElement::SVGFEGaussianBlurElement):
(WebCore::SVGFEGaussianBlurElement::isSupportedAttribute):
(WebCore::SVGFEGaussianBlurElement::parseAttribute):
(WebCore::SVGFEGaussianBlurElement::svgAttributeChanged):
(WebCore::SVGFEGaussianBlurElement::build):
* svg/SVGFEGaussianBlurElement.h:
* svg/SVGFEGaussianBlurElement.idl:

LayoutTests: Add edgeMode attribtue.

Add 'edgeMode' attribute to SVGFEGaussianBlur
https://bugs.webkit.org/show_bug.cgi?id=120582

Added DOM and SVGDOM tests for the attribute 'edgeMode'.
Also added a reftest to test edgeMode='duplicate'.

Reviewed by Rob Buis.

* platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png: Added.
* svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt: Added.
* svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html: Added.
* svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt: Added.
* svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html: Added.
* svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js: Added.
(repaintTest):
* svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js: Added.
(repaintTest):
* svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg: Added.
* svg/filters/svg-gaussianblur-edgeMode-duplicate.svg: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (154947 => 154948)


--- trunk/LayoutTests/ChangeLog	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/LayoutTests/ChangeLog	2013-09-02 04:53:46 UTC (rev 154948)
@@ -1,3 +1,27 @@
+2013-09-01  Dirk Schulze  <[email protected]>
+
+        Add edgeMode attribtue.
+
+        Add 'edgeMode' attribute to SVGFEGaussianBlur
+        https://bugs.webkit.org/show_bug.cgi?id=120582
+
+        Added DOM and SVGDOM tests for the attribute 'edgeMode'.
+        Also added a reftest to test edgeMode='duplicate'.
+
+        Reviewed by Rob Buis.
+
+        * platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png: Added.
+        * svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt: Added.
+        * svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html: Added.
+        * svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt: Added.
+        * svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html: Added.
+        * svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js: Added.
+        (repaintTest):
+        * svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js: Added.
+        (repaintTest):
+        * svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg: Added.
+        * svg/filters/svg-gaussianblur-edgeMode-duplicate.svg: Added.
+
 2013-09-01  Xabier Rodriguez Calvar  <[email protected]>
 
         Volume slider value should be 0 when audio is muted

Added: trunk/LayoutTests/platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png


(Binary files differ)
Property changes on: trunk/LayoutTests/platform/mac/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.png ___________________________________________________________________

Added: svn:mime-type

Added: trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr-expected.txt	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,13 @@
+SVG 1.1 dynamic update tests
+
+Tests dynamic updates of the 'edgeMode' attribute of the SVGFEGaussianBlurElement object
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS gaussianBlurElement.getAttribute('edgeMode') is "wrap"
+PASS gaussianBlurElement.getAttribute('edgeMode') is "duplicate"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body _onload_="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop-expected.txt	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,13 @@
+SVG 1.1 dynamic update tests
+
+Tests dynamic updates of the 'edgeMode' property of the SVGFEGaussianBlurElement object
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS gaussianBlurElement.edgeMode.baseVal is SVGFEGaussianBlurElement.SVG_EDGEMODE_WRAP
+PASS gaussianBlurElement.edgeMode.baseVal is SVGFEGaussianBlurElement.SVG_EDGEMODE_DUPLICATE
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body _onload_="runRepaintTest()">
+<h1>SVG 1.1 dynamic update tests</h1>
+<p id="description"></p>
+<div id="console"></div>
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-dom-edgeMode-attr.js	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,46 @@
+// [Name] SVGFEGaussianBlurElement-dom-edgeMode-attr.js
+// [Expected rendering result] An image with feGaussianBlur filter - and a series of PASS messages
+
+description("Tests dynamic updates of the 'edgeMode' attribute of the SVGFEGaussianBlurElement object")
+createSVGTestCase();
+
+var gaussianBlurElement = createSVGElement("feGaussianBlur");
+gaussianBlurElement.setAttribute("in", "SourceGraphic");
+gaussianBlurElement.setAttribute("stdDeviation", "10");
+gaussianBlurElement.setAttribute("edgeMode", "wrap");
+
+var filterElement = createSVGElement("filter");
+filterElement.setAttribute("id", "myFilter");
+filterElement.setAttribute("filterUnits", "userSpaceOnUse");
+filterElement.setAttribute("x", "0");
+filterElement.setAttribute("y", "0");
+filterElement.setAttribute("width", "200");
+filterElement.setAttribute("height", "200");
+filterElement.appendChild(gaussianBlurElement);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(filterElement);
+
+rootSVGElement.appendChild(defsElement);
+rootSVGElement.setAttribute("width", "700");
+rootSVGElement.setAttribute("height", "200");
+
+var imageElement = createSVGElement("image");
+imageElement.setAttributeNS(xlinkNS, "xlink:href", "../W3C-SVG-1.1/resources/convolveImage.png");
+imageElement.setAttribute("x", "0");
+imageElement.setAttribute("y", "0");
+imageElement.setAttribute("width", "200");
+imageElement.setAttribute("height", "200");
+imageElement.setAttribute("filter", "url(#myFilter)");
+rootSVGElement.appendChild(imageElement);
+
+shouldBeEqualToString("gaussianBlurElement.getAttribute('edgeMode')", "wrap");
+
+function repaintTest() {
+    gaussianBlurElement.setAttribute("edgeMode", "duplicate");
+    shouldBeEqualToString("gaussianBlurElement.getAttribute('edgeMode')", "duplicate");
+
+    completeTest();
+}
+
+var successfullyParsed = true;

Added: trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js (0 => 154948)


--- trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js	                        (rev 0)
+++ trunk/LayoutTests/svg/dynamic-updates/script-tests/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.js	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,46 @@
+// [Name] SVGFEGaussianBlurElement-dom-edgeMode-prop.js
+// [Expected rendering result] An image with feGaussianBlur filter - and a series of PASS messages
+
+description("Tests dynamic updates of the 'edgeMode' property of the SVGFEGaussianBlurElement object")
+createSVGTestCase();
+
+var gaussianBlurElement = createSVGElement("feGaussianBlur");
+gaussianBlurElement.setAttribute("in", "SourceGraphic");
+gaussianBlurElement.setAttribute("stdDeviation", "10");
+gaussianBlurElement.setAttribute("edgeMode", "wrap");
+
+var filterElement = createSVGElement("filter");
+filterElement.setAttribute("id", "myFilter");
+filterElement.setAttribute("filterUnits", "userSpaceOnUse");
+filterElement.setAttribute("x", "0");
+filterElement.setAttribute("y", "0");
+filterElement.setAttribute("width", "200");
+filterElement.setAttribute("height", "200");
+filterElement.appendChild(gaussianBlurElement);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(filterElement);
+
+rootSVGElement.appendChild(defsElement);
+rootSVGElement.setAttribute("width", "700");
+rootSVGElement.setAttribute("height", "200");
+
+var imageElement = createSVGElement("image");
+imageElement.setAttributeNS(xlinkNS, "xlink:href", "../W3C-SVG-1.1/resources/convolveImage.png");
+imageElement.setAttribute("x", "0");
+imageElement.setAttribute("y", "0");
+imageElement.setAttribute("width", "200");
+imageElement.setAttribute("height", "200");
+imageElement.setAttribute("filter", "url(#myFilter)");
+rootSVGElement.appendChild(imageElement);
+
+shouldBe("gaussianBlurElement.edgeMode.baseVal", "SVGFEGaussianBlurElement.SVG_EDGEMODE_WRAP");
+
+function repaintTest() {
+    gaussianBlurElement.edgeMode.baseVal = SVGFEGaussianBlurElement.SVG_EDGEMODE_DUPLICATE;
+    shouldBe("gaussianBlurElement.edgeMode.baseVal", "SVGFEGaussianBlurElement.SVG_EDGEMODE_DUPLICATE");
+
+    completeTest();
+}
+
+var successfullyParsed = true;

Added: trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg (0 => 154948)


--- trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,14 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<filter id="blur">
+<feGaussianBlur stdDeviation="3"/>
+</filter>
+<clipPath id="clip">
+<rect x="20" y="20" width="140" height="140"/>
+</clipPath>
+</defs>
+<g filter="url(#blur)" clip-path="url(#clip)">
+<rect width="180" height="180" fill="green"/>
+<rect x="40" y="40" width="100" height="100" fill="blue"/>
+</g>
+</svg>
\ No newline at end of file

Added: trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate.svg (0 => 154948)


--- trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate.svg	                        (rev 0)
+++ trunk/LayoutTests/svg/filters/svg-gaussianblur-edgeMode-duplicate.svg	2013-09-02 04:53:46 UTC (rev 154948)
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<filter id="blur">
+<feGaussianBlur stdDeviation="3" edgeMode="duplicate"/>
+</filter>
+</defs>
+<g filter="url(#blur)">
+<rect x="20" y="20" width="140" height="140" fill="green"/>
+<rect x="40" y="40" width="100" height="100" fill="blue"/>
+</g>
+</svg>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (154947 => 154948)


--- trunk/Source/WebCore/ChangeLog	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/ChangeLog	2013-09-02 04:53:46 UTC (rev 154948)
@@ -1,3 +1,45 @@
+2013-09-01  Dirk Schulze  <[email protected]>
+
+        Add 'edgeMode' attribute to SVGFEGaussianBlur
+        https://bugs.webkit.org/show_bug.cgi?id=120582
+
+        Add 'edgeMode' attribute to the SVGFEGaussianBlur element. This attribute
+        allows users to define the behavior on edges with the values 'none' where
+        pixel values outside the input image are treated as transparent black. (The
+        current blurring behavior.) 'duplicate' which repeats the values on the
+        nearest edge and 'warp', which takes the pixel of the opposite site of
+        the input image.
+        Beside the attribute, this patch implements the behavior of 'duplicate'.
+
+        http://dev.w3.org/fxtf/filters/#feGaussianBlurEdgeModeAttribute
+
+        Reviewed by Rob Buis.
+
+        Tests: svg/dynamic-updates/SVGFEGaussianBlurElement-dom-edgeMode-attr.html
+               svg/dynamic-updates/SVGFEGaussianBlurElement-svgdom-edgeMode-prop.html
+               svg/filters/svg-gaussianblur-edgeMode-duplicate-expected.svg
+               svg/filters/svg-gaussianblur-edgeMode-duplicate.svg
+
+        * platform/graphics/filters/FEGaussianBlur.cpp:
+        (WebCore::FEGaussianBlur::FEGaussianBlur):
+        (WebCore::FEGaussianBlur::create):
+        (WebCore::FEGaussianBlur::edgeMode):
+        (WebCore::FEGaussianBlur::setEdgeMode):
+        (WebCore::boxBlur):
+        (WebCore::FEGaussianBlur::platformApplyGeneric):
+        (WebCore::FEGaussianBlur::determineAbsolutePaintRect):
+        * platform/graphics/filters/FEGaussianBlur.h:
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRenderer::build):
+        * svg/SVGFEGaussianBlurElement.cpp:
+        (WebCore::SVGFEGaussianBlurElement::SVGFEGaussianBlurElement):
+        (WebCore::SVGFEGaussianBlurElement::isSupportedAttribute):
+        (WebCore::SVGFEGaussianBlurElement::parseAttribute):
+        (WebCore::SVGFEGaussianBlurElement::svgAttributeChanged):
+        (WebCore::SVGFEGaussianBlurElement::build):
+        * svg/SVGFEGaussianBlurElement.h:
+        * svg/SVGFEGaussianBlurElement.idl:
+
 2013-09-01  Andreas Kling  <[email protected]>
 
         EventHandler::m_frame should be a Frame&.

Modified: trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp (154947 => 154948)


--- trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.cpp	2013-09-02 04:53:46 UTC (rev 154948)
@@ -50,16 +50,17 @@
 
 namespace WebCore {
 
-FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y)
+FEGaussianBlur::FEGaussianBlur(Filter* filter, float x, float y, EdgeModeType edgeMode)
     : FilterEffect(filter)
     , m_stdX(x)
     , m_stdY(y)
+    , m_edgeMode(edgeMode)
 {
 }
 
-PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(Filter* filter, float x, float y)
+PassRefPtr<FEGaussianBlur> FEGaussianBlur::create(Filter* filter, float x, float y, EdgeModeType edgeMode)
 {
-    return adoptRef(new FEGaussianBlur(filter, x, y));
+    return adoptRef(new FEGaussianBlur(filter, x, y, edgeMode));
 }
 
 float FEGaussianBlur::stdDeviationX() const
@@ -82,26 +83,69 @@
     m_stdY = y;
 }
 
+EdgeModeType FEGaussianBlur::edgeMode() const
+{
+    return m_edgeMode;
+}
+
+void FEGaussianBlur::setEdgeMode(EdgeModeType edgeMode)
+{
+    m_edgeMode = edgeMode;
+}
+
 inline void boxBlur(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* dstPixelArray,
-                    unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage)
+    unsigned dx, int dxLeft, int dxRight, int stride, int strideLine, int effectWidth, int effectHeight, bool alphaImage, EdgeModeType edgeMode)
 {
     for (int y = 0; y < effectHeight; ++y) {
         int line = y * strideLine;
         for (int channel = 3; channel >= 0; --channel) {
             int sum = 0;
-            // Fill the kernel
-            int maxKernelSize = min(dxRight, effectWidth);
-            for (int i = 0; i < maxKernelSize; ++i)
-                sum += srcPixelArray->item(line + i * stride + channel);
+            // The code for edgeMode='none' is the common case and highly optimized.
+            // Furthermore, this code path affects more than just the input area.
+            if (edgeMode == EDGEMODE_NONE) {
+                // Fill the kernel
+                int maxKernelSize = min(dxRight, effectWidth);
+                for (int i = 0; i < maxKernelSize; ++i)
+                    sum += srcPixelArray->item(line + i * stride + channel);
 
-            // Blurring
-            for (int x = 0; x < effectWidth; ++x) {
-                int pixelByteOffset = line + x * stride + channel;
-                dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
-                if (x >= dxLeft)
-                    sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
-                if (x + dxRight < effectWidth)
-                    sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
+                // Blurring
+                for (int x = 0; x < effectWidth; ++x) {
+                    int pixelByteOffset = line + x * stride + channel;
+                    dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
+                    // Shift kernel.
+                    if (x >= dxLeft)
+                        sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
+                    if (x + dxRight < effectWidth)
+                        sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
+                }
+            } else {
+                // FIXME: Add support for 'wrap' here.
+                // Get edge values for edgeMode 'duplicate'.
+                int edgeValueLeft = srcPixelArray->item(line + channel);
+                int edgeValueRight = srcPixelArray->item(line + (effectWidth - 1) * stride + channel);
+                // Fill the kernel
+                for (int i = dxLeft * -1; i < dxRight; ++i) {
+                    if (i < 0)
+                        sum += edgeValueLeft;
+                    else if (i >= effectWidth)
+                        sum += edgeValueRight;
+                    else
+                        sum += srcPixelArray->item(line + i * stride + channel);
+                }
+                // Blurring
+                for (int x = 0; x < effectWidth; ++x) {
+                    int pixelByteOffset = line + x * stride + channel;
+                    dstPixelArray->set(pixelByteOffset, static_cast<unsigned char>(sum / dx));
+                    // Shift kernel.
+                    if (x < dxLeft)
+                        sum -= edgeValueLeft;
+                    else
+                        sum -= srcPixelArray->item(pixelByteOffset - dxLeft * stride);
+                    if (x + dxRight >= effectWidth)
+                        sum += edgeValueRight;
+                    else
+                        sum += srcPixelArray->item(pixelByteOffset + dxRight * stride);
+                }
             }
             if (alphaImage) // Source image is black, it just has different alpha values
                 break;
@@ -126,9 +170,9 @@
             if (!isAlphaImage())
                 boxBlurNEON(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height());
             else
-                boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true);
+                boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), true, m_edgeMode);
 #else
-            boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
+            boxBlur(src, dst, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage(), m_edgeMode);
 #endif
             swap(src, dst);
         }
@@ -139,9 +183,9 @@
             if (!isAlphaImage())
                 boxBlurNEON(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width());
             else
-                boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true);
+                boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), true, m_edgeMode);
 #else
-            boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
+            boxBlur(src, dst, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage(), m_edgeMode);
 #endif
             swap(src, dst);
         }
@@ -264,6 +308,11 @@
     calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);
 
     FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
+    // Edge modes other than 'none' do not inflate the affected paint rect.
+    if (m_edgeMode != EDGEMODE_NONE) {
+        setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
+        return;
+    }
 
     // We take the half kernel size and multiply it with three, because we run box blur three times.
     absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f);

Modified: trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h (154947 => 154948)


--- trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/platform/graphics/filters/FEGaussianBlur.h	2013-09-02 04:53:46 UTC (rev 154948)
@@ -23,14 +23,15 @@
 #define FEGaussianBlur_h
 
 #if ENABLE(FILTERS)
+#include "FEConvolveMatrix.h"
+#include "Filter.h"
 #include "FilterEffect.h"
-#include "Filter.h"
 
 namespace WebCore {
 
 class FEGaussianBlur : public FilterEffect {
 public:
-    static PassRefPtr<FEGaussianBlur> create(Filter*, float, float);
+    static PassRefPtr<FEGaussianBlur> create(Filter*, float, float, EdgeModeType);
 
     float stdDeviationX() const;
     void setStdDeviationX(float);
@@ -38,6 +39,9 @@
     float stdDeviationY() const;
     void setStdDeviationY(float);
 
+    EdgeModeType edgeMode() const;
+    void setEdgeMode(EdgeModeType);
+
     static float calculateStdDeviation(float);
 
     virtual void platformApplySoftware();
@@ -67,7 +71,7 @@
 
     static void platformApplyWorker(PlatformApplyParameters*);
 
-    FEGaussianBlur(Filter*, float, float);
+    FEGaussianBlur(Filter*, float, float, EdgeModeType);
 
     static inline void kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight);
     inline void platformApply(Uint8ClampedArray* srcPixelArray, Uint8ClampedArray* tmpPixelArray, unsigned kernelSizeX, unsigned kernelSizeY, IntSize& paintSize);
@@ -76,6 +80,7 @@
 
     float m_stdX;
     float m_stdY;
+    EdgeModeType m_edgeMode;
 };
 
 inline void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int& dRight)

Modified: trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp (154947 => 154948)


--- trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp	2013-09-02 04:53:46 UTC (rev 154948)
@@ -326,7 +326,7 @@
         case FilterOperation::BLUR: {
             BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
             float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
-            effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation);
+            effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation, EDGEMODE_NONE);
             break;
         }
         case FilterOperation::DROP_SHADOW: {

Modified: trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.cpp (154947 => 154948)


--- trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.cpp	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.cpp	2013-09-02 04:53:46 UTC (rev 154948)
@@ -36,16 +36,19 @@
 DEFINE_ANIMATED_STRING(SVGFEGaussianBlurElement, SVGNames::inAttr, In1, in1)
 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEGaussianBlurElement, SVGNames::stdDeviationAttr, stdDeviationXIdentifier(), StdDeviationX, stdDeviationX)
 DEFINE_ANIMATED_NUMBER_MULTIPLE_WRAPPERS(SVGFEGaussianBlurElement, SVGNames::stdDeviationAttr, stdDeviationYIdentifier(), StdDeviationY, stdDeviationY)
+DEFINE_ANIMATED_ENUMERATION(SVGFEGaussianBlurElement, SVGNames::edgeModeAttr, EdgeMode, edgeMode, EdgeModeType)
 
 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGFEGaussianBlurElement)
     REGISTER_LOCAL_ANIMATED_PROPERTY(in1)
     REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationX)
     REGISTER_LOCAL_ANIMATED_PROPERTY(stdDeviationY)
+    REGISTER_LOCAL_ANIMATED_PROPERTY(edgeMode)
     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGFilterPrimitiveStandardAttributes)
 END_REGISTER_ANIMATED_PROPERTIES
 
 inline SVGFEGaussianBlurElement::SVGFEGaussianBlurElement(const QualifiedName& tagName, Document* document)
     : SVGFilterPrimitiveStandardAttributes(tagName, document)
+    , m_edgeMode(EDGEMODE_NONE)
 {
     ASSERT(hasTagName(SVGNames::feGaussianBlurTag));
     registerAnimatedPropertiesForSVGFEGaussianBlurElement();
@@ -81,6 +84,7 @@
     if (supportedAttributes.isEmpty()) {
         supportedAttributes.add(SVGNames::inAttr);
         supportedAttributes.add(SVGNames::stdDeviationAttr);
+        supportedAttributes.add(SVGNames::edgeModeAttr);
     }
     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
 }
@@ -106,6 +110,17 @@
         return;
     }
 
+    if (name == SVGNames::edgeModeAttr) {
+        EdgeModeType propertyValue = SVGPropertyTraits<EdgeModeType>::fromString(value);
+        if (propertyValue > 0)
+            setEdgeModeBaseValue(propertyValue);
+        else
+            document().accessSVGExtensions()->reportWarning(
+                "feGaussianBlur: problem parsing edgeMode=\"" + value
+                + "\". Filtered element will not be displayed.");
+        return;
+    }
+
     ASSERT_NOT_REACHED();
 }
 
@@ -118,7 +133,9 @@
 
     SVGElementInstance::InvalidationGuard invalidationGuard(this);
     
-    if (attrName == SVGNames::inAttr || attrName == SVGNames::stdDeviationAttr) {
+    if (attrName == SVGNames::inAttr
+        || attrName == SVGNames::stdDeviationAttr
+        || attrName == SVGNames::edgeModeAttr) {
         invalidate();
         return;
     }
@@ -136,7 +153,7 @@
     if (stdDeviationX() < 0 || stdDeviationY() < 0)
         return 0;
 
-    RefPtr<FilterEffect> effect = FEGaussianBlur::create(filter, stdDeviationX(), stdDeviationY());
+    RefPtr<FilterEffect> effect = FEGaussianBlur::create(filter, stdDeviationX(), stdDeviationY(), edgeMode());
     effect->inputEffects().append(input1);
     return effect.release();
 }

Modified: trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.h (154947 => 154948)


--- trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.h	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.h	2013-09-02 04:53:46 UTC (rev 154948)
@@ -23,7 +23,9 @@
 
 #if ENABLE(SVG) && ENABLE(FILTERS)
 #include "FEGaussianBlur.h"
+#include "SVGAnimatedEnumeration.h"
 #include "SVGAnimatedNumber.h"
+#include "SVGFEConvolveMatrixElement.h"
 #include "SVGFilterPrimitiveStandardAttributes.h"
 
 namespace WebCore {
@@ -49,6 +51,7 @@
         DECLARE_ANIMATED_STRING(In1, in1)
         DECLARE_ANIMATED_NUMBER(StdDeviationX, stdDeviationX)
         DECLARE_ANIMATED_NUMBER(StdDeviationY, stdDeviationY)
+        DECLARE_ANIMATED_ENUMERATION(EdgeMode, edgeMode, EdgeModeType)
     END_DECLARE_ANIMATED_PROPERTIES
 };
 

Modified: trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.idl (154947 => 154948)


--- trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.idl	2013-09-01 20:04:02 UTC (rev 154947)
+++ trunk/Source/WebCore/svg/SVGFEGaussianBlurElement.idl	2013-09-02 04:53:46 UTC (rev 154948)
@@ -24,11 +24,19 @@
  */
 
 [
-    Conditional=SVG&FILTERS
+    Conditional=SVG&FILTERS,
+    DoNotCheckConstants
 ] interface SVGFEGaussianBlurElement : SVGElement {
+    // Edge Mode Values
+    const unsigned short SVG_EDGEMODE_UNKNOWN   = 0;
+    const unsigned short SVG_EDGEMODE_DUPLICATE = 1;
+    const unsigned short SVG_EDGEMODE_WRAP      = 2;
+    const unsigned short SVG_EDGEMODE_NONE      = 3;
+
     readonly attribute SVGAnimatedString in1;
     readonly attribute SVGAnimatedNumber stdDeviationX;
     readonly attribute SVGAnimatedNumber stdDeviationY;
+    readonly attribute SVGAnimatedEnumeration edgeMode;
 
     void setStdDeviation([Default=Undefined] optional float stdDeviationX, 
                          [Default=Undefined] optional float stdDeviationY);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to