haikuwebkit/LayoutTests/svg/filters/feImage-subregions-preseveA...

44 lines
1.5 KiB
XML
Raw Permalink Normal View History

<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. Canonical link: https://commits.webkit.org/94091@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@106113 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2012-01-27 13:54:21 +00:00
<svg viewBox="0 0 800 600" width="400" height="500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<title>Green rectangles should be within the red frames</title>
<rect id="rect" width="100" height="100" fill="green"/>
<filter id="filter1" >
<feImage preserveAspectRatio="none" x="0%" y="0%" width="100%" height="100%" xlink:href="#rect"/>
</filter>
<filter id="filter2" >
<feImage preserveAspectRatio="none" xlink:href="#rect"/>
</filter>
<filter id="filter3" >
<feImage preserveAspectRatio="none" x="0%" y="0%" width="100%" height="100%" xlink:href="resources/green.png"/>
</filter>
<filter id="filter4" >
<feImage preserveAspectRatio="none" xlink:href="resources/green.png"/>
</filter>
</defs>
<g transform="translate(50, 10)">
<rect width="400" height="200" fill="green" filter="url(#filter1)"/>
<g transform="translate(0, 250)">
<rect width="400" height="200" fill="green" filter="url(#filter2)"/>
</g>
</g>
<g transform="translate(250, 10)">
<rect width="400" height="200" fill="green" filter="url(#filter3)"/>
<g transform="translate(0, 250)">
<rect width="400" height="200" fill="green" filter="url(#filter4)"/>
</g>
</g>
<rect fill="none" stroke="red" x="50" y="10" width="100" height="100"/>
<rect fill="none" stroke="red" x="10" y="240" width="100" height="100"/>
<rect fill="none" stroke="red" x="250" y="10" width="440" height="220"/>
<rect fill="none" stroke="red" x="210" y="240" width="480" height="240"/>
</svg>