<feImage> doesn't work with local references when using primitiveUnits="objectBoundin...
authorzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 13:54:21 +0000 (13:54 +0000)
committerzimmermann@webkit.org <zimmermann@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jan 2012 13:54:21 +0000 (13:54 +0000)
commit88d0fbf4c569c58f5c41d672da2852ecdb05adb2
treecbfd6443dd0fbd4528b97de0a59f28204d26848b
parente6e25e2a1efaf784c835bddad822a74db31c2798
<feImage> doesn't work with local references when using primitiveUnits="objectBoundingBox"
https://bugs.webkit.org/show_bug.cgi?id=77205

Reviewed by Antti Koivisto.

Source/WebCore:

Consider following testcase:
<svg width="1000" height="500">
<defs>
    <circle id="c" cx="50%" cy="50%" r="10%"/>
    <filter id="f" filterUnits="userSpaceOnUse" x="0" y="0" width="100" height="100" primitiveUnits="objectBoundingBox">
        <feImage xlink:href="#c"/>
    </filter>
</defs>
<rect width="100" height="100" filter="url(#f)"/>
</svg>

The <svg> has a viewport of 1000x50. The <circle> in the <defs> element is resolved as <circle cx="500" cy="250" r="79"/>,
as the context for this element (looking at it isolated!) is the viewport of the <svg>. We then setup a 0x0 - 100x100 rect
in user space, which gets filtered, by a filter, also defined in user space (for simplicity), but with primitiveUnits="objectBoundingBox".

That means that the default subregion of the filter effect <feImage/> which has no inputs, is defined in the SVG 1.1 spec to be equal to
the filter region, which is 0x0-100x100 in user space. This <feImage/> is supposed to produce a 100x100 image, containing a circle in the
middle (aka. <circle cx="50" cy="50".../>), but it doesn't, as the <circle> it's trying to paint, is laid out at 500x250, and thus outside
the 100x100 sized image buffer.

So how to resolve this?
The RenderSVGShape thats owned by the <circle> generates its Path value by calling cx().value(lengthContext) and the SVGLengthContext here
resolves to the <svg>. That happens on _layout_. If we would want to change the SVGLengthContext in this case (what I originally planned!)
to carry a custom 100x100 viewport, we'd need to relayout. Unfortunately this is not an option, as this would mean that
SVGImageBufferTools::renderSubtreeToImageBuffer, would need to relayout its children first, but we produce the filter images when painting.
This is very dangerous and has just recently been fixed so that SVGImageBufferTools can ASSERT(!item->needsLayout()) when painting the
subtree to an image buffer.

The only sane solution I see, that does not require relayouts, is to make a map between the <circle> bounding box in user space (500x250
center point) to the filter primitive subregion space (here: 100x100 center point), and concat that transformation before painting the
subtree to the image buffer. Of course this approach only works if all values of the <circle> are relative. If someone uses
<circle id="c" cx="50%" cy="666"> the transformation that I'm looking for is undefined. We'd really need to create a new Path here, to
resolve only cx against the new viewport, and not cy.

Though in practice it turns out this is not a problem. All use cases of feImage + primitiveUnits="objectBoundingBox" link to elements
that are completely defined in percentual values, as this is really the only thing which makes sense - otherwise you can always switch
back to primtiveUnits="userSpaceOnUse". Anyhow, I'm going to fix all known wild-life test cases by my approach, and say we don't support
using mixed length units when referencing those elements from feImages with primitiveUnits="objectBoundingBox".

Adding lots of new testcases, trying all the different feImage modes.

Tests: svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox.svg
       svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse.svg
       svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox.svg
       svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse.svg
       svg/filters/feImage-position.svg
       svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox.svg
       svg/filters/feImage-subregions-preseveAspectRatio-none.svg
       svg/filters/feImage-subregions.svg

* rendering/svg/RenderSVGResourceFilterPrimitive.cpp:
(WebCore::RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion): Reverse logic, simplifying the code a bit. Remove FEImage special cases (absoluteSubregion).
* svg/SVGLengthContext.h: Make determineViewport() public, for use in FEImage.
* svg/graphics/filters/SVGFEImage.cpp:
(WebCore::FEImage::determineAbsolutePaintRect): Don't apply preserveAspectRatio transformation for local elements, it's not defined and breaks content.
(WebCore::FEImage::platformApplySoftware): Figure out the absolute subregion by utilizing filterPrimitiveSubregion() as FETurbulence does.
                                           Map between filter primitive subregion and target object space for primitiveUnits="objectBoundingBox" support on SVG element references.
* svg/graphics/filters/SVGFEImage.h: Remove absoluteSubregion member & setter, it's no longer needed.

LayoutTests:

Add new test cases covering all combinations of filterUnits/primitiveUnits and <feImage>.

* platform/chromium/test_expectations.txt:
* platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png: Added.
* platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.txt: Added.
* platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.png: Added.
* platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.txt: Added.
* platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.png: Added.
* platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.txt: Added.
* platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.png: Added.
* platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.txt: Added.
* platform/mac/svg/filters/feImage-position-expected.png: Added.
* platform/mac/svg/filters/feImage-position-expected.txt: Added.
* platform/mac/svg/filters/feImage-subregions-expected.png: Added.
* platform/mac/svg/filters/feImage-subregions-expected.txt: Added.
* platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-expected.png: Added.
* platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-expected.txt: Added.
* platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox-expected.png: Added.
* platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox-expected.txt: Added.
* svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox.svg: Added.
* svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse.svg: Added.
* svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox.svg: Added.
* svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse.svg: Added.
* svg/filters/feImage-position.svg: Added.
* svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox.svg: Added.
* svg/filters/feImage-subregions-preseveAspectRatio-none.svg: Added.
* svg/filters/feImage-subregions.svg: Added.
* svg/filters/resources/green.png: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@106113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
32 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/chromium/test_expectations.txt
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-position-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-position-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox-expected.txt [new file with mode: 0644]
LayoutTests/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-objectBoundingBox.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-filterUnits-objectBoundingBox-primitiveUnits-userSpaceOnUse.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-objectBoundingBox.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-filterUnits-userSpaceOnUse-primitiveUnits-userSpaceOnUse.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-position.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-subregions-preseveAspectRatio-none-with-viewBox.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-subregions-preseveAspectRatio-none.svg [new file with mode: 0644]
LayoutTests/svg/filters/feImage-subregions.svg [new file with mode: 0644]
LayoutTests/svg/filters/resources/green.png [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
Source/WebCore/svg/SVGLengthContext.h
Source/WebCore/svg/graphics/filters/SVGFEImage.cpp
Source/WebCore/svg/graphics/filters/SVGFEImage.h