diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-01-05 21:15:07 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-01-05 21:15:07 +0000 |
commit | 76dd277b1fa021c42fc3acdd8d61e7dc05f9c267 (patch) | |
tree | e937ee3f7762dd64e2066ad018e1327e8648d443 /src/core | |
parent | c84547a8d3cb04f0547db282b34e26abfbe64ec3 (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.cpp | 55 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 22 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 13 |
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; } |