[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

krit at webkit.org krit at webkit.org
Wed Dec 22 14:16:58 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit af1738d4d342bf4ea258ed4c416ea7ad08860dbc
Author: krit at webkit.org <krit at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Oct 6 09:45:18 2010 +0000

    2010-10-06  Dirk Schulze  <krit at webkit.org>
    
            Reviewed by Nikolas Zimmermann.
    
            SVGs with filters look grainy when scaled
            https://bugs.webkit.org/show_bug.cgi?id=5526
    
            SVG filter effects need smarter size calculation
            https://bugs.webkit.org/show_bug.cgi?id=31370
    
            SVG elements use Filters before own transformations
            https://bugs.webkit.org/show_bug.cgi?id=32486
    
            Calculate all filter results in device space instead of the filtered objects user space. This change is similar to
            the patches for SVG Pattern and SVG Masker before. It avoids pixelation and guarantees smooth filter results for
            every scale level and is independent of any transformation to the target element or any ancester of the target.
            The second part of this patch reduces the size of every effect to the smallest affected region instead of the complete
            filter primitive subregion (http://www.w3.org/TR/SVG/filters.html#FilterPrimitiveSubRegion). We just use the subregion
            as clipping region, like mentioned in the SVG specification, to make the affected region even smaller now.
    
            This is a huge speed up. The ECMA cloud (http://ejohn.org/files/ecma-cloud.svg) is more than 100 times faster on Gtk and
            renders in less than a second.
            Some examples on svg-wow.org can be viewed the first time now, since the subregions were much bigger than the affected
            region.
            There's still more potential to speed up filters, by further reducing the ImageBuffer sizes.
            Renamed repaintRectInLocalCoordinates to absolutePaintRect, since all coordinates are in device space instead of the
            user space now.
            The absolute paint rect is calculated by determineAbsolutePaintRect() and gets called by FilterEffect::effectContext() on
            applying the effect.
            Partly rewrote filter resolution (http://www.w3.org/TR/SVG/filters.html#FilterElementFilterResAttribute) to work with the
            new concept. This also corrects the old behavior to match the SVG specification.
    
            Tests: svg/filters/filterRes1.svg
                   svg/filters/filterRes2.svg
                   svg/filters/filterRes3.svg
    
            * platform/graphics/cairo/GraphicsContextCairo.cpp: Call setAbsolutePaintRect instead of setRepaintRectInLocalCoordinates.
            (WebCore::GraphicsContext::createShadowMask):
            * platform/graphics/filters/FEBlend.cpp: Renamed repaintRectInLocalCoordinates to absolutePaintRect.
            (WebCore::FEBlend::apply):
            * platform/graphics/filters/FEColorMatrix.cpp: Ditto.
            (WebCore::FEColorMatrix::apply):
            * platform/graphics/filters/FEComponentTransfer.cpp: Ditto.
            (WebCore::FEComponentTransfer::apply):
            * platform/graphics/filters/FEComposite.cpp: Ditto.
            (WebCore::FEComposite::determineAbsolutePaintRect):
            (WebCore::FEComposite::apply):
            * platform/graphics/filters/FEComposite.h:
            * platform/graphics/filters/FEConvolveMatrix.cpp: Ditto.
            (WebCore::FEConvolveMatrix::apply):
            * platform/graphics/filters/FEConvolveMatrix.h:
            (WebCore::FEConvolveMatrix::determineAbsolutePaintRect):
            * platform/graphics/filters/FEDisplacementMap.cpp: Ditto.
            (WebCore::FEDisplacementMap::apply):
            * platform/graphics/filters/FEDisplacementMap.h:
            (WebCore::FEDisplacementMap::determineAbsolutePaintRect):
            * platform/graphics/filters/FEFlood.cpp: Ditto.
            (WebCore::FEFlood::apply):
            * platform/graphics/filters/FEFlood.h:
            (WebCore::FEFlood::determineAbsolutePaintRect):
            * platform/graphics/filters/FEGaussianBlur.cpp: Ditto.
            (WebCore::calculateKernelSize):
            (WebCore::FEGaussianBlur::determineAbsolutePaintRect):
            (WebCore::FEGaussianBlur::apply):
            * platform/graphics/filters/FEGaussianBlur.h:
            * platform/graphics/filters/FELighting.cpp: Ditto.
            (WebCore::FELighting::apply):
            * platform/graphics/filters/FEMerge.cpp: Ditto.
            (WebCore::FEMerge::apply):
            * platform/graphics/filters/FEMorphology.cpp: Ditto.
            (WebCore::FEMorphology::determineAbsolutePaintRect):
            (WebCore::FEMorphology::apply):
            * platform/graphics/filters/FEMorphology.h:
            * platform/graphics/filters/FEOffset.cpp: Ditto.
            (WebCore::FEOffset::determineAbsolutePaintRect):
            (WebCore::FEOffset::apply):
            * platform/graphics/filters/FEOffset.h:
            * platform/graphics/filters/FETile.cpp: Ditto.
            (WebCore::FETile::determineFilterPrimitiveSubregion):
            (WebCore::FETile::apply):
            * platform/graphics/filters/FETile.h:
            (WebCore::FETile::determineAbsolutePaintRect):
            * platform/graphics/filters/FETurbulence.cpp: Ditto.
            (WebCore::FETurbulence::apply):
            * platform/graphics/filters/FETurbulence.h:
            (WebCore::FETurbulence::determineAbsolutePaintRect):
            * platform/graphics/filters/Filter.h:
            (WebCore::Filter::applyHorizontalScale): Map horizontal effect values to absolute coordinates.
            (WebCore::Filter::applyVerticalScale): Map vertical effect values to absolute coordinates.
            (WebCore::Filter::mapAbsolutePointToLocalPoint):
            (WebCore::Filter::filterRegionInUserSpace):
            * platform/graphics/filters/FilterEffect.cpp: Ditto.
            (WebCore::FilterEffect::determineFilterPrimitiveSubregion):
            (WebCore::FilterEffect::determineAbsolutePaintRect):
            (WebCore::FilterEffect::requestedRegionOfInputImageData):
            (WebCore::FilterEffect::drawingRegionOfInputImage):
            (WebCore::FilterEffect::effectContext):
            * platform/graphics/filters/FilterEffect.h:
            (WebCore::FilterEffect::absolutePaintRect):
            (WebCore::FilterEffect::setAbsolutePaintRect):
            (WebCore::FilterEffect::maxEffectRect): The subregion in absolute coordinates for SVG.
            (WebCore::FilterEffect::setMaxEffectRect):
            * platform/graphics/filters/SourceAlpha.cpp: Ditto.
            (WebCore::SourceAlpha::determineAbsolutePaintRect):
            (WebCore::SourceAlpha::apply):
            * platform/graphics/filters/SourceAlpha.h:
            * platform/graphics/filters/SourceGraphic.cpp: Ditto.
            (WebCore::SourceGraphic::determineAbsolutePaintRect):
            (WebCore::SourceGraphic::apply):
            * platform/graphics/filters/SourceGraphic.h:
            * rendering/RenderSVGResourceFilter.cpp:
            (WebCore::RenderSVGResourceFilter::applyResource):
            (WebCore::RenderSVGResourceFilter::postApplyResource):
            * rendering/RenderSVGResourceFilter.h:
            (WebCore::FilterData::FilterData):
            * svg/graphics/filters/SVGFEImage.cpp: Ditto.
            (WebCore::FEImage::apply):
            * svg/graphics/filters/SVGFEImage.h:
            (WebCore::FEImage::determineAbsolutePaintRect):
            * svg/graphics/filters/SVGFilter.cpp:
            (WebCore::SVGFilter::SVGFilter):
            (WebCore::SVGFilter::determineFilterPrimitiveSubregion):
            (WebCore::SVGFilter::applyHorizontalScale):
            (WebCore::SVGFilter::applyVerticalScale):
            (WebCore::SVGFilter::create):
            * svg/graphics/filters/SVGFilter.h:
            (WebCore::SVGFilter::effectBoundingBoxMode):
            (WebCore::SVGFilter::filterRegionInUserSpace):
            (WebCore::SVGFilter::filterRegion):
            (WebCore::SVGFilter::mapAbsolutePointToLocalPoint): Map absolute point to local point in userspace.
            (WebCore::SVGFilter::sourceImageRect):
            (WebCore::SVGFilter::maxImageSize):
    2010-10-06  Dirk Schulze  <krit at webkit.org>
    
            Reviewed by Nikolas Zimmermann.
    
            SVGs with filters look grainy when scaled
            https://bugs.webkit.org/show_bug.cgi?id=5526
    
            Added three new tests for SVGs filterRes.
            Shadow tests for SVG Filter needed an update. Current tests didn't respect
            primitiveUnits "objectBoundingBox" for stdDeviation on feGaussianBlur correctly.
    
            * platform/mac/svg/filters/filterRes1-expected.checksum: Added.
            * platform/mac/svg/filters/filterRes1-expected.png: Added.
            * platform/mac/svg/filters/filterRes1-expected.txt: Added.
            * platform/mac/svg/filters/filterRes2-expected.checksum: Added.
            * platform/mac/svg/filters/filterRes2-expected.png: Added.
            * platform/mac/svg/filters/filterRes2-expected.txt: Added.
            * platform/mac/svg/filters/filterRes3-expected.checksum: Added.
            * platform/mac/svg/filters/filterRes3-expected.png: Added.
            * platform/mac/svg/filters/filterRes3-expected.txt: Added.
            * platform/mac/svg/filters/shadow-on-filter-expected.txt:
            * platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt:
            * svg/filters/filterRes1.svg: Added.
            * svg/filters/filterRes2.svg: Added.
            * svg/filters/filterRes3.svg: Added.
            * svg/filters/shadow-on-filter.svg:
            * svg/filters/shadow-on-rect-with-filter.svg:
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@69181 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 7a6fcbd..1b215ce 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,31 @@
+2010-10-06  Dirk Schulze  <krit at webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVGs with filters look grainy when scaled
+        https://bugs.webkit.org/show_bug.cgi?id=5526
+
+        Added three new tests for SVGs filterRes.
+        Shadow tests for SVG Filter needed an update. Current tests didn't respect
+        primitiveUnits "objectBoundingBox" for stdDeviation on feGaussianBlur correctly.
+
+        * platform/mac/svg/filters/filterRes1-expected.checksum: Added.
+        * platform/mac/svg/filters/filterRes1-expected.png: Added.
+        * platform/mac/svg/filters/filterRes1-expected.txt: Added.
+        * platform/mac/svg/filters/filterRes2-expected.checksum: Added.
+        * platform/mac/svg/filters/filterRes2-expected.png: Added.
+        * platform/mac/svg/filters/filterRes2-expected.txt: Added.
+        * platform/mac/svg/filters/filterRes3-expected.checksum: Added.
+        * platform/mac/svg/filters/filterRes3-expected.png: Added.
+        * platform/mac/svg/filters/filterRes3-expected.txt: Added.
+        * platform/mac/svg/filters/shadow-on-filter-expected.txt:
+        * platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt:
+        * svg/filters/filterRes1.svg: Added.
+        * svg/filters/filterRes2.svg: Added.
+        * svg/filters/filterRes3.svg: Added.
+        * svg/filters/shadow-on-filter.svg:
+        * svg/filters/shadow-on-rect-with-filter.svg:
+
 2010-10-06  Kent Tamura  <tkent at chromium.org>
 
         Unreviewed, test expectation update.
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes1-expected.checksum b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.checksum
new file mode 100644
index 0000000..e513e05
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.checksum
@@ -0,0 +1 @@
+516097e4549a4f7197ca0fa54100a0ee
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes1-expected.png b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.png
new file mode 100644
index 0000000..53cf051
Binary files /dev/null and b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes1-expected.txt b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.txt
new file mode 100644
index 0000000..f677711
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes1-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderSVGRoot {svg} at (10,10) size 400x120
+    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+      RenderSVGResourceFilter {filter} [id="f1"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+      RenderSVGResourceFilter {filter} [id="f2"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+      RenderSVGResourceFilter {filter} [id="f3"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+    RenderPath {rect} at (10,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M20.00,20.00 L120.00,20.00 L120.00,120.00 L20.00,120.00 Z"]
+      [filter="f1"] RenderSVGResourceFilter {filter} at (10,10) size 120x120
+    RenderPath {rect} at (150,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M160.00,20.00 L260.00,20.00 L260.00,120.00 L160.00,120.00 Z"]
+      [filter="f2"] RenderSVGResourceFilter {filter} at (150,10) size 120x120
+    RenderPath {rect} at (290,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M300.00,20.00 L400.00,20.00 L400.00,120.00 L300.00,120.00 Z"]
+      [filter="f3"] RenderSVGResourceFilter {filter} at (290,10) size 120x120
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes2-expected.checksum b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.checksum
new file mode 100644
index 0000000..129dd60
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.checksum
@@ -0,0 +1 @@
+65bfcfc9dd4b5c7da633e3bb46c116f8
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes2-expected.png b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.png
new file mode 100644
index 0000000..d669e62
Binary files /dev/null and b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes2-expected.txt b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.txt
new file mode 100644
index 0000000..fd531de
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes2-expected.txt
@@ -0,0 +1,20 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderSVGRoot {svg} at (10,10) size 400x120
+    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+      RenderSVGResourceFilter {filter} [id="f1"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feOffset dx="0.00" dy="0.00"]
+          [SourceGraphic]
+      RenderSVGResourceFilter {filter} [id="f2"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feOffset dx="0.00" dy="0.00"]
+          [SourceGraphic]
+      RenderSVGResourceFilter {filter} [id="f3"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feOffset dx="0.00" dy="0.00"]
+          [SourceGraphic]
+    RenderPath {rect} at (10,10) size 120x120 [fill={[type=SOLID] [color=#008000]}] [data="M20.00,20.00 L120.00,20.00 L120.00,120.00 L20.00,120.00 Z"]
+      [filter="f1"] RenderSVGResourceFilter {filter} at (10,10) size 120x120
+    RenderPath {rect} at (150,10) size 120x120 [fill={[type=SOLID] [color=#008000]}] [data="M160.00,20.00 L260.00,20.00 L260.00,120.00 L160.00,120.00 Z"]
+      [filter="f2"] RenderSVGResourceFilter {filter} at (150,10) size 120x120
+    RenderPath {rect} at (290,10) size 120x120 [fill={[type=SOLID] [color=#008000]}] [data="M300.00,20.00 L400.00,20.00 L400.00,120.00 L300.00,120.00 Z"]
+      [filter="f3"] RenderSVGResourceFilter {filter} at (290,10) size 120x120
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes3-expected.checksum b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.checksum
new file mode 100644
index 0000000..e513e05
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.checksum
@@ -0,0 +1 @@
+516097e4549a4f7197ca0fa54100a0ee
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes3-expected.png b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.png
new file mode 100644
index 0000000..53cf051
Binary files /dev/null and b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.png differ
diff --git a/LayoutTests/platform/mac/svg/filters/filterRes3-expected.txt b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.txt
new file mode 100644
index 0000000..f677711
--- /dev/null
+++ b/LayoutTests/platform/mac/svg/filters/filterRes3-expected.txt
@@ -0,0 +1,17 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderSVGRoot {svg} at (10,10) size 400x120
+    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
+      RenderSVGResourceFilter {filter} [id="f1"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+      RenderSVGResourceFilter {filter} [id="f2"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+      RenderSVGResourceFilter {filter} [id="f3"] [filterUnits=objectBoundingBox] [primitiveUnits=userSpaceOnUse]
+        [feFlood flood-color="#008000" flood-opacity="1.00"]
+    RenderPath {rect} at (10,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M20.00,20.00 L120.00,20.00 L120.00,120.00 L20.00,120.00 Z"]
+      [filter="f1"] RenderSVGResourceFilter {filter} at (10,10) size 120x120
+    RenderPath {rect} at (150,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M160.00,20.00 L260.00,20.00 L260.00,120.00 L160.00,120.00 Z"]
+      [filter="f2"] RenderSVGResourceFilter {filter} at (150,10) size 120x120
+    RenderPath {rect} at (290,10) size 120x120 [fill={[type=SOLID] [color=#000000]}] [data="M300.00,20.00 L400.00,20.00 L400.00,120.00 L300.00,120.00 Z"]
+      [filter="f3"] RenderSVGResourceFilter {filter} at (290,10) size 120x120
diff --git a/LayoutTests/platform/mac/svg/filters/shadow-on-filter-expected.txt b/LayoutTests/platform/mac/svg/filters/shadow-on-filter-expected.txt
index 9bccb77..e4986ff 100644
--- a/LayoutTests/platform/mac/svg/filters/shadow-on-filter-expected.txt
+++ b/LayoutTests/platform/mac/svg/filters/shadow-on-filter-expected.txt
@@ -4,7 +4,7 @@ layer at (0,0) size 800x600
   RenderSVGRoot {svg} at (50,50) size 480x480
     RenderSVGHiddenContainer {defs} at (0,0) size 0x0
       RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=objectBoundingBox]
-        [feGaussianBlur stdDeviation="4.00, 4.00"]
+        [feGaussianBlur stdDeviation="0.01, 0.01"]
           [feComposite operation="OVER"]
             [feFlood flood-color="#FF0000" flood-opacity="1.00"]
             [feFlood flood-color="#008000" flood-opacity="1.00"]
diff --git a/LayoutTests/platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt b/LayoutTests/platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt
index 39221ef..a389f5d 100644
--- a/LayoutTests/platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt
+++ b/LayoutTests/platform/mac/svg/filters/shadow-on-rect-with-filter-expected.txt
@@ -4,7 +4,7 @@ layer at (0,0) size 800x600
   RenderSVGRoot {svg} at (37,37) size 493x493
     RenderSVGHiddenContainer {defs} at (0,0) size 0x0
       RenderSVGResourceFilter {filter} [id="filter"] [filterUnits=objectBoundingBox] [primitiveUnits=objectBoundingBox]
-        [feGaussianBlur stdDeviation="4.00, 4.00"]
+        [feGaussianBlur stdDeviation="0.01, 0.01"]
           [feComposite operation="OVER"]
             [feFlood flood-color="#FF0000" flood-opacity="1.00"]
             [feFlood flood-color="#008000" flood-opacity="1.00"]
diff --git a/LayoutTests/svg/filters/filterRes1.svg b/LayoutTests/svg/filters/filterRes1.svg
new file mode 100644
index 0000000..7ef81b5
--- /dev/null
+++ b/LayoutTests/svg/filters/filterRes1.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<filter id="f1" filterRes="60">
+    <feFlood flood-color="green"/>
+</filter>
+<filter id="f2" filterRes="120">
+    <feFlood flood-color="green"/>
+</filter>
+<filter id="f3">
+    <feFlood flood-color="green"/>
+</filter>
+</defs>
+<rect x="20" y="20" width="100" height="100" filter="url(#f1)"/>
+<rect x="160" y="20" width="100" height="100" filter="url(#f2)"/>
+<rect x="300" y="20" width="100" height="100" filter="url(#f3)"/>
+</svg>
+
diff --git a/LayoutTests/svg/filters/filterRes2.svg b/LayoutTests/svg/filters/filterRes2.svg
new file mode 100644
index 0000000..cd72507
--- /dev/null
+++ b/LayoutTests/svg/filters/filterRes2.svg
@@ -0,0 +1,17 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<filter id="f1" filterRes="60">
+    <feOffset/>
+</filter>
+<filter id="f2" filterRes="120">
+    <feOffset/>
+</filter>
+<filter id="f3">
+    <feOffset/>
+</filter>
+</defs>
+<rect x="20" y="20" width="100" height="100" fill="green" filter="url(#f1)"/>
+<rect x="160" y="20" width="100" height="100" fill="green" filter="url(#f2)"/>
+<rect x="300" y="20" width="100" height="100" fill="green" filter="url(#f3)"/>
+</svg>
+
diff --git a/LayoutTests/svg/filters/filterRes3.svg b/LayoutTests/svg/filters/filterRes3.svg
new file mode 100644
index 0000000..9e2769e
--- /dev/null
+++ b/LayoutTests/svg/filters/filterRes3.svg
@@ -0,0 +1,20 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+<filter id="f1" filterRes="60">
+    <feFlood flood-color="green"/>
+    <feOfffset/>
+</filter>
+<filter id="f2" filterRes="120">
+    <feFlood flood-color="green"/>
+    <feOfffset/>
+</filter>
+<filter id="f3">
+    <feFlood flood-color="green"/>
+    <feOfffset/>
+</filter>
+</defs>
+<rect x="20" y="20" width="100" height="100" filter="url(#f1)"/>
+<rect x="160" y="20" width="100" height="100" filter="url(#f2)"/>
+<rect x="300" y="20" width="100" height="100" filter="url(#f3)"/>
+</svg>
+
diff --git a/LayoutTests/svg/filters/shadow-on-filter.svg b/LayoutTests/svg/filters/shadow-on-filter.svg
index c0ba24a..ae82fdd 100644
--- a/LayoutTests/svg/filters/shadow-on-filter.svg
+++ b/LayoutTests/svg/filters/shadow-on-filter.svg
@@ -4,7 +4,7 @@
 <feFlood x="-40%" y="-40%" width="50%" height="50%" flood-color="red" style="-webkit-svg-shadow:-4px -4px 0px blue;" result="flood1"/>
 <feFlood x="-20%" y="-20%" width="50%" height="50%" flood-color="green" result="flood2"/>
 <feComposite in="flood1" in2="flood2" width="120%" height="120%" result="comp1" style="-webkit-svg-shadow:4px -1px 3px green;"/>
-<feGaussianBlur stdDeviation="4 4" style="-webkit-svg-shadow: 6px 4px 8px yellow;"/>
+<feGaussianBlur stdDeviation="0.0133" style="-webkit-svg-shadow: 6px 4px 8px yellow;"/>
 </filter>
 </defs>
 <rect x="200" y="200" width="300" height="300" fill="green" style="filter:url(#filter);"/>
diff --git a/LayoutTests/svg/filters/shadow-on-rect-with-filter.svg b/LayoutTests/svg/filters/shadow-on-rect-with-filter.svg
index 5e49af8..a497cdc 100644
--- a/LayoutTests/svg/filters/shadow-on-rect-with-filter.svg
+++ b/LayoutTests/svg/filters/shadow-on-rect-with-filter.svg
@@ -4,7 +4,7 @@
 <feFlood x="-40%" y="-40%" width="50%" height="50%" flood-color="red" result="flood1"/>
 <feFlood x="-20%" y="-20%" width="50%" height="50%" flood-color="green" result="flood2"/>
 <feComposite in="flood1" in2="flood2" width="120%" height="120%" result="comp1" />
-<feGaussianBlur stdDeviation="4 4" />
+<feGaussianBlur stdDeviation="0.0133" />
 </filter>
 </defs>
 <rect x="200" y="200" width="300" height="300" fill="green" style="filter:url(#filter);-webkit-svg-shadow:-10px -10px 3px orange;"/>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index bbef68f..6377ca9 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,136 @@
+2010-10-06  Dirk Schulze  <krit at webkit.org>
+
+        Reviewed by Nikolas Zimmermann.
+
+        SVGs with filters look grainy when scaled
+        https://bugs.webkit.org/show_bug.cgi?id=5526
+
+        SVG filter effects need smarter size calculation
+        https://bugs.webkit.org/show_bug.cgi?id=31370
+
+        SVG elements use Filters before own transformations
+        https://bugs.webkit.org/show_bug.cgi?id=32486
+
+        Calculate all filter results in device space instead of the filtered objects user space. This change is similar to
+        the patches for SVG Pattern and SVG Masker before. It avoids pixelation and guarantees smooth filter results for
+        every scale level and is independent of any transformation to the target element or any ancester of the target.
+        The second part of this patch reduces the size of every effect to the smallest affected region instead of the complete
+        filter primitive subregion (http://www.w3.org/TR/SVG/filters.html#FilterPrimitiveSubRegion). We just use the subregion
+        as clipping region, like mentioned in the SVG specification, to make the affected region even smaller now.
+
+        This is a huge speed up. The ECMA cloud (http://ejohn.org/files/ecma-cloud.svg) is more than 100 times faster on Gtk and
+        renders in less than a second.
+        Some examples on svg-wow.org can be viewed the first time now, since the subregions were much bigger than the affected
+        region.
+        There's still more potential to speed up filters, by further reducing the ImageBuffer sizes.
+        Renamed repaintRectInLocalCoordinates to absolutePaintRect, since all coordinates are in device space instead of the
+        user space now.
+        The absolute paint rect is calculated by determineAbsolutePaintRect() and gets called by FilterEffect::effectContext() on
+        applying the effect.
+        Partly rewrote filter resolution (http://www.w3.org/TR/SVG/filters.html#FilterElementFilterResAttribute) to work with the
+        new concept. This also corrects the old behavior to match the SVG specification.
+
+        Tests: svg/filters/filterRes1.svg
+               svg/filters/filterRes2.svg
+               svg/filters/filterRes3.svg
+
+        * platform/graphics/cairo/GraphicsContextCairo.cpp: Call setAbsolutePaintRect instead of setRepaintRectInLocalCoordinates.
+        (WebCore::GraphicsContext::createShadowMask):
+        * platform/graphics/filters/FEBlend.cpp: Renamed repaintRectInLocalCoordinates to absolutePaintRect.
+        (WebCore::FEBlend::apply):
+        * platform/graphics/filters/FEColorMatrix.cpp: Ditto.
+        (WebCore::FEColorMatrix::apply):
+        * platform/graphics/filters/FEComponentTransfer.cpp: Ditto.
+        (WebCore::FEComponentTransfer::apply):
+        * platform/graphics/filters/FEComposite.cpp: Ditto.
+        (WebCore::FEComposite::determineAbsolutePaintRect):
+        (WebCore::FEComposite::apply):
+        * platform/graphics/filters/FEComposite.h:
+        * platform/graphics/filters/FEConvolveMatrix.cpp: Ditto.
+        (WebCore::FEConvolveMatrix::apply):
+        * platform/graphics/filters/FEConvolveMatrix.h:
+        (WebCore::FEConvolveMatrix::determineAbsolutePaintRect):
+        * platform/graphics/filters/FEDisplacementMap.cpp: Ditto.
+        (WebCore::FEDisplacementMap::apply):
+        * platform/graphics/filters/FEDisplacementMap.h:
+        (WebCore::FEDisplacementMap::determineAbsolutePaintRect):
+        * platform/graphics/filters/FEFlood.cpp: Ditto.
+        (WebCore::FEFlood::apply):
+        * platform/graphics/filters/FEFlood.h:
+        (WebCore::FEFlood::determineAbsolutePaintRect):
+        * platform/graphics/filters/FEGaussianBlur.cpp: Ditto.
+        (WebCore::calculateKernelSize):
+        (WebCore::FEGaussianBlur::determineAbsolutePaintRect):
+        (WebCore::FEGaussianBlur::apply):
+        * platform/graphics/filters/FEGaussianBlur.h:
+        * platform/graphics/filters/FELighting.cpp: Ditto.
+        (WebCore::FELighting::apply):
+        * platform/graphics/filters/FEMerge.cpp: Ditto.
+        (WebCore::FEMerge::apply):
+        * platform/graphics/filters/FEMorphology.cpp: Ditto.
+        (WebCore::FEMorphology::determineAbsolutePaintRect):
+        (WebCore::FEMorphology::apply):
+        * platform/graphics/filters/FEMorphology.h:
+        * platform/graphics/filters/FEOffset.cpp: Ditto.
+        (WebCore::FEOffset::determineAbsolutePaintRect):
+        (WebCore::FEOffset::apply):
+        * platform/graphics/filters/FEOffset.h:
+        * platform/graphics/filters/FETile.cpp: Ditto.
+        (WebCore::FETile::determineFilterPrimitiveSubregion):
+        (WebCore::FETile::apply):
+        * platform/graphics/filters/FETile.h:
+        (WebCore::FETile::determineAbsolutePaintRect):
+        * platform/graphics/filters/FETurbulence.cpp: Ditto.
+        (WebCore::FETurbulence::apply):
+        * platform/graphics/filters/FETurbulence.h:
+        (WebCore::FETurbulence::determineAbsolutePaintRect):
+        * platform/graphics/filters/Filter.h:
+        (WebCore::Filter::applyHorizontalScale): Map horizontal effect values to absolute coordinates.
+        (WebCore::Filter::applyVerticalScale): Map vertical effect values to absolute coordinates.
+        (WebCore::Filter::mapAbsolutePointToLocalPoint):
+        (WebCore::Filter::filterRegionInUserSpace):
+        * platform/graphics/filters/FilterEffect.cpp: Ditto.
+        (WebCore::FilterEffect::determineFilterPrimitiveSubregion):
+        (WebCore::FilterEffect::determineAbsolutePaintRect):
+        (WebCore::FilterEffect::requestedRegionOfInputImageData):
+        (WebCore::FilterEffect::drawingRegionOfInputImage):
+        (WebCore::FilterEffect::effectContext):
+        * platform/graphics/filters/FilterEffect.h:
+        (WebCore::FilterEffect::absolutePaintRect):
+        (WebCore::FilterEffect::setAbsolutePaintRect):
+        (WebCore::FilterEffect::maxEffectRect): The subregion in absolute coordinates for SVG.
+        (WebCore::FilterEffect::setMaxEffectRect):
+        * platform/graphics/filters/SourceAlpha.cpp: Ditto.
+        (WebCore::SourceAlpha::determineAbsolutePaintRect):
+        (WebCore::SourceAlpha::apply):
+        * platform/graphics/filters/SourceAlpha.h:
+        * platform/graphics/filters/SourceGraphic.cpp: Ditto.
+        (WebCore::SourceGraphic::determineAbsolutePaintRect):
+        (WebCore::SourceGraphic::apply):
+        * platform/graphics/filters/SourceGraphic.h:
+        * rendering/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::applyResource):
+        (WebCore::RenderSVGResourceFilter::postApplyResource):
+        * rendering/RenderSVGResourceFilter.h:
+        (WebCore::FilterData::FilterData):
+        * svg/graphics/filters/SVGFEImage.cpp: Ditto.
+        (WebCore::FEImage::apply):
+        * svg/graphics/filters/SVGFEImage.h:
+        (WebCore::FEImage::determineAbsolutePaintRect):
+        * svg/graphics/filters/SVGFilter.cpp:
+        (WebCore::SVGFilter::SVGFilter):
+        (WebCore::SVGFilter::determineFilterPrimitiveSubregion):
+        (WebCore::SVGFilter::applyHorizontalScale):
+        (WebCore::SVGFilter::applyVerticalScale):
+        (WebCore::SVGFilter::create):
+        * svg/graphics/filters/SVGFilter.h:
+        (WebCore::SVGFilter::effectBoundingBoxMode):
+        (WebCore::SVGFilter::filterRegionInUserSpace):
+        (WebCore::SVGFilter::filterRegion):
+        (WebCore::SVGFilter::mapAbsolutePointToLocalPoint): Map absolute point to local point in userspace.
+        (WebCore::SVGFilter::sourceImageRect):
+        (WebCore::SVGFilter::maxImageSize):
+
 2010-10-06  Pavel Podivilov  <podivilov at chromium.org>
 
         Reviewed by Yury Semikhatsky.
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index ed3b30a..7721ccc 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -944,12 +944,12 @@ PlatformRefPtr<cairo_surface_t> GraphicsContext::createShadowMask(PassOwnPtr<Ima
     RefPtr<Filter> filter = ImageBufferFilter::create();
     filter->setSourceImage(buffer);
     RefPtr<FilterEffect> source = SourceGraphic::create();
-    source->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size()));
+    source->setAbsolutePaintRect(IntRect(IntPoint(), roundedIntSize(shadowRect.size())));
     source->setIsAlphaImage(true);
     RefPtr<FilterEffect> blur = FEGaussianBlur::create(stdDeviation, stdDeviation);
     FilterEffectVector& inputEffects = blur->inputEffects();
     inputEffects.append(source.get());
-    blur->setRepaintRectInLocalCoordinates(FloatRect(FloatPoint(), shadowRect.size()));
+    blur->setAbsolutePaintRect(IntRect(IntPoint(), roundedIntSize(shadowRect.size())));
     blur->apply(filter.get());
     return blur->resultImage()->m_data.m_surface;
 #endif
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 4185f61..1a40027 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -98,13 +98,13 @@ void FEBlend::apply(Filter* filter)
     if (m_mode == FEBLEND_MODE_UNKNOWN)
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
-    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
 
-    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
     RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
 
     IntRect imageRect(IntPoint(), resultImage()->size());
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index 86c37c2..06e2c49 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -160,11 +160,11 @@ void FEColorMatrix::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
-    filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+    filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()));
 
     IntRect imageRect(IntPoint(), resultImage()->size());
     PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index 6fe38e4..08d0b1f 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -154,7 +154,7 @@ void FEComponentTransfer::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
@@ -167,7 +167,7 @@ void FEComponentTransfer::apply(Filter* filter)
     for (unsigned channel = 0; channel < 4; channel++)
         (*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
 
-    IntRect drawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<ImageData> imageData(in->resultImage()->getUnmultipliedImageData(drawingRect));
     CanvasPixelArray* srcPixelArray(imageData->data());
 
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 94e2524..70a212e 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2004, 2005 Rob Buis <buis at kde.org>
  * Copyright (C) 2005 Eric Seidel <eric at webkit.org>
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -112,6 +113,27 @@ inline void arithmetic(const RefPtr<CanvasPixelArray>& srcPixelArrayA, CanvasPix
         }
     }
 }
+    
+void FEComposite::determineAbsolutePaintRect(Filter* filter)
+{
+    switch (m_type) {
+    case FECOMPOSITE_OPERATOR_IN:
+    case FECOMPOSITE_OPERATOR_ATOP:
+        // For In and Atop the first effect just influences the result of
+        // the second effect. So just use the absolute paint rect of the second effect here.
+        setAbsolutePaintRect(inputEffect(1)->absolutePaintRect());
+        return;
+    case FECOMPOSITE_OPERATOR_ARITHMETIC:
+        // Arithmetic may influnce the compele filter primitive region. So we can't
+        // optimize the paint region here.
+        setAbsolutePaintRect(maxEffectRect());
+        return;
+    default:
+        // Take the union of both input effects.
+        FilterEffect::determineAbsolutePaintRect(filter);
+        return;
+    }
+}
 
 void FEComposite::apply(Filter* filter)
 {
@@ -122,39 +144,39 @@ void FEComposite::apply(Filter* filter)
     if (!in->resultImage() || !in2->resultImage())
         return;
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     FloatRect srcRect = FloatRect(0, 0, -1, -1);
     switch (m_type) {
     case FECOMPOSITE_OPERATOR_OVER:
-        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->absolutePaintRect()));
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()));
         break;
     case FECOMPOSITE_OPERATOR_IN:
         filterContext->save();
-        filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+        filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->absolutePaintRect()));
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()));
         filterContext->restore();
         break;
     case FECOMPOSITE_OPERATOR_OUT:
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
-        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()), srcRect, CompositeDestinationOut);
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()));
+        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
         break;
     case FECOMPOSITE_OPERATOR_ATOP:
-        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeSourceAtop);
+        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->absolutePaintRect()));
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
         break;
     case FECOMPOSITE_OPERATOR_XOR:
-        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->repaintRectInLocalCoordinates()));
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()), srcRect, CompositeXOR);
+        filterContext->drawImageBuffer(in2->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in2->absolutePaintRect()));
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
         break;
     case FECOMPOSITE_OPERATOR_ARITHMETIC: {
-        IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+        IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
         RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
 
-        IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+        IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
         RefPtr<ImageData> imageData(in2->resultImage()->getPremultipliedImageData(effectBDrawingRect));
         CanvasPixelArray* srcPixelArrayB(imageData->data());
 
diff --git a/WebCore/platform/graphics/filters/FEComposite.h b/WebCore/platform/graphics/filters/FEComposite.h
index 82a3b06..ecdb037 100644
--- a/WebCore/platform/graphics/filters/FEComposite.h
+++ b/WebCore/platform/graphics/filters/FEComposite.h
@@ -61,6 +61,8 @@ public:
 
     virtual void apply(Filter*);
     virtual void dump();
+    
+    virtual void determineAbsolutePaintRect(Filter*);
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
index dd66c6a..d487a47 100644
--- a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -377,11 +377,11 @@ void FEConvolveMatrix::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     IntRect imageRect(IntPoint(), resultImage()->size());
-    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->filterPrimitiveSubregion());
+    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
 
     RefPtr<CanvasPixelArray> srcPixelArray;
     if (m_preserveAlpha)
diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.h b/WebCore/platform/graphics/filters/FEConvolveMatrix.h
index 2fe634f..8d3439e 100644
--- a/WebCore/platform/graphics/filters/FEConvolveMatrix.h
+++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.h
@@ -75,6 +75,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
 private:
diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
index 6b5dbaa..0c53241 100644
--- a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2004, 2005 Rob Buis <buis at kde.org>
  * Copyright (C) 2005 Eric Seidel <eric at webkit.org>
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -88,13 +89,13 @@ void FEDisplacementMap::apply(Filter* filter)
     if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN)
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
-    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<CanvasPixelArray> srcPixelArrayA(in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
 
-    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->repaintRectInLocalCoordinates());
+    IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
     RefPtr<CanvasPixelArray> srcPixelArrayB(in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect)->data());
 
     IntRect imageRect(IntPoint(), resultImage()->size());
@@ -102,10 +103,10 @@ void FEDisplacementMap::apply(Filter* filter)
 
     ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
 
-    float scaleX = m_scale / 255.f * filter->filterResolution().width();
-    float scaleY = m_scale / 255.f * filter->filterResolution().height();
-    float scaleAdjustmentX = (0.5f - 0.5f * m_scale) * filter->filterResolution().width();
-    float scaleAdjustmentY = (0.5f - 0.5f * m_scale) * filter->filterResolution().height();
+    float scaleX = filter->applyHorizontalScale(m_scale / 255);
+    float scaleY = filter->applyVerticalScale(m_scale / 255);
+    float scaleAdjustmentX = filter->applyHorizontalScale(0.5f - 0.5f * m_scale);
+    float scaleAdjustmentY = filter->applyVerticalScale(0.5f - 0.5f * m_scale);
     int stride = imageRect.width() * 4;
     for (int y = 0; y < imageRect.height(); ++y) {
         int line = y * stride;
diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.h b/WebCore/platform/graphics/filters/FEDisplacementMap.h
index dc87b90..c5b97a7 100644
--- a/WebCore/platform/graphics/filters/FEDisplacementMap.h
+++ b/WebCore/platform/graphics/filters/FEDisplacementMap.h
@@ -53,6 +53,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
 private:
diff --git a/WebCore/platform/graphics/filters/FEFlood.cpp b/WebCore/platform/graphics/filters/FEFlood.cpp
index 7804d89..4b56a5c 100644
--- a/WebCore/platform/graphics/filters/FEFlood.cpp
+++ b/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -62,14 +62,14 @@ void FEFlood::setFloodOpacity(float floodOpacity)
     m_floodOpacity = floodOpacity;
 }
 
-void FEFlood::apply(Filter*)
+void FEFlood::apply(Filter* filter)
 {
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
-    filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size()), color, DeviceColorSpace);
+    filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, DeviceColorSpace);
 }
 
 void FEFlood::dump()
