diff options
-rw-r--r-- | gm/tileimagefilter.cpp | 10 | ||||
-rw-r--r-- | include/core/SkImageFilter.h | 11 | ||||
-rw-r--r-- | src/core/SkImageFilter.cpp | 5 | ||||
-rw-r--r-- | src/effects/SkTileImageFilter.cpp | 32 |
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); |