Changeset 96155 in webkit


Ignore:
Timestamp:
Sep 27, 2011 2:06:17 PM (13 years ago)
Author:
timothy_horton@apple.com
Message:

REGRESSION(65665): Pattern size being clamped to SVG size can prevent transformed elements from being fully covered by userSpaceOnUse patterns
https://bugs.webkit.org/show_bug.cgi?id=67700
<rdar://problem/10125102>

Reviewed by Darin Adler.

Clamp all resources to the same size, 4096x4096 (arbitrarily chosen), instead of to the size
of the <svg> element. This fixes the case where a transformed element displays part of a resource
outside of the size of the <svg> element.

When drawing an oversized pattern into its tile image, scale the content down to fit. When drawing
the tile image to the screen, scale it back up to fit the expected area. This will cause pixelation
when patterns are over the 4k limit.

Tests: svg/custom/transformed-pattern-clamp-svg-root.svg, svg/custom/oversized-pattern-scale.svg

  • rendering/svg/RenderSVGResourceClipper.cpp:

(WebCore::RenderSVGResourceClipper::applyClippingToContext):

  • rendering/svg/RenderSVGResourceGradient.cpp:

(WebCore::createMaskAndSwapContextForTextGradient):
(WebCore::clipToTextMask):

  • rendering/svg/RenderSVGResourceMasker.cpp:

(WebCore::RenderSVGResourceMasker::applyResource):

  • rendering/svg/RenderSVGResourcePattern.cpp:

(WebCore::RenderSVGResourcePattern::applyResource):
(WebCore::RenderSVGResourcePattern::createTileImage):

  • rendering/svg/RenderSVGResourcePattern.h:
  • rendering/svg/SVGImageBufferTools.cpp:

(WebCore::SVGImageBufferTools::clampedAbsoluteTargetRect):

  • rendering/svg/SVGImageBufferTools.h:

pattern-excessive-malloc is so excessive that it runs into the floating point precision barrier
when determining the scale to draw the pattern at; drop the size two orders of magnitude, which is
still very excessive but easier to draw with.

Add a test (transformed-pattern-clamp-svg-root.svg) that ensures that patterns on transformed
elements are displayed correctly, instead of being clamped to the size of the <svg> element.

Add a test (oversized-pattern-scale.svg) that ensures that oversized patterns are correctly drawn
into the pattern tile scaled down and then are scaled back up when drawn to the screen.

  • platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png:
  • platform/mac/svg/custom/pattern-excessive-malloc-expected.txt:
  • platform/qt/svg/custom/pattern-excessive-malloc-expected.txt:
  • svg/custom/pattern-excessive-malloc-expected.txt:
  • svg/custom/pattern-excessive-malloc.svg:
  • svg/custom/oversized-pattern-scale-expected.png: Added.
  • svg/custom/oversized-pattern-scale-expected.txt: Added.
  • svg/custom/oversized-pattern-scale.svg: Added.
  • svg/custom/transformed-pattern-clamp-svg-root.svg: Added.
  • svg/custom/transformed-pattern-clamp-svg-root-expected.png: Added.
  • svg/custom/transformed-pattern-clamp-svg-root-expected.txt: Added.