diff --git a/WebCore/platform/graphics/filters/FEFlood.h b/WebCore/platform/graphics/filters/FEFlood.h
index b615531..e6a9574 100644
--- a/WebCore/platform/graphics/filters/FEFlood.h
+++ b/WebCore/platform/graphics/filters/FEFlood.h
@@ -42,6 +42,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
 private:
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index fd9a3d8..b3264dd 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -4,6 +4,7 @@
  * Copyright (C) 2005 Eric Seidel <eric at webkit.org>
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
  * Copyright (C) 2010 Igalia, S.L.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -34,7 +35,8 @@
 
 using std::max;
 
-static const float gGaussianKernelFactor = (3 * sqrtf(2 * piFloat) / 4.f);
+static const float gGaussianKernelFactor = 3 / 4.f * sqrtf(2 * piFloat);
+static const unsigned gMaxKernelSize = 1000;
 
 namespace WebCore {
 
@@ -125,6 +127,41 @@ void FEGaussianBlur::kernelPosition(int boxBlur, unsigned& std, int& dLeft, int&
     }
 }
 
+inline void calculateKernelSize(Filter* filter, unsigned& kernelSizeX, unsigned& kernelSizeY, float stdX, float stdY)
+{
+    stdX = filter->applyHorizontalScale(stdX);
+    stdY = filter->applyVerticalScale(stdY);
+    
+    kernelSizeX = 0;
+    if (stdX)
+        kernelSizeX = max<unsigned>(2, static_cast<unsigned>(floorf(stdX * gGaussianKernelFactor + 0.5f)));
+    kernelSizeY = 0;
+    if (stdY)
+        kernelSizeY = max<unsigned>(2, static_cast<unsigned>(floorf(stdY * gGaussianKernelFactor + 0.5f)));
+    
+    // Limit the kernel size to 1000. A bigger radius won't make a big difference for the result image but
+    // inflates the absolute paint rect to much. This is compatible with Firefox' behavior.
+    if (kernelSizeX > gMaxKernelSize)
+        kernelSizeX = gMaxKernelSize;
+    if (kernelSizeY > gMaxKernelSize)
+        kernelSizeY = gMaxKernelSize;
+}
+
+void FEGaussianBlur::determineAbsolutePaintRect(Filter* filter)
+{
+    FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect();
+    absolutePaintRect.intersect(maxEffectRect());
+
+    unsigned kernelSizeX = 0;
+    unsigned kernelSizeY = 0;
+    calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
+
+    // We take the half kernel size and multiply it with three, because we run box blur three times.
+    absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f);
+    absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f);
+    setAbsolutePaintRect(enclosingIntRect(absolutePaintRect));
+}
+
 void FEGaussianBlur::apply(Filter* filter)
 {
     FilterEffect* in = inputEffect(0);
@@ -132,12 +169,12 @@ void FEGaussianBlur::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     setIsAlphaImage(in->isAlphaImage());
 
-    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<ImageData> srcImageData(in->resultImage()->getPremultipliedImageData(effectDrawingRect));
     IntRect imageRect(IntPoint(), resultImage()->size());
 
@@ -147,12 +184,8 @@ void FEGaussianBlur::apply(Filter* filter)
     }
 
     unsigned kernelSizeX = 0;
-    if (m_stdX)
-        kernelSizeX = max(2U, static_cast<unsigned>(floor(m_stdX * filter->filterResolution().width() * gGaussianKernelFactor + 0.5f)));
-
     unsigned kernelSizeY = 0;
-    if (m_stdY)
-        kernelSizeY = max(2U, static_cast<unsigned>(floor(m_stdY * filter->filterResolution().height() * gGaussianKernelFactor + 0.5f)));
+    calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY);
 
     CanvasPixelArray* srcPixelArray(srcImageData->data());
     RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.h b/WebCore/platform/graphics/filters/FEGaussianBlur.h
index 745bcc8..0f72543 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.h
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.h
@@ -42,6 +42,8 @@ public:
 
     virtual void apply(Filter*);
     virtual void dump();
+    
+    virtual void determineAbsolutePaintRect(Filter*);
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp
index f49b67d..e1df580 100644
--- a/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/WebCore/platform/graphics/filters/FELighting.cpp
@@ -247,12 +247,12 @@ void FELighting::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     setIsAlphaImage(false);
 
-    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<ImageData> srcImageData(in->resultImage()->getUnmultipliedImageData(effectDrawingRect));
     CanvasPixelArray* srcPixelArray(srcImageData->data());
 
@@ -261,8 +261,9 @@ void FELighting::apply(Filter* filter)
     // output for various kernelUnitLengths, and I am not sure they are reliable.
     // Anyway, feConvolveMatrix should also use the implementation
 
