aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-05 21:15:07 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-01-05 21:15:07 +0000
commit76dd277b1fa021c42fc3acdd8d61e7dc05f9c267 (patch)
treee937ee3f7762dd64e2066ad018e1327e8648d443 /src/core
parentc84547a8d3cb04f0547db282b34e26abfbe64ec3 (diff)
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
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkCanvas.cpp55
-rw-r--r--src/core/SkDevice.cpp22
-rw-r--r--src/core/SkPaint.cpp13
3 files changed, 69 insertions, 21 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 353c92c6f0..e9fcb57f01 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -735,8 +735,14 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
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 @@ void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect
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 @@ void SkCanvas::drawDevice(SkDevice* device, int x, int y,
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
}
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 4cad466ed5..578d0c88eb 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -101,6 +101,12 @@ void SkDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& region,
const SkClipStack& clipStack) {
}
+bool SkDevice::filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) {
+ return false;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y,
@@ -354,20 +360,8 @@ void SkDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
void SkDevice::drawDevice(const SkDraw& draw, SkDevice* device,
int x, int y, const SkPaint& paint) {
- SkBitmap output;
- const SkBitmap* src = &device->accessBitmap(false);
- SkImageFilter* filter = paint.getImageFilter();
-
- if (filter) {
- SkIPoint loc;
- loc.set(x, y);
- if (filter->filterImage(*src, *draw.fMatrix, &output, &loc)) {
- src = &output;
- x = loc.fX;
- y = loc.fY;
- }
- }
- draw.drawSprite(*src, x, y, paint);
+ const SkBitmap& src = device->accessBitmap(false);
+ draw.drawSprite(src, x, y, paint);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index eeb8669ea2..f7b3ae35fe 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1982,11 +1982,18 @@ bool SkPaint::nothingToDraw() const {
//////////// Move these to their own file soon.
-bool SkImageFilter::filterImage(const SkBitmap& src, const SkMatrix& matrix,
+bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
+ const SkMatrix& ctm,
SkBitmap* result, SkIPoint* loc) {
+ SkASSERT(proxy);
SkASSERT(result);
SkASSERT(loc);
- return this->onFilterImage(src, matrix, result, loc);
+ /*
+ * Give the proxy first shot at the filter. If it returns false, ask
+ * the filter to do it.
+ */
+ return proxy->filterImage(this, src, ctm, result, loc) ||
+ this->onFilterImage(proxy, src, ctm, result, loc);
}
bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
@@ -1996,7 +2003,7 @@ bool SkImageFilter::filterBounds(const SkIRect& src, const SkMatrix& ctm,
return this->onFilterBounds(src, ctm, dst);
}
-bool SkImageFilter::onFilterImage(const SkBitmap& src, const SkMatrix&,
+bool SkImageFilter::onFilterImage(Proxy*, const SkBitmap&, const SkMatrix&,
SkBitmap*, SkIPoint*) {
return false;
}