aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/tileimagefilter.cpp10
-rw-r--r--include/core/SkImageFilter.h11
-rw-r--r--src/core/SkImageFilter.cpp5
-rw-r--r--src/effects/SkTileImageFilter.cpp32
4 files changed, 44 insertions, 14 deletions
diff --git a/gm/tileimagefilter.cpp b/gm/tileimagefilter.cpp
index 10086c9c17..eb0ad09f4b 100644
--- a/gm/tileimagefilter.cpp
+++ b/gm/tileimagefilter.cpp
@@ -47,6 +47,12 @@ protected:
void onDraw(SkCanvas* canvas) override {
canvas->clear(SK_ColorBLACK);
+ SkPaint red;
+ red.setColor(SK_ColorRED);
+ red.setStyle(SkPaint::kStroke_Style);
+ SkPaint blue;
+ blue.setColor(SK_ColorBLUE);
+ blue.setStyle(SkPaint::kStroke_Style);
int x = 0, y = 0;
for (size_t i = 0; i < 4; i++) {
@@ -67,6 +73,8 @@ protected:
SkPaint paint;
paint.setImageFilter(filter);
canvas->drawImage(fBitmap, 0, 0, &paint);
+ canvas->drawRect(srcRect, red);
+ canvas->drawRect(dstRect, blue);
canvas->restore();
x += image->width() + MARGIN;
if (x + image->width() > WIDTH) {
@@ -96,6 +104,8 @@ protected:
canvas->saveLayer(&dstRect, &paint);
canvas->drawImage(fBitmap, 0, 0);
canvas->restore();
+ canvas->drawRect(srcRect, red);
+ canvas->drawRect(dstRect, blue);
canvas->restore();
}
private:
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 13fe6530c7..eb5d2a1b06 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -98,11 +98,17 @@ public:
uint32_t fFlags;
};
+ enum TileUsage {
+ kPossible_TileUsage, //!< the created device may be drawn tiled
+ kNever_TileUsage, //!< the created device will never be drawn tiled
+ };
+
class Proxy {
public:
virtual ~Proxy() {}
- virtual SkBaseDevice* createDevice(int width, int height) = 0;
+ virtual SkBaseDevice* createDevice(int width, int height,
+ TileUsage usage = kNever_TileUsage) = 0;
// Returns true if the proxy handled the filter itself. If this returns
// false then the filter's code will be called.
@@ -115,7 +121,8 @@ public:
public:
DeviceProxy(SkBaseDevice* device) : fDevice(device) {}
- SkBaseDevice* createDevice(int width, int height) override;
+ SkBaseDevice* createDevice(int width, int height,
+ TileUsage usage = kNever_TileUsage) override;
// Returns true if the proxy handled the filter itself. If this returns
// false then the filter's code will be called.
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index e64cf7200a..b068644d55 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -663,9 +663,10 @@ void SkImageFilter::PurgeCache() {
///////////////////////////////////////////////////////////////////////////////////////////////////
-SkBaseDevice* SkImageFilter::DeviceProxy::createDevice(int w, int h) {
+SkBaseDevice* SkImageFilter::DeviceProxy::createDevice(int w, int h, TileUsage usage) {
SkBaseDevice::CreateInfo cinfo(SkImageInfo::MakeN32Premul(w, h),
- SkBaseDevice::kNever_TileUsage,
+ kPossible_TileUsage == usage ? SkBaseDevice::kPossible_TileUsage
+ : SkBaseDevice::kNever_TileUsage,
kUnknown_SkPixelGeometry,
false, /* preserveLCDText */
true /*forImageFilter*/);
diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp
index 8d15801387..ca4c15d419 100644
--- a/src/effects/SkTileImageFilter.cpp
+++ b/src/effects/SkTileImageFilter.cpp
@@ -54,15 +54,31 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
srcRect.roundOut(&srcIRect);
srcIRect.offset(-srcOffset);
SkBitmap subset;
- SkIRect bounds;
- source.getBounds(&bounds);
+ SkIRect srcBounds;
+ source.getBounds(&srcBounds);
- if (!srcIRect.intersect(bounds)) {
+ if (!SkIRect::Intersects(srcIRect, srcBounds)) {
offset->fX = offset->fY = 0;
return true;
- } else if (!source.extractSubset(&subset, srcIRect)) {
- return false;
}
+ if (srcBounds.contains(srcIRect)) {
+ if (!source.extractSubset(&subset, srcIRect)) {
+ return false;
+ }
+ } else {
+ SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(srcIRect.width(),
+ srcIRect.height(),
+ kPossible_TileUsage));
+ if (!device) {
+ return false;
+ }
+ SkCanvas canvas(device);
+ canvas.drawBitmap(src, SkIntToScalar(srcOffset.x()),
+ SkIntToScalar(srcOffset.y()));
+ subset = device->accessBitmap(false);
+ }
+ SkASSERT(subset.width() == srcIRect.width());
+ SkASSERT(subset.height() == srcIRect.height());
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(w, h));
if (nullptr == device.get()) {
@@ -72,12 +88,8 @@ bool SkTileImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- SkMatrix shaderMatrix;
- shaderMatrix.setTranslate(SkIntToScalar(srcOffset.fX),
- SkIntToScalar(srcOffset.fY));
SkAutoTUnref<SkShader> shader(SkShader::CreateBitmapShader(subset,
- SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode,
- &shaderMatrix));
+ SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
paint.setShader(shader);
canvas.translate(-dstRect.fLeft, -dstRect.fTop);
canvas.drawRect(dstRect, paint);