-    if (drawLighting(srcPixelArray, effectDrawingRect.width(), effectDrawingRect.height()))
-        resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
+    IntSize absolutePaintSize = absolutePaintRect().size();
+    if (drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height()))
+        resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), absolutePaintSize), IntPoint());
 }
 
 } // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FELighting.h b/WebCore/platform/graphics/filters/FELighting.h
index 28c00c4..bd56cee 100644
--- a/WebCore/platform/graphics/filters/FELighting.h
+++ b/WebCore/platform/graphics/filters/FELighting.h
@@ -44,6 +44,8 @@ class FELighting : public FilterEffect {
 public:
     virtual void apply(Filter*);
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
 protected:
     enum LightingType {
         DiffuseLighting,
diff --git a/WebCore/platform/graphics/filters/FEMerge.cpp b/WebCore/platform/graphics/filters/FEMerge.cpp
index 19c832a..d9332de 100644
--- a/WebCore/platform/graphics/filters/FEMerge.cpp
+++ b/WebCore/platform/graphics/filters/FEMerge.cpp
@@ -50,13 +50,13 @@ void FEMerge::apply(Filter* filter)
             return;
     }
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     for (unsigned i = 0; i < size; ++i) {
         FilterEffect* in = inputEffect(i);
-        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->repaintRectInLocalCoordinates()));
+        filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegionOfInputImage(in->absolutePaintRect()));
     }
 }
 
