Commit 2166ed8c authored by eric@webkit.org's avatar eric@webkit.org

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.

git-svn-id: svn://svn.chromium.org/blink/trunk@54203 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent fc8a2755
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.
2010-02-01 Daniel Bates <dbates@webkit.org>
Reviewed by Adam Barth.
......
......@@ -35,12 +35,32 @@ Pattern::Pattern(Image* image, bool repeatX, bool repeatY)
: m_tileImage(image)
, m_repeatX(repeatX)
, m_repeatY(repeatY)
#if PLATFORM(SKIA)
, m_pattern(0)
#endif
{
ASSERT(image);
}
Pattern::~Pattern()
{
platformDestroy();
}
void Pattern::setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation)
{
m_patternSpaceTransformation = patternSpaceTransformation;
setPlatformPatternSpaceTransform();
}
#if !PLATFORM(SKIA)
void Pattern::platformDestroy()
{
}
void Pattern::setPlatformPatternSpaceTransform()
{
}
#endif
}
......@@ -74,9 +74,16 @@ namespace WebCore {
Image* tileImage() const { return m_tileImage.get(); }
void platformDestroy();
// Pattern space is an abstract space that maps to the default user space by the transformation 'userSpaceTransformation'
#if PLATFORM(SKIA)
PlatformPatternPtr platformPattern(const TransformationMatrix& userSpaceTransformation);
#else
PlatformPatternPtr createPlatformPattern(const TransformationMatrix& userSpaceTransformation) const;
void setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation) { m_patternSpaceTransformation = patternSpaceTransformation; }
#endif
void setPatternSpaceTransform(const TransformationMatrix& patternSpaceTransformation);
void setPlatformPatternSpaceTransform();
private:
Pattern(Image*, bool repeatX, bool repeatY);
......@@ -85,6 +92,7 @@ namespace WebCore {
bool m_repeatX;
bool m_repeatY;
TransformationMatrix m_patternSpaceTransformation;
PlatformPatternPtr m_pattern;
};
} //namespace
......
......@@ -997,9 +997,7 @@ void GraphicsContext::setPlatformFillPattern(Pattern* pattern)
if (paintingDisabled())
return;
SkShader* pat = pattern->createPlatformPattern(getCTM());
platformContext()->setFillShader(pat);
pat->safeUnref();
platformContext()->setFillShader(pattern->platformPattern(getCTM()));
}
void GraphicsContext::setPlatformShadow(const IntSize& size,
......@@ -1084,9 +1082,7 @@ void GraphicsContext::setPlatformStrokePattern(Pattern* pattern)
if (paintingDisabled())
return;
SkShader* pat = pattern->createPlatformPattern(getCTM());
platformContext()->setStrokeShader(pat);
pat->safeUnref();
platformContext()->setStrokeShader(pattern->platformPattern(getCTM()));
}
void GraphicsContext::setPlatformTextDrawingMode(int mode)
......
......@@ -40,8 +40,17 @@
namespace WebCore {
PlatformPatternPtr Pattern::createPlatformPattern(const TransformationMatrix& patternTransform) const
void Pattern::platformDestroy()
{
m_pattern->safeUnref();
m_pattern = 0;
}
PlatformPatternPtr Pattern::platformPattern(const TransformationMatrix& patternTransform)
{
if (m_pattern)
return m_pattern;
// Note: patternTransform is ignored since it seems to be applied elsewhere
// (when the pattern is used?). Applying it to the pattern (i.e.
// shader->setLocalMatrix) results in a double transformation. This can be
......@@ -53,31 +62,42 @@ PlatformPatternPtr Pattern::createPlatformPattern(const TransformationMatrix& pa
SkBitmap* bm = m_tileImage->nativeImageForCurrentFrame();
// If we don't have a bitmap, return a transparent shader.
if (!bm)
return new SkColorShader(SkColorSetARGB(0, 0, 0, 0));
m_pattern = new SkColorShader(SkColorSetARGB(0, 0, 0, 0));
if (m_repeatX && m_repeatY)
return SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
else if (m_repeatX && m_repeatY)
m_pattern = SkShader::CreateBitmapShader(*bm, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode);
// Skia does not have a "draw the tile only once" option. Clamp_TileMode
// repeats the last line of the image after drawing one tile. To avoid
// filling the space with arbitrary pixels, this workaround forces the
// image to have a line of transparent pixels on the "repeated" edge(s),
// thus causing extra space to be transparent filled.
SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
int expandW = m_repeatX ? 0 : 1;
int expandH = m_repeatY ? 0 : 1;
else {
// Create a transparent bitmap 1 pixel wider and/or taller than the
// original, then copy the orignal into it.
// FIXME: Is there a better way to pad (not scale) an image in skia?
SkBitmap bm2;
bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
bm2.allocPixels();
bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
SkCanvas canvas(bm2);
canvas.drawBitmap(*bm, 0, 0);
return SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
// Skia does not have a "draw the tile only once" option. Clamp_TileMode
// repeats the last line of the image after drawing one tile. To avoid
// filling the space with arbitrary pixels, this workaround forces the
// image to have a line of transparent pixels on the "repeated" edge(s),
// thus causing extra space to be transparent filled.
SkShader::TileMode tileModeX = m_repeatX ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
SkShader::TileMode tileModeY = m_repeatY ? SkShader::kRepeat_TileMode : SkShader::kClamp_TileMode;
int expandW = m_repeatX ? 0 : 1;
int expandH = m_repeatY ? 0 : 1;
// Create a transparent bitmap 1 pixel wider and/or taller than the
// original, then copy the orignal into it.
// FIXME: Is there a better way to pad (not scale) an image in skia?
SkBitmap bm2;
bm2.setConfig(bm->config(), bm->width() + expandW, bm->height() + expandH);
bm2.allocPixels();
bm2.eraseARGB(0x00, 0x00, 0x00, 0x00);
SkCanvas canvas(bm2);
canvas.drawBitmap(*bm, 0, 0);
m_pattern = SkShader::CreateBitmapShader(bm2, tileModeX, tileModeY);
}
m_pattern->setLocalMatrix(m_patternSpaceTransformation);
return m_pattern;
}
void Pattern::setPlatformPatternSpaceTransform()
{
if (m_pattern)
m_pattern->setLocalMatrix(m_patternSpaceTransformation);
}
} // namespace WebCore
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment