Changeset 54203 in webkit


Ignore:
Timestamp:
Feb 1, 2010 9:36:40 PM (14 years ago)
Author:
eric@webkit.org
Message:

2010-02-01 Stephen White <senorblanco@chromium.org>

Reviewed by Eric Seidel.

Fix for Pattern transformations in Chromium/Skia. This required
reworking Pattern a bit to be more like the Gradient implementation.
In particular, it now holds an m_pattern reference to the
platform-specific implementation, and passes along changes to the
m_patternSpaceTransformation, in the same way that Gradient does for
m_gradientSpaceTransformation. This is necessary since Skia creates the
platform-specific pattern (SkShader) once, rather than recreating it
on each draw.
For platforms other than Skia, m_pattern is unused, they will
continue to use the static createPlatformPattern(), and the new
notification functions are stubbed out. Other platforms can switch to
the new implementation if they so choose.

https://bugs.webkit.org/show_bug.cgi?id=24534

Covered by svg/custom/pattern-y-offset.svg,
svg/custom/pattern-cycle-detection.svg, and many more.

  • platform/graphics/Pattern.cpp: (WebCore::Pattern::Pattern): Initializer for m_pattern. (WebCore::Pattern::~Pattern): call platformDestroy(). (WebCore::Pattern::setPatternSpaceTransform): Pass along the transform via setPlatformPatternSpaceTransform(). (WebCore::Pattern::platformDestroy): (WebCore::Pattern::setPlatformPatternSpaceTransform): Stub implementations for non-skia platforms.
  • platform/graphics/Pattern.h:
  • platform/graphics/skia/GraphicsContextSkia.cpp: (WebCore::GraphicsContext::setPlatformFillPattern): (WebCore::GraphicsContext::setPlatformStrokePattern): Call platformPattern() instead of static version. Since Pattern now owns its SkShader, no need to unref here.
  • platform/graphics/skia/PatternSkia.cpp: (WebCore::Pattern::platformDestroy): Unref the SkShader on destroy. (WebCore::Pattern::platformPattern): Create the platform pattern (SkShader) once, and cache it. (WebCore::Pattern::setPlatformPatternSpaceTransform): Set the shader's local matrix from the m_patternSpaceTransformation.