diff --git a/WebCore/platform/graphics/filters/FEMorphology.cpp b/WebCore/platform/graphics/filters/FEMorphology.cpp
index 7329e1e..ab6a11f 100644
--- a/WebCore/platform/graphics/filters/FEMorphology.cpp
+++ b/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2004, 2005 Rob Buis <buis at kde.org>
  * Copyright (C) 2005 Eric Seidel <eric at webkit.org>
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -74,6 +75,14 @@ float FEMorphology::radiusY() const
     return m_radiusY;
 }
 
+void FEMorphology::determineAbsolutePaintRect(Filter* filter)
+{
+    FloatRect paintRect = inputEffect(0)->absolutePaintRect();
+    paintRect.inflateX(filter->applyHorizontalScale(m_radiusX));
+    paintRect.inflateY(filter->applyVerticalScale(m_radiusY));
+    setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
 void FEMorphology::setRadiusY(float radiusY)
 {
     m_radiusY = radiusY;
@@ -86,18 +95,18 @@ void FEMorphology::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     setIsAlphaImage(in->isAlphaImage());
-
-    int radiusX = static_cast<int>(m_radiusX * filter->filterResolution().width());
-    int radiusY = static_cast<int>(m_radiusY * filter->filterResolution().height());
-    if (radiusX <= 0 || radiusY <= 0)
+    if (m_radiusX <= 0 || m_radiusY <= 0)
         return;
 
+    int radiusX = static_cast<int>(floorf(filter->applyHorizontalScale(m_radiusX)));
+    int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY)));
+
     IntRect imageRect(IntPoint(), resultImage()->size());
-    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->repaintRectInLocalCoordinates());
+    IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
     RefPtr<CanvasPixelArray> srcPixelArray(in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data());
     RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
 
diff --git a/WebCore/platform/graphics/filters/FEMorphology.h b/WebCore/platform/graphics/filters/FEMorphology.h
index c8ce058..913671d 100644
--- a/WebCore/platform/graphics/filters/FEMorphology.h
+++ b/WebCore/platform/graphics/filters/FEMorphology.h
@@ -49,6 +49,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*);
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
 private:
diff --git a/WebCore/platform/graphics/filters/FEOffset.cpp b/WebCore/platform/graphics/filters/FEOffset.cpp
index ea84cf0..1014364 100644
--- a/WebCore/platform/graphics/filters/FEOffset.cpp
+++ b/WebCore/platform/graphics/filters/FEOffset.cpp
@@ -3,6 +3,7 @@
  * Copyright (C) 2004, 2005 Rob Buis <buis at kde.org>
  * Copyright (C) 2005 Eric Seidel <eric at webkit.org>
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -62,6 +63,14 @@ void FEOffset::setDy(float dy)
     m_dy = dy;
 }
 
+void FEOffset::determineAbsolutePaintRect(Filter* filter)
+{
+    FloatRect paintRect = inputEffect(0)->absolutePaintRect();
+    paintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+    paintRect.intersect(maxEffectRect());
+    setAbsolutePaintRect(enclosingIntRect(paintRect));
+}
+
 void FEOffset::apply(Filter* filter)
 {
     FilterEffect* in = inputEffect(0);
@@ -69,28 +78,15 @@ void FEOffset::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     setIsAlphaImage(in->isAlphaImage());
 
-    FloatRect sourceImageRect = filter->sourceImageRect();
-    sourceImageRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
-
-    if (filter->effectBoundingBoxMode()) {
-        m_dx *= sourceImageRect.width();
-        m_dy *= sourceImageRect.height();
-    }
-    m_dx *= filter->filterResolution().width();
-    m_dy *= filter->filterResolution().height();
-
-    FloatRect dstRect = FloatRect(m_dx + in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(),
-                                  m_dy + in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y(),
-                                  in->repaintRectInLocalCoordinates().width(),
-                                  in->repaintRectInLocalCoordinates().height());
-
-    filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, dstRect);
+    FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
+    drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
+    filterContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, drawingRegion);
 }
 
 void FEOffset::dump()
diff --git a/WebCore/platform/graphics/filters/FEOffset.h b/WebCore/platform/graphics/filters/FEOffset.h
index 052ba74..36575c5 100644
--- a/WebCore/platform/graphics/filters/FEOffset.h
+++ b/WebCore/platform/graphics/filters/FEOffset.h
@@ -40,6 +40,8 @@ public:
 
     virtual void apply(Filter*);
     virtual void dump();
+    
+    virtual void determineAbsolutePaintRect(Filter*);
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
diff --git a/WebCore/platform/graphics/filters/FETile.cpp b/WebCore/platform/graphics/filters/FETile.cpp
index 41abd34..e40580c 100644
--- a/WebCore/platform/graphics/filters/FETile.cpp
+++ b/WebCore/platform/graphics/filters/FETile.cpp
@@ -27,6 +27,7 @@
 #include "Filter.h"
 #include "GraphicsContext.h"
 #include "Pattern.h"
