add filterImage() entry-point to SkDevice, to allow it to specialize on subclasses
of SkImageFilter. If that returns false, then the filter itself is invoked.
git-svn-id: http://skia.googlecode.com/svn/trunk@2977 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 353c92c..e9fcb57 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -735,8 +735,14 @@
bool isOpaque;
SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque);
- SkDevice* device = this->createLayerDevice(config, ir.width(), ir.height(),
- isOpaque);
+ SkDevice* device;
+ if (paint && paint->getImageFilter()) {
+ device = this->createCompatibleDevice(config, ir.width(), ir.height(),
+ isOpaque);
+ } else {
+ device = this->createLayerDevice(config, ir.width(), ir.height(),
+ isOpaque);
+ }
if (NULL == device) {
SkDebugf("Unable to create device for layer.");
return count;
@@ -855,6 +861,34 @@
this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
}
+#include "SkImageFilter.h"
+
+class DeviceImageFilterProxy : public SkImageFilter::Proxy {
+public:
+ DeviceImageFilterProxy(SkDevice* device) : fDevice(device) {}
+
+ virtual SkDevice* createDevice(int w, int h) SK_OVERRIDE;
+ virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
+private:
+ SkDevice* fDevice;
+};
+
+SkDevice* DeviceImageFilterProxy::createDevice(int w, int h) {
+ return fDevice->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
+ w, h, false);
+}
+
+bool DeviceImageFilterProxy::filterImage(SkImageFilter* filter,
+ const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result,
+ SkIPoint* offset) {
+ return fDevice->filterImage(filter, src, ctm, result, offset);
+}
+
void SkCanvas::drawDevice(SkDevice* device, int x, int y,
const SkPaint* paint) {
SkPaint tmp;
@@ -865,8 +899,21 @@
LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type)
while (iter.next()) {
- iter.fDevice->drawDevice(iter, device, x - iter.getX(), y - iter.getY(),
- looper.paint());
+ paint = &looper.paint();
+ SkImageFilter* filter = paint->getImageFilter();
+ SkIPoint pos = { x - iter.getX(), y - iter.getY() };
+ if (filter) {
+ DeviceImageFilterProxy proxy(device);
+ SkBitmap dst;
+ const SkBitmap& src = device->accessBitmap(false);
+ if (filter->filterImage(&proxy, src, *iter.fMatrix, &dst, &pos)) {
+ SkPaint tmp(*paint);
+ tmp.setImageFilter(NULL);
+ iter.fDevice->drawSprite(iter, dst, pos.x(), pos.y(), tmp);
+ }
+ } else {
+ iter.fDevice->drawDevice(iter, device, pos.x(), pos.y(), *paint);
+ }
}
LOOPER_END
}