Location:
trunk/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r54202 r54203  
     12010-02-01  Stephen White  <senorblanco@chromium.org>
     2
     3        Reviewed by Eric Seidel.
     4
     5        Fix for Pattern transformations in Chromium/Skia.  This required
     6        reworking Pattern a bit to be more like the Gradient implementation.
     7        In particular, it now holds an m_pattern reference to the
     8        platform-specific implementation, and passes along changes to the
     9        m_patternSpaceTransformation, in the same way that Gradient does for
     10        m_gradientSpaceTransformation.  This is necessary since Skia creates the
     11        platform-specific pattern (SkShader) once, rather than recreating it
     12        on each draw.
     13        For platforms other than Skia, m_pattern is unused, they will
     14        continue to use the static createPlatformPattern(), and the new
     15        notification functions are stubbed out.  Other platforms can switch to
     16        the new implementation if they so choose.
     17
     18        https://bugs.webkit.org/show_bug.cgi?id=24534
     19
     20        Covered by svg/custom/pattern-y-offset.svg,
     21        svg/custom/pattern-cycle-detection.svg, and many more.
     22
     23        * platform/graphics/Pattern.cpp:
     24        (WebCore::Pattern::Pattern):
     25        Initializer for m_pattern.
     26        (WebCore::Pattern::~Pattern):
     27        call platformDestroy().
     28        (WebCore::Pattern::setPatternSpaceTransform):
     29        Pass along the transform via setPlatformPatternSpaceTransform().
     30        (WebCore::Pattern::platformDestroy):
     31        (WebCore::Pattern::setPlatformPatternSpaceTransform):
     32        Stub implementations for non-skia platforms.
     33        * platform/graphics/Pattern.h:
     34        * platform/graphics/skia/GraphicsContextSkia.cpp:
     35        (WebCore::GraphicsContext::setPlatformFillPattern):
     36        (WebCore::GraphicsContext::setPlatformStrokePattern):
     37        Call platformPattern() instead of static version.
     38        Since Pattern now owns its SkShader, no need to unref here.
     39        * platform/graphics/skia/PatternSkia.cpp:
     40        (WebCore::Pattern::platformDestroy):
     41        Unref the SkShader on destroy.
     42        (WebCore::Pattern::platformPattern):
     43        Create the platform pattern (SkShader) once, and cache it.
     44        (WebCore::Pattern::setPlatformPatternSpaceTransform):
     45        Set the shader's local matrix from the m_patternSpaceTransformation.
     46
    1472010-02-01  Daniel Bates  <dbates@webkit.org>
    248
  • trunk/WebCore/platform/graphics/Pattern.cpp

    r35732 r54203  
    3636    , m_repeatX(repeatX)
    3737    , m_repeatY(repeatY)
     38#if PLATFORM(SKIA)
     39    , m_pattern(0)
     40#endif
    3841{
    3942    ASSERT(image);
     
    4245Pattern::~Pattern()
    4346{
     47    platformDestroy();
    4448}
    4549
     50void Pattern::setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation)
     51{
     52    m_patternSpaceTransformation = patternSpaceTransformation;
     53    setPlatformPatternSpaceTransform();
    4654}
     55
     56#if !PLATFORM(SKIA)
     57void Pattern::platformDestroy()
     58{
     59}
     60
     61void Pattern::setPlatformPatternSpaceTransform()
     62{
     63}
     64#endif
     65
     66}
  • trunk/WebCore/platform/graphics/Pattern.h

    r52791 r54203  
    7575        Image* tileImage() const { return m_tileImage.get(); }
    7676
     77        void platformDestroy();
     78
    7779        // Pattern space is an abstract space that maps to the default user space by the transformation 'userSpaceTransformation'
     80#if PLATFORM(SKIA)
     81        PlatformPatternPtr platformPattern(const TransformationMatrix& userSpaceTransformation);
     82#else
    7883        PlatformPatternPtr createPlatformPattern(const TransformationMatrix& userSpaceTransformation) const;
    79         void setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation) { m_patternSpaceTransformation = patternSpaceTransformation; }
     84#endif
     85        void setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation);
     86        void setPlatformPatternSpaceTransform();
    8087
    8188    private:
     
    8693        bool m_repeatY;
    8794        TransformationMatrix m_patternSpaceTransformation;
     95        PlatformPatternPtr m_pattern;
    8896    };
    8997
  • trunk/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp

    r54137 r54203  
    998998        return;
    999999
    1000     SkShader* pat = pattern->createPlatformPattern(getCTM());
    1001     platformContext()->setFillShader(pat);
    1002     pat->safeUnref();
     1000    platformContext()->setFillShader(pattern->platformPattern(getCTM()));
    10031001}
    10041002
     
    10851083        return;
    10861084
    1087     SkShader* pat = pattern->createPlatformPattern(getCTM());
    1088     platformContext()->setStrokeShader(pat);
    1089     pat->safeUnref();
     1085    platformContext()->setStrokeShader(pattern->platformPattern(getCTM()));
    10901086}
    10911087
  • trunk/WebCore/platform/graphics/skia/PatternSkia.cpp

    r44575 r54203  
    4141namespace WebCore {
    4242
    43 PlatformPatternPtr Pattern::createPlatformPattern(const TransformationMatrix& patternTransform) const
     43void Pattern::platformDestroy()
    4444{
     45    m_pattern->safeUnref();
     46    m_pattern = 0;
     47}
     48
     49PlatformPatternPtr Pattern::platformPattern(const TransformationMatrix& patternTransform)
     50{
     51    if (m_pattern)
     52        return m_pattern;
     53
    4554    // Note: patternTransform is ignored since it seems to be applied elsewhere
    4655    // (when the pattern is used?). Applying it to the pattern (i.e.
     
    5463    // If we don't have a bitmap, return a transparent shader.
    5564    if (!bm)
    56         return new SkColorShader(SkColorSetARGB(0, 0, 0, 0));
     65        m_pattern = new SkColorShader(SkColorSetARGB(0, 0, 0, 0));
    5766
    58     if (m_repeatX && m_repeatY)
    59         return SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
     67    else if (m_repeatX && m_repeatY)
     68        m_pattern = SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
    6069
    61     // Skia does not have a "draw the tile only once" option. Clamp_TileMode
    62     // repeats the last line of the image after drawing one tile. To avoid
    63     // filling the space with arbitrary pixels, this workaround forces the
    64     // image to have a line of transparent pixels on the "repeated" edge(s),
    65     // thus causing extra space to be transparent filled.
    66     SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
    67     SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
    68     int expandW = m_repeatX ? 0 : 1;
    69     int expandH = m_repeatY ? 0 : 1;
     70    else {
    7071
    71     // Create a transparent bitmap 1 pixel wider and/or taller than the
    72     // original, then copy the orignal into it.
    73     // FIXME: Is there a better way to pad (not scale) an image in skia?
    74     SkBitmap bm2;
    75     bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
    76     bm2.allocPixels();
    77     bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
    78     SkCanvas canvas(bm2);
    79     canvas.drawBitmap(*bm, 0, 0);
    80     return SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
     72        // Skia does not have a "draw the tile only once" option. Clamp_TileMode
     73        // repeats the last line of the image after drawing one tile. To avoid
     74        // filling the space with arbitrary pixels, this workaround forces the
     75        // image to have a line of transparent pixels on the "repeated" edge(s),
     76        // thus causing extra space to be transparent filled.
     77        SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     78        SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
     79        int expandW = m_repeatX ? 0 : 1;
     80        int expandH = m_repeatY ? 0 : 1;
     81
     82        // Create a transparent bitmap 1 pixel wider and/or taller than the
     83        // original, then copy the orignal into it.
     84        // FIXME: Is there a better way to pad (not scale) an image in skia?
     85        SkBitmap bm2;
     86        bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
     87        bm2.allocPixels();
     88        bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
     89        SkCanvas canvas(bm2);
     90        canvas.drawBitmap(*bm, 0, 0);
     91        m_pattern = SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
     92    }
     93    m_pattern->setLocalMatrix(m_patternSpaceTransformation);
     94    return m_pattern;
     95}
     96
     97void Pattern::setPlatformPatternSpaceTransform()
     98{
     99    if (m_pattern)
     100        m_pattern->setLocalMatrix(m_patternSpaceTransformation);
    81101}
    82102
Note: See TracChangeset for help on using the changeset viewer.