+#include "SVGImageBufferTools.h"
 
 namespace WebCore {
 
@@ -44,7 +45,7 @@ FloatRect FETile::determineFilterPrimitiveSubregion(Filter* filter)
 {
     inputEffect(0)->determineFilterPrimitiveSubregion(filter);
 
-    filter->determineFilterPrimitiveSubregion(this, filter->filterRegion());
+    filter->determineFilterPrimitiveSubregion(this, filter->filterRegionInUserSpace());
     return filterPrimitiveSubregion();
 }
 
@@ -55,34 +56,37 @@ void FETile::apply(Filter* filter)
     if (!in->resultImage())
         return;
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     setIsAlphaImage(in->isAlphaImage());
 
-    IntRect tileRect = enclosingIntRect(in->repaintRectInLocalCoordinates());
-
     // Source input needs more attention. It has the size of the filterRegion but gives the
     // size of the cutted sourceImage back. This is part of the specification and optimization.
+    FloatRect tileRect = in->maxEffectRect();
+    FloatPoint inMaxEffectLocation = tileRect.location();
+    FloatPoint maxEffectLocation = maxEffectRect().location();
     if (in->isSourceInput()) {
-        FloatRect filterRegion = filter->filterRegion();
-        filterRegion.scale(filter->filterResolution().width(), filter->filterResolution().height());
-        tileRect = enclosingIntRect(filterRegion);
+        tileRect = filter->filterRegion();
+        tileRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
     }
 
-    OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
+    OwnPtr<ImageBuffer> tileImage;
+    if (!SVGImageBufferTools::createImageBuffer(tileRect, tileRect, tileImage, DeviceRGB))
+        return;
+
     GraphicsContext* tileImageContext = tileImage->context();
-    tileImageContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, IntPoint());
-    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
+    tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
+    tileImageContext->drawImageBuffer(in->resultImage(), DeviceColorSpace, in->absolutePaintRect().location());
 
-    AffineTransform matrix;
-    matrix.translate(in->repaintRectInLocalCoordinates().x() - repaintRectInLocalCoordinates().x(),
-                     in->repaintRectInLocalCoordinates().y() - repaintRectInLocalCoordinates().y());
-    pattern.get()->setPatternSpaceTransform(matrix);
+    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
 
+    AffineTransform patternTransform;
+    patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
+    pattern->setPatternSpaceTransform(patternTransform);
     filterContext->setFillPattern(pattern);
-    filterContext->fillRect(FloatRect(FloatPoint(), repaintRectInLocalCoordinates().size()));
+    filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
 }
 
 void FETile::dump()
diff --git a/WebCore/platform/graphics/filters/FETile.h b/WebCore/platform/graphics/filters/FETile.h
index 20efbcd..8562c90 100644
--- a/WebCore/platform/graphics/filters/FETile.h
+++ b/WebCore/platform/graphics/filters/FETile.h
@@ -35,6 +35,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
     virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
diff --git a/WebCore/platform/graphics/filters/FETurbulence.cpp b/WebCore/platform/graphics/filters/FETurbulence.cpp
index bb24362..b1494a5 100644
--- a/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -321,7 +321,7 @@ unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paint
 
 void FETurbulence::apply(Filter* filter)
 {
-    if (!effectContext())
+    if (!effectContext(filter))
         return;
 
     IntRect imageRect(IntPoint(), resultImage()->size());
@@ -329,10 +329,10 @@ void FETurbulence::apply(Filter* filter)
         return;
 
     RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
-    PaintingData paintingData(m_seed, imageRect.size());
+    PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
     initPaint(paintingData);
 
-    FloatRect filterRegion = filter->filterRegion();
+    FloatRect filterRegion = absolutePaintRect();
     FloatPoint point;
     point.setY(filterRegion.y());
     int indexOfPixelChannel = 0;
@@ -342,7 +342,7 @@ void FETurbulence::apply(Filter* filter)
         for (int x = 0; x < imageRect.width(); ++x) {
             point.setX(point.x() + 1);
             for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel)
-                imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, point));
+                imageData->data()->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, filter->mapAbsolutePointToLocalPoint(point)));
         }
     }
     resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
diff --git a/WebCore/platform/graphics/filters/FETurbulence.h b/WebCore/platform/graphics/filters/FETurbulence.h
index 1a5a28a..c15d7d1 100644
--- a/WebCore/platform/graphics/filters/FETurbulence.h
+++ b/WebCore/platform/graphics/filters/FETurbulence.h
@@ -60,6 +60,8 @@ public:
 
     virtual void apply(Filter*);
     virtual void dump();
+    
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
 
diff --git a/WebCore/platform/graphics/filters/Filter.h b/WebCore/platform/graphics/filters/Filter.h
index bce4be3..121e389 100644
--- a/WebCore/platform/graphics/filters/Filter.h
+++ b/WebCore/platform/graphics/filters/Filter.h
@@ -44,11 +44,18 @@ namespace WebCore {
         FloatSize filterResolution() const { return m_filterResolution; }
         void setFilterResolution(const FloatSize& filterResolution) { m_filterResolution = filterResolution; }
 
+        virtual float applyHorizontalScale(float value) const { return value * m_filterResolution.width(); }
+        virtual float applyVerticalScale(float value) const { return value * m_filterResolution.height(); }
+        
         virtual FloatRect sourceImageRect() const = 0;
         virtual FloatRect filterRegion() const = 0;
+        
+        virtual FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint&) const { return FloatPoint(); }
 
         // SVG specific
         virtual void determineFilterPrimitiveSubregion(FilterEffect*, const FloatRect&) { }
+        
+        virtual FloatRect filterRegionInUserSpace() const { return FloatRect(); }
 
         virtual FloatSize maxImageSize() const = 0;
         virtual bool effectBoundingBoxMode() const = 0;
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index 461b22a..b6c7e18 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -46,7 +46,7 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter)
 
     // FETurbulence, FEImage and FEFlood don't have input effects, take the filter region as unite rect.
     if (!size)
-        uniteRect = filter->filterRegion();
+        uniteRect = filter->filterRegionInUserSpace();
     else {
         for (unsigned i = 0; i < size; ++i)
             uniteRect.unite(m_inputEffects.at(i)->determineFilterPrimitiveSubregion(filter));
@@ -56,18 +56,29 @@ FloatRect FilterEffect::determineFilterPrimitiveSubregion(Filter* filter)
     return m_filterPrimitiveSubregion;
 }
 
-IntRect FilterEffect::requestedRegionOfInputImageData(const FloatRect& effectRect) const
+void FilterEffect::determineAbsolutePaintRect(Filter*)
+{
+    m_absolutePaintRect = IntRect();
+    unsigned size = m_inputEffects.size();
+    for (unsigned i = 0; i < size; ++i)
+        m_absolutePaintRect.unite(m_inputEffects.at(i)->absolutePaintRect());
+    
+    // SVG specification wants us to clip to primitive subregion.
+    m_absolutePaintRect.intersect(m_maxEffectRect);
+}
+
+IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
 {
     ASSERT(m_effectBuffer);
-    FloatPoint location = m_repaintRectInLocalCoordinates.location();
+    IntPoint location = m_absolutePaintRect.location();
     location.move(-effectRect.x(), -effectRect.y());
-    return IntRect(roundedIntPoint(location), m_effectBuffer->size());
+    return IntRect(location, m_effectBuffer->size());
 }
 
-FloatRect FilterEffect::drawingRegionOfInputImage(const FloatRect& srcRect) const
+IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
 {
-    return FloatRect(FloatPoint(srcRect.x() - m_repaintRectInLocalCoordinates.x(),
-                                srcRect.y() - m_repaintRectInLocalCoordinates.y()), srcRect.size());
+    return IntRect(IntPoint(srcRect.x() - m_absolutePaintRect.x(),
+                            srcRect.y() - m_absolutePaintRect.y()), srcRect.size());
 }
 
 FilterEffect* FilterEffect::inputEffect(unsigned number) const
@@ -76,10 +87,12 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const
     return m_inputEffects.at(number).get();
 }
 
-GraphicsContext* FilterEffect::effectContext()
+GraphicsContext* FilterEffect::effectContext(Filter* filter)
 {
-    IntRect bufferRect = enclosingIntRect(m_repaintRectInLocalCoordinates);
-    m_effectBuffer = ImageBuffer::create(bufferRect.size(), LinearRGB);
+    determineAbsolutePaintRect(filter);
+    if (m_absolutePaintRect.isEmpty())
+        return 0;
+    m_effectBuffer = ImageBuffer::create(m_absolutePaintRect.size(), LinearRGB);
     if (!m_effectBuffer)
         return 0;
     return m_effectBuffer->context();
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index ebe1880..9e8bb61 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -49,25 +49,30 @@ public:
 
     // Creates the ImageBuffer for the current filter primitive result in the size of the
     // repaintRect. Gives back the GraphicsContext of the own ImageBuffer.
-    GraphicsContext* effectContext();
+    GraphicsContext* effectContext(Filter*);
 
     FilterEffectVector& inputEffects() { return m_inputEffects; }
     FilterEffect* inputEffect(unsigned) const;
     unsigned numberOfEffectInputs() const { return m_inputEffects.size(); }
 
-    FloatRect drawingRegionOfInputImage(const FloatRect&) const;
-    IntRect requestedRegionOfInputImageData(const FloatRect&) const;
+    IntRect drawingRegionOfInputImage(const IntRect&) const;
+    IntRect requestedRegionOfInputImageData(const IntRect&) const;
 
     // Solid black image with different alpha values.
     bool isAlphaImage() const { return m_alphaImage; }
     void setIsAlphaImage(bool alphaImage) { m_alphaImage = alphaImage; }
 
-    FloatRect repaintRectInLocalCoordinates() const { return m_repaintRectInLocalCoordinates; }
-    void setRepaintRectInLocalCoordinates(const FloatRect& repaintRectInLocalCoordinates) { m_repaintRectInLocalCoordinates = repaintRectInLocalCoordinates; }
+    IntRect absolutePaintRect() const { return m_absolutePaintRect; }
+    void setAbsolutePaintRect(const IntRect& absolutePaintRect) { m_absolutePaintRect = absolutePaintRect; }
+    
+    IntRect maxEffectRect() const { return m_maxEffectRect; }
+    void setMaxEffectRect(const IntRect& maxEffectRect) { m_maxEffectRect = maxEffectRect; } 
 
     virtual void apply(Filter*) = 0;
     virtual void dump() = 0;
 
+    virtual void determineAbsolutePaintRect(Filter*);
+    
     virtual bool isSourceInput() const { return false; }
 
     virtual TextStream& externalRepresentation(TextStream&, int indention = 0) const;
@@ -87,7 +92,7 @@ public:
     bool hasHeight() const { return m_hasHeight; }
     void setHasHeight(bool value) { m_hasHeight = value; }
 
-    // FIXME: Pseudo primitives like SourceGraphic and SourceAlpha as well as FETile still need special handling.
+    // FIXME: FETile still needs special handling.
     virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
 
     FloatRect filterPrimitiveSubregion() const { return m_filterPrimitiveSubregion; }
@@ -105,8 +110,11 @@ private:
 
     bool m_alphaImage;
 
-    // FIXME: Should be the paint region of the filter primitive, instead of the scaled subregion on use of filterRes.
-    FloatRect m_repaintRectInLocalCoordinates;
+    IntRect m_absolutePaintRect;
+    
+    // The maximum size of a filter primitive. In SVG this is the primitive subregion in absolute coordinate space.
+    // The absolute paint rect should never be bigger than m_maxEffectRect.
+    IntRect m_maxEffectRect;
 
 private:
     // The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive.
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index beaf2e7..15caf5a 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -42,28 +42,22 @@ const AtomicString& SourceAlpha::effectName()
     return s_effectName;
 }
 
-FloatRect SourceAlpha::determineFilterPrimitiveSubregion(Filter* filter)
+void SourceAlpha::determineAbsolutePaintRect(Filter* filter)
 {
-    FloatRect clippedSourceRect = filter->sourceImageRect();
-    if (filter->sourceImageRect().x() < filter->filterRegion().x())
-        clippedSourceRect.setX(filter->filterRegion().x());
-    if (filter->sourceImageRect().y() < filter->filterRegion().y())
-        clippedSourceRect.setY(filter->filterRegion().y());
-    setFilterPrimitiveSubregion(clippedSourceRect);
-    clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
-    setRepaintRectInLocalCoordinates(clippedSourceRect);
-    return filter->filterRegion();
+    FloatRect paintRect = filter->sourceImageRect();
+    paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+    setAbsolutePaintRect(enclosingIntRect(paintRect));
 }
 
 void SourceAlpha::apply(Filter* filter)
 {
-    GraphicsContext* filterContext = effectContext();
-    if (!filterContext)
+    GraphicsContext* filterContext = effectContext(filter);
+    if (!filterContext || !filter->sourceImage())
         return;
 
     setIsAlphaImage(true);
 
-    FloatRect imageRect(FloatPoint(), filter->sourceImage()->size());
+    FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
     filterContext->save();
     filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
     filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.h b/WebCore/platform/graphics/filters/SourceAlpha.h
index f0fa319..2c249e6 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.h
+++ b/WebCore/platform/graphics/filters/SourceAlpha.h
@@ -34,11 +34,11 @@ public:
 
     static const AtomicString& effectName();
 
-    virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
-
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*);
+
     virtual bool isSourceInput() const { return true; }
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index c014e68..5e5dc34 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -41,23 +41,17 @@ const AtomicString& SourceGraphic::effectName()
     return s_effectName;
 }
 
-FloatRect SourceGraphic::determineFilterPrimitiveSubregion(Filter* filter)
+void SourceGraphic::determineAbsolutePaintRect(Filter* filter)
 {
-    FloatRect clippedSourceRect = filter->sourceImageRect();
-    if (filter->sourceImageRect().x() < filter->filterRegion().x())
-        clippedSourceRect.setX(filter->filterRegion().x());
-    if (filter->sourceImageRect().y() < filter->filterRegion().y())
-        clippedSourceRect.setY(filter->filterRegion().y());
-    setFilterPrimitiveSubregion(clippedSourceRect);
-    clippedSourceRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
-    setRepaintRectInLocalCoordinates(clippedSourceRect);
-    return filter->filterRegion();
+    FloatRect paintRect = filter->sourceImageRect();
+    paintRect.scale(filter->filterResolution().width(), filter->filterResolution().height());
+    setAbsolutePaintRect(enclosingIntRect(paintRect));
 }
 
 void SourceGraphic::apply(Filter* filter)
 {
-    GraphicsContext* filterContext = effectContext();
-    if (!filterContext)
+    GraphicsContext* filterContext = effectContext(filter);
+    if (!filterContext || !filter->sourceImage())
         return;
 
     filterContext->drawImageBuffer(filter->sourceImage(), DeviceColorSpace, IntPoint());
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h
index 2378798..1816373 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.h
+++ b/WebCore/platform/graphics/filters/SourceGraphic.h
@@ -35,11 +35,11 @@ public:
 
     static const AtomicString& effectName();
 
-    virtual FloatRect determineFilterPrimitiveSubregion(Filter*);
-
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*);
+
     virtual bool isSourceInput() const { return true; }
 
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp
index 4dccad6..4b2080a 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.cpp
+++ b/WebCore/rendering/RenderSVGResourceFilter.cpp
@@ -39,6 +39,7 @@
 #include "SVGFilter.h"
 #include "SVGFilterElement.h"
 #include "SVGFilterPrimitiveStandardAttributes.h"
+#include "SVGImageBufferTools.h"
 #include "SVGStyledElement.h"
 #include "SVGUnitTypes.h"
 #include <wtf/Vector.h>
@@ -150,70 +151,93 @@ bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*,
     }
 
     OwnPtr<FilterData> filterData(new FilterData);
+    FloatRect targetBoundingBox = object->objectBoundingBox();
+
+    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
+    filterData->boundaries = filterElement->filterBoundingBox(targetBoundingBox);
+    if (filterData->boundaries.isEmpty())
+        return false;
+
+    // Determine absolute transformation matrix for filter. 
+    AffineTransform absoluteTransform;
+    SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(object, absoluteTransform);
+    if (!absoluteTransform.isInvertible())
+        return false;
+
+    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
+    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), absoluteTransform.e(), absoluteTransform.f());
+
+    // Determine absolute boundaries of the filter and the drawing region.
+    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
+    FloatRect drawingRegion = object->strokeBoundingBox();
+    drawingRegion.intersect(filterData->boundaries);
+    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(drawingRegion);
+
+    // Create the SVGFilter object.
+    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
+
+    // Create all relevant filter primitives.
     filterData->builder = buildPrimitives();
     if (!filterData->builder)
         return false;
 
-    FloatRect paintRect = object->strokeBoundingBox();
-
     // Calculate the scale factor for the use of filterRes.
     // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
-    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
-    filterData->boundaries = filterElement->filterBoundingBox(object->objectBoundingBox());
-    if (filterData->boundaries.isEmpty())
-        return false;
-
-    FloatSize scale(1.0f, 1.0f);
+    FloatSize scale(1, 1);
     if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
-        scale.setWidth(filterElement->filterResX() / filterData->boundaries.width());
-        scale.setHeight(filterElement->filterResY() / filterData->boundaries.height());
+        scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width());
+        scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height());
     }
 
     if (scale.isEmpty())
         return false;
 
-    // clip sourceImage to filterRegion
-    FloatRect clippedSourceRect = paintRect;
-    clippedSourceRect.intersect(filterData->boundaries);
-
-    // scale filter size to filterRes
-    FloatRect tempSourceRect = clippedSourceRect;
-
-    // scale to big sourceImage size to kMaxFilterSize
+    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
+    FloatRect tempSourceRect = absoluteDrawingRegion;
     tempSourceRect.scale(scale.width(), scale.height());
     fitsInMaximumImageSize(tempSourceRect.size(), scale);
 
-    // prepare Filters
-    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
-    filterData->filter = SVGFilter::create(paintRect, filterData->boundaries, primitiveBoundingBoxMode);
+    // Set the scale level in SVGFilter.
     filterData->filter->setFilterResolution(scale);
 
     FilterEffect* lastEffect = filterData->builder->lastEffect();
     if (!lastEffect)
         return false;
-    
+
+    // Determine the filter primitive subregions of every effect.
     lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get());
-    // At least one FilterEffect has a too big image size,
-    // recalculate the effect sizes with new scale factors.
     if (!fitsInMaximumImageSize(filterData->filter->maxImageSize(), scale)) {
+        // At least one FilterEffect has a too big image size,
+        // recalculate the effect sizes with new scale factor.
         filterData->filter->setFilterResolution(scale);
         lastEffect->determineFilterPrimitiveSubregion(filterData->filter.get());
     }
 
-    clippedSourceRect.scale(scale.width(), scale.height());
-
-    // Draw the content of the current element and it's childs to a imageBuffer to get the SourceGraphic.
-    // The size of the SourceGraphic is clipped to the size of the filterRegion.
-    IntRect bufferRect = enclosingIntRect(clippedSourceRect);
-    OwnPtr<ImageBuffer> sourceGraphic(ImageBuffer::create(bufferRect.size(), LinearRGB));
-    
-    if (!sourceGraphic.get())
+    // If the drawingRegion is empty, we have something like <g filter=".."/>.
+    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
+    if (drawingRegion.isEmpty()) {
+        ASSERT(!m_filter.contains(object));
+        filterData->savedContext = context;
+        m_filter.set(object, filterData.leakPtr());
         return false;
+    }
 
+    absoluteDrawingRegion.scale(scale.width(), scale.height());
+
+    OwnPtr<ImageBuffer> sourceGraphic;
+    if (!SVGImageBufferTools::createImageBuffer(absoluteDrawingRegion, absoluteDrawingRegion, sourceGraphic, LinearRGB))
+        return false;
+    
     GraphicsContext* sourceGraphicContext = sourceGraphic->context();
-    sourceGraphicContext->translate(-clippedSourceRect.x(), -clippedSourceRect.y());
-    sourceGraphicContext->scale(scale);
-    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), paintRect.size()));
+    ASSERT(sourceGraphicContext);
+  
+    sourceGraphicContext->translate(-absoluteDrawingRegion.x(), -absoluteDrawingRegion.y());
+    if (scale.width() != 1 || scale.height() != 1)
+        sourceGraphicContext->scale(scale);
+
+    sourceGraphicContext->concatCTM(filterData->shearFreeAbsoluteTransform);
+    sourceGraphicContext->clearRect(FloatRect(FloatPoint(), absoluteDrawingRegion.size()));
     filterData->sourceGraphicBuffer = sourceGraphic.release();
     filterData->savedContext = context;
 
@@ -270,10 +294,17 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
         }
 
         ImageBuffer* resultImage = lastEffect->resultImage();
-        if (resultImage)
-            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->filterPrimitiveSubregion());
-    }
+        if (resultImage) {
+            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
 
+            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
+            context->clip(lastEffect->maxEffectRect());
+            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect());
+            context->scale(filterData->filter->filterResolution());
+
+            context->concatCTM(filterData->shearFreeAbsoluteTransform);
+        }
+    }
     filterData->sourceGraphicBuffer.clear();
 }
 
diff --git a/WebCore/rendering/RenderSVGResourceFilter.h b/WebCore/rendering/RenderSVGResourceFilter.h
index 314c94d..c64f5c6 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.h
+++ b/WebCore/rendering/RenderSVGResourceFilter.h
@@ -42,7 +42,8 @@ namespace WebCore {
 
 struct FilterData {
     FilterData()
-        : builded(false)
+        : savedContext(0)
+        , builded(false)
     {
     }
 
@@ -50,6 +51,7 @@ struct FilterData {
     RefPtr<SVGFilterBuilder> builder;
     OwnPtr<ImageBuffer> sourceGraphicBuffer;
     GraphicsContext* savedContext;
+    AffineTransform shearFreeAbsoluteTransform;
     FloatRect boundaries;
     FloatSize scale;
     bool builded;
diff --git a/WebCore/svg/graphics/filters/SVGFEImage.cpp b/WebCore/svg/graphics/filters/SVGFEImage.cpp
index c94547b..d7edc38 100644
--- a/WebCore/svg/graphics/filters/SVGFEImage.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEImage.cpp
@@ -44,17 +44,17 @@ PassRefPtr<FEImage> FEImage::create(RefPtr<Image> image, const SVGPreserveAspect
     return adoptRef(new FEImage(image, preserveAspectRatio));
 }
 
-void FEImage::apply(Filter*)
+void FEImage::apply(Filter* filter)
 {
     if (!m_image.get())
         return;
 
-    GraphicsContext* filterContext = effectContext();
+    GraphicsContext* filterContext = effectContext(filter);
     if (!filterContext)
         return;
 
     FloatRect srcRect(FloatPoint(), m_image->size());
-    FloatRect destRect(FloatPoint(), filterPrimitiveSubregion().size());
+    FloatRect destRect(FloatPoint(), absolutePaintRect().size());
 
     m_preserveAspectRatio.transformRect(destRect, srcRect);
 
diff --git a/WebCore/svg/graphics/filters/SVGFEImage.h b/WebCore/svg/graphics/filters/SVGFEImage.h
index fe2d8c4..7cd971b 100644
--- a/WebCore/svg/graphics/filters/SVGFEImage.h
+++ b/WebCore/svg/graphics/filters/SVGFEImage.h
@@ -36,6 +36,8 @@ public:
     virtual void apply(Filter*);
     virtual void dump();
 
+    virtual void determineAbsolutePaintRect(Filter*) { setAbsolutePaintRect(maxEffectRect()); }
+
     virtual TextStream& externalRepresentation(TextStream&, int indention) const;
     
 private:
diff --git a/WebCore/svg/graphics/filters/SVGFilter.cpp b/WebCore/svg/graphics/filters/SVGFilter.cpp
index d72dc3d..2b16ad4 100644
--- a/WebCore/svg/graphics/filters/SVGFilter.cpp
+++ b/WebCore/svg/graphics/filters/SVGFilter.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Dirk Schulze <krit at webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -24,12 +25,15 @@
 
 namespace WebCore {
 
-SVGFilter::SVGFilter(const FloatRect& targetBoundingBox, const FloatRect& filterRect, bool effectBBoxMode)
+SVGFilter::SVGFilter(const AffineTransform& absoluteTransform, const FloatRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode)
     : Filter()
+    , m_absoluteTransform(absoluteTransform)
+    , m_absoluteSourceDrawingRegion(absoluteSourceDrawingRegion)
     , m_targetBoundingBox(targetBoundingBox)
-    , m_filterRect(filterRect)
+    , m_filterRegion(filterRegion)
     , m_effectBBoxMode(effectBBoxMode)
 {
+    m_absoluteFilterRegion = absoluteTransform.mapRect(filterRegion);
 }
 
 void SVGFilter::determineFilterPrimitiveSubregion(FilterEffect* effect, const FloatRect& unionOfPreviousPrimitiveSubregions)
@@ -66,22 +70,37 @@ void SVGFilter::determineFilterPrimitiveSubregion(FilterEffect* effect, const Fl
     }
 
     // clip every filter effect to the filter region
-    newSubRegion.intersect(m_filterRect);
+    newSubRegion.intersect(m_filterRegion);
 
     effect->setFilterPrimitiveSubregion(newSubRegion);
-    
     // TODO: Everything above should be moved to a first phase of layout in RenderSVGResourceFilterPrimitive.
     // The scaling of the subregion to the repaint rect should be merged with a more intelligent repaint logic
     // and moved to the second phase of layout in RenderSVGResourceFilterPrimitive.
     // See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
+    newSubRegion = m_absoluteTransform.mapRect(newSubRegion);
     newSubRegion.scale(filterResolution().width(), filterResolution().height());
-    effect->setRepaintRectInLocalCoordinates(newSubRegion);
-    m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size()); 
+    effect->setMaxEffectRect(enclosingIntRect(newSubRegion));
+    if (!effect->isSourceInput())
+        m_maxImageSize = m_maxImageSize.expandedTo(newSubRegion.size()); 
 }
 
-PassRefPtr<SVGFilter> SVGFilter::create(const FloatRect& targetBoundingBox, const FloatRect& filterRect, bool effectBBoxMode)
+float SVGFilter::applyHorizontalScale(float value) const
 {
-    return adoptRef(new SVGFilter(targetBoundingBox, filterRect, effectBBoxMode));
+    if (m_effectBBoxMode)
+        value *= m_targetBoundingBox.width();
+    return Filter::applyHorizontalScale(value) * m_absoluteFilterRegion.width() / m_filterRegion.width();
+}
+
+float SVGFilter::applyVerticalScale(float value) const
+{
+    if (m_effectBBoxMode)
+        value *= m_targetBoundingBox.height();
+    return Filter::applyVerticalScale(value) * m_absoluteFilterRegion.height() / m_filterRegion.height();
+}
+
+PassRefPtr<SVGFilter> SVGFilter::create(const AffineTransform& absoluteTransform, const FloatRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode)
+{
+    return adoptRef(new SVGFilter(absoluteTransform, absoluteSourceDrawingRegion, targetBoundingBox, filterRegion, effectBBoxMode));
 }
 
 } // namespace WebCore
diff --git a/WebCore/svg/graphics/filters/SVGFilter.h b/WebCore/svg/graphics/filters/SVGFilter.h
index 631f1ee..1b19e9f 100644
--- a/WebCore/svg/graphics/filters/SVGFilter.h
+++ b/WebCore/svg/graphics/filters/SVGFilter.h
@@ -21,6 +21,7 @@
 #define SVGFilter_h
 
 #if ENABLE(SVG) && ENABLE(FILTERS)
+#include "AffineTransform.h"
 #include "Filter.h"
 #include "FilterEffect.h"
 #include "FloatRect.h"
@@ -32,27 +33,36 @@
 
 namespace WebCore {
 
-    class SVGFilter : public Filter {
-    public:
-        static PassRefPtr<SVGFilter> create(const FloatRect&, const FloatRect&, bool);
+class SVGFilter : public Filter {
+public:
+    static PassRefPtr<SVGFilter> create(const AffineTransform&, const FloatRect&, const FloatRect&, const FloatRect&, bool);
 
-        virtual bool effectBoundingBoxMode() const { return m_effectBBoxMode; }
+    virtual bool effectBoundingBoxMode() const { return m_effectBBoxMode; }
 
-        virtual FloatRect filterRegion() const { return m_filterRect; }
-        
-        virtual FloatRect sourceImageRect() const { return m_targetBoundingBox; }
+    virtual FloatRect filterRegionInUserSpace() const { return m_filterRegion; }
+    virtual FloatRect filterRegion() const { return m_absoluteFilterRegion; }
 
-        virtual FloatSize maxImageSize() const { return m_maxImageSize; }
-        virtual void determineFilterPrimitiveSubregion(FilterEffect*, const FloatRect&);
+    virtual FloatPoint mapAbsolutePointToLocalPoint(const FloatPoint& point) const { return m_absoluteTransform.inverse().mapPoint(point); }
 
-    private:
-        SVGFilter(const FloatRect& targetBoundingBox, const FloatRect& filterRect, bool effectBBoxMode);
+    virtual float applyHorizontalScale(float value) const;
+    virtual float applyVerticalScale(float value) const;
 
-        FloatSize m_maxImageSize;
-        FloatRect m_targetBoundingBox;
-        FloatRect m_filterRect;
-        bool m_effectBBoxMode;
-    };
+    virtual FloatRect sourceImageRect() const { return m_absoluteSourceDrawingRegion; }
+    
+    virtual FloatSize maxImageSize() const { return m_maxImageSize; }
+    virtual void determineFilterPrimitiveSubregion(FilterEffect*, const FloatRect&);
+
+private:
+    SVGFilter(const AffineTransform& absoluteTransform, const FloatRect& absoluteSourceDrawingRegion, const FloatRect& targetBoundingBox, const FloatRect& filterRegion, bool effectBBoxMode);
+
+    AffineTransform m_absoluteTransform;
+    FloatRect m_absoluteSourceDrawingRegion;
+    FloatRect m_targetBoundingBox;
+    FloatRect m_absoluteFilterRegion;
+    FloatRect m_filterRegion;
+    bool m_effectBBoxMode;
+    FloatSize m_maxImageSize;
+};
 
 } // namespace WebCore
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list