Location:
trunk
Files:
6 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r96154 r96155  
     12011-09-27  Tim Horton  <timothy_horton@apple.com>
     2
     3        REGRESSION(65665): Pattern size being clamped to SVG size can prevent transformed elements from being fully covered by userSpaceOnUse patterns
     4        https://bugs.webkit.org/show_bug.cgi?id=67700
     5        <rdar://problem/10125102>
     6
     7        Reviewed by Darin Adler.
     8
     9        pattern-excessive-malloc is so excessive that it runs into the floating point precision barrier
     10        when determining the scale to draw the pattern at; drop the size two orders of magnitude, which is
     11        still very excessive but easier to draw with.
     12
     13        Add a test (transformed-pattern-clamp-svg-root.svg) that ensures that patterns on transformed
     14        elements are displayed correctly, instead of being clamped to the size of the <svg> element.
     15
     16        Add a test (oversized-pattern-scale.svg) that ensures that oversized patterns are correctly drawn
     17        into the pattern tile scaled down and then are scaled back up when drawn to the screen.
     18
     19        * platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png:
     20        * platform/mac/svg/custom/pattern-excessive-malloc-expected.txt:
     21        * platform/qt/svg/custom/pattern-excessive-malloc-expected.txt:
     22        * svg/custom/pattern-excessive-malloc-expected.txt:
     23        * svg/custom/pattern-excessive-malloc.svg:
     24        * svg/custom/oversized-pattern-scale-expected.png: Added.
     25        * svg/custom/oversized-pattern-scale-expected.txt: Added.
     26        * svg/custom/oversized-pattern-scale.svg: Added.
     27        * svg/custom/transformed-pattern-clamp-svg-root.svg: Added.
     28        * svg/custom/transformed-pattern-clamp-svg-root-expected.png: Added.
     29        * svg/custom/transformed-pattern-clamp-svg-root-expected.txt: Added.
     30
    1312011-09-27  Dan Bernstein  <mitz@apple.com>
    232
  • trunk/LayoutTests/platform/mac/svg/custom/pattern-excessive-malloc-expected.txt

    r69386 r96155  
    55    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
    66      RenderSVGResourcePattern {pattern} [id="pattern"] [patternUnits=userSpaceOnUse] [patternContentUnits=userSpaceOnUse]
    7         RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=99999997952.00] [height=99999997952.00]
     7        RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=1000000000.00] [height=1000000000.00]
    88    RenderSVGPath {rect} at (10,300) size 100x100 [fill={[type=PATTERN] [id="pattern"]}] [x=10.00] [y=300.00] [width=100.00] [height=100.00]
  • trunk/LayoutTests/platform/qt/svg/custom/pattern-excessive-malloc-expected.txt

    r69388 r96155  
    55    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
    66      RenderSVGResourcePattern {pattern} [id="pattern"] [patternUnits=userSpaceOnUse] [patternContentUnits=userSpaceOnUse]
    7         RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=99999997952.00] [height=99999997952.00]
     7        RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=1000000000.00] [height=1000000000.00]
    88    RenderSVGPath {rect} at (10,300) size 100x100 [fill={[type=PATTERN] [id="pattern"]}] [x=10.00] [y=300.00] [width=100.00] [height=100.00]
  • trunk/LayoutTests/svg/custom/pattern-excessive-malloc-expected.txt

    r69280 r96155  
    55    RenderSVGHiddenContainer {defs} at (0,0) size 0x0
    66      RenderSVGResourcePattern {pattern} [id="pattern"] [patternUnits=userSpaceOnUse] [patternContentUnits=userSpaceOnUse]
    7         RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [data="M0.00,0.00 L99999997952.00,0.00 L99999997952.00,99999997952.00 L0.00,99999997952.00 Z"]
    8     RenderSVGPath {rect} at (10,300) size 100x100 [fill={[type=PATTERN] [id="pattern"]}] [data="M10.00,300.00 L110.00,300.00 L110.00,400.00 L10.00,400.00 Z"]
     7        RenderSVGPath {rect} at (0,0) size 800x600 [fill={[type=SOLID] [color=#FF0000]}] [x=0.00] [y=0.00] [width=1000000000.00] [height=1000000000.00]
     8    RenderSVGPath {rect} at (10,300) size 100x100 [fill={[type=PATTERN] [id="pattern"]}] [x=10.00] [y=300.00] [width=100.00] [height=100.00]
  • trunk/LayoutTests/svg/custom/pattern-excessive-malloc.svg

    r54560 r96155  
    22<svg xmlns="http://www.w3.org/2000/svg">
    33<defs>
    4 <pattern id="pattern" width="100000000000" height="100000000000" patternUnits="userSpaceOnUse">
    5 <rect x="0" y="0" width="100000000000" height="100000000000" fill="red" style="stroke:none" />
     4<pattern id="pattern" width="1000000000" height="1000000000" patternUnits="userSpaceOnUse">
     5<rect x="0" y="0" width="1000000000" height="1000000000" fill="red" style="stroke:none" />
    66</pattern>
    77</defs>
  • trunk/Source/WebCore/ChangeLog

    r96154 r96155  
     12011-09-27  Tim Horton  <timothy_horton@apple.com>
     2
     3        REGRESSION(65665): Pattern size being clamped to SVG size can prevent transformed elements from being fully covered by userSpaceOnUse patterns
     4        https://bugs.webkit.org/show_bug.cgi?id=67700
     5        <rdar://problem/10125102>
     6
     7        Reviewed by Darin Adler.
     8
     9        Clamp all resources to the same size, 4096x4096 (arbitrarily chosen), instead of to the size
     10        of the <svg> element. This fixes the case where a transformed element displays part of a resource
     11        outside of the size of the <svg> element.
     12
     13        When drawing an oversized pattern into its tile image, scale the content down to fit. When drawing
     14        the tile image to the screen, scale it back up to fit the expected area. This will cause pixelation
     15        when patterns are over the 4k limit.
     16
     17        Tests: svg/custom/transformed-pattern-clamp-svg-root.svg, svg/custom/oversized-pattern-scale.svg
     18
     19        * rendering/svg/RenderSVGResourceClipper.cpp:
     20        (WebCore::RenderSVGResourceClipper::applyClippingToContext):
     21        * rendering/svg/RenderSVGResourceGradient.cpp:
     22        (WebCore::createMaskAndSwapContextForTextGradient):
     23        (WebCore::clipToTextMask):
     24        * rendering/svg/RenderSVGResourceMasker.cpp:
     25        (WebCore::RenderSVGResourceMasker::applyResource):
     26        * rendering/svg/RenderSVGResourcePattern.cpp:
     27        (WebCore::RenderSVGResourcePattern::applyResource):
     28        (WebCore::RenderSVGResourcePattern::createTileImage):
     29        * rendering/svg/RenderSVGResourcePattern.h:
     30        * rendering/svg/SVGImageBufferTools.cpp:
     31        (WebCore::SVGImageBufferTools::clampedAbsoluteTargetRect):
     32        * rendering/svg/SVGImageBufferTools.h:
     33
    1342011-09-27  Dan Bernstein  <mitz@apple.com>
    235
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp

    r95901 r96155  
    174174
    175175    FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect);
    176     FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(object, absoluteTargetRect);
     176    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
    177177
    178178    if (shouldCreateClipData && !clampedAbsoluteTargetRect.isEmpty()) {
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp

    r90560 r96155  
    8787
    8888    FloatRect absoluteTargetRect = absoluteTransform.mapRect(textRootBlock->repaintRectInLocalCoordinates());
    89     FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(textRootBlock, absoluteTargetRect);
     89    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
    9090    if (clampedAbsoluteTargetRect.isEmpty())
    9191        return false;
     
    124124
    125125    FloatRect absoluteTargetRect = absoluteTransform.mapRect(targetRect);
    126     FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(textRootBlock, absoluteTargetRect);
     126    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
    127127
    128128    SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, clampedAbsoluteTargetRect, imageBuffer);
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp

    r95901 r96155  
    100100
    101101    FloatRect absoluteTargetRect = absoluteTransform.mapRect(object->repaintRectInLocalCoordinates());
    102     FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(object, absoluteTargetRect);
     102    FloatRect clampedAbsoluteTargetRect = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTargetRect);
    103103
    104104    if (!maskerData->maskImage && !clampedAbsoluteTargetRect.isEmpty()) {
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp

    r94338 r96155  
    121121        SVGImageBufferTools::clear2DRotation(absoluteTransformIgnoringRotation);
    122122        FloatRect absoluteTileBoundaries = absoluteTransformIgnoringRotation.mapRect(tileBoundaries);
     123        FloatRect clampedAbsoluteTileBoundaries;
    123124
    124125        // Build tile image.
    125         OwnPtr<ImageBuffer> tileImage = createTileImage(object, m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform);
     126        OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
    126127        if (!tileImage)
    127128            return false;
     
    138139        // Compute pattern space transformation.
    139140        patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y());
    140         patternData->transform.scale(tileBoundaries.width() / absoluteTileBoundaries.width(), tileBoundaries.height() / absoluteTileBoundaries.height());
     141        patternData->transform.scale(tileBoundaries.width() / clampedAbsoluteTileBoundaries.width(), tileBoundaries.height() / clampedAbsoluteTileBoundaries.height());
    141142
    142143        AffineTransform patternTransform = m_attributes.patternTransform();
     
    242243}
    243244
    244 PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(RenderObject* object,
    245                                                                   const PatternAttributes& attributes,
     245PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes,
    246246                                                                  const FloatRect& tileBoundaries,
    247247                                                                  const FloatRect& absoluteTileBoundaries,
    248                                                                   const AffineTransform& tileImageTransform) const
    249 {
    250     ASSERT(object);
    251 
    252     // Clamp tile image size against SVG viewport size, as last resort, to avoid allocating huge image buffers.
    253     FloatRect contentBoxRect = SVGRenderSupport::findTreeRootObject(object)->contentBoxRect();
    254 
    255     FloatRect clampedAbsoluteTileBoundaries = absoluteTileBoundaries;
    256     if (clampedAbsoluteTileBoundaries.width() > contentBoxRect.width())
    257         clampedAbsoluteTileBoundaries.setWidth(contentBoxRect.width());
    258 
    259     if (clampedAbsoluteTileBoundaries.height() > contentBoxRect.height())
    260         clampedAbsoluteTileBoundaries.setHeight(contentBoxRect.height());
     248                                                                  const AffineTransform& tileImageTransform,
     249                                                                  FloatRect& clampedAbsoluteTileBoundaries) const
     250{
     251    clampedAbsoluteTileBoundaries = SVGImageBufferTools::clampedAbsoluteTargetRect(absoluteTileBoundaries);
    261252
    262253    OwnPtr<ImageBuffer> tileImage;
     
    269260
    270261    // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
    271     tileImageContext->scale(FloatSize(absoluteTileBoundaries.width() / tileBoundaries.width(),
    272                                       absoluteTileBoundaries.height() / tileBoundaries.height()));
     262    tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
     263                                      clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()));
    273264
    274265    // Apply tile image transformations.
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.h

    r75350 r96155  
    6262    bool buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement*, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
    6363
    64     PassOwnPtr<ImageBuffer> createTileImage(RenderObject*, const PatternAttributes&, const FloatRect& tileBoundaries,
    65                                             const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform) const;
     64    PassOwnPtr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries,
     65                                            const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform,
     66                                            FloatRect& clampedAbsoluteTileBoundaries) const;
    6667
    6768    bool m_shouldCollectPatternAttributes : 1;
  • trunk/Source/WebCore/rendering/svg/SVGImageBufferTools.cpp

    r95901 r96155  
    2828#include "RenderSVGContainer.h"
    2929#include "RenderSVGRoot.h"
     30
     31static float kMaxImageBufferSize = 4096;
    3032
    3133namespace WebCore {
     
    114116}
    115117
    116 FloatRect SVGImageBufferTools::clampedAbsoluteTargetRectForRenderer(const RenderObject* renderer, const FloatRect& absoluteTargetRect)
     118FloatRect SVGImageBufferTools::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
    117119{
    118     ASSERT(renderer);
     120    FloatRect clampedAbsoluteTargetRect = absoluteTargetRect;
    119121
    120     const RenderSVGRoot* svgRoot = SVGRenderSupport::findTreeRootObject(renderer);
    121     FloatRect clampedAbsoluteTargetRect = absoluteTargetRect;
    122     clampedAbsoluteTargetRect.intersect(svgRoot->frameRect());
     122    if (clampedAbsoluteTargetRect.width() > kMaxImageBufferSize)
     123        clampedAbsoluteTargetRect.setWidth(kMaxImageBufferSize);
     124
     125    if (clampedAbsoluteTargetRect.height() > kMaxImageBufferSize)
     126        clampedAbsoluteTargetRect.setHeight(kMaxImageBufferSize);
     127
    123128    return clampedAbsoluteTargetRect;
    124129}
  • trunk/Source/WebCore/rendering/svg/SVGImageBufferTools.h

    r95901 r96155  
    4141
    4242    static void calculateTransformationToOutermostSVGCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
    43     static FloatRect clampedAbsoluteTargetRectForRenderer(const RenderObject*, const FloatRect& absoluteTargetRect);
     43    static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
    4444    static IntSize roundedImageBufferSize(const FloatSize&);
    4545    static void clear2DRotation(AffineTransform&);
Note: See TracChangeset for help on using the changeset viewer.