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/gm/testimagefilters.cpp b/gm/testimagefilters.cpp
index e484e1b..fc71d30 100644
--- a/gm/testimagefilters.cpp
+++ b/gm/testimagefilters.cpp
@@ -10,6 +10,8 @@
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkShader.h"
+
+#include "SkBlurImageFilter.h"
#include "SkTestImageFilters.h"
#define FILTER_WIDTH SkIntToScalar(150)
@@ -24,13 +26,17 @@
return new SkColorFilterImageFilter(cf);
}
static SkImageFilter* make3() {
+ return new SkBlurImageFilter(8, 0);
+}
+
+static SkImageFilter* make4() {
SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
SkImageFilter* inner = new SkDownSampleImageFilter(SK_Scalar1 / 5);
SkAutoUnref aur0(outer);
SkAutoUnref aur1(inner);
return new SkComposeImageFilter(outer, inner);
}
-static SkImageFilter* make4() {
+static SkImageFilter* make5() {
SkImageFilter* first = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
SkImageFilter* second = new SkDownSampleImageFilter(SK_Scalar1 / 5);
SkAutoUnref aur0(first);
@@ -38,20 +44,37 @@
return new SkMergeImageFilter(first, second);
}
-static SkImageFilter* make5() {
+static SkImageFilter* make6() {
SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
SkImageFilter* inner = new SkDownSampleImageFilter(SK_Scalar1 / 5);
SkAutoUnref aur0(outer);
SkAutoUnref aur1(inner);
SkImageFilter* compose = new SkComposeImageFilter(outer, inner);
SkAutoUnref aur2(compose);
-
+
SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
SkXfermode::kSrcIn_Mode);
SkAutoUnref aur3(cf);
SkImageFilter* blue = new SkColorFilterImageFilter(cf);
SkAutoUnref aur4(blue);
+
+ return new SkMergeImageFilter(compose, blue);
+}
+static SkImageFilter* make7() {
+ SkImageFilter* outer = new SkOffsetImageFilter(SkIntToScalar(16), SkIntToScalar(16));
+ SkImageFilter* inner = make3();
+ SkAutoUnref aur0(outer);
+ SkAutoUnref aur1(inner);
+ SkImageFilter* compose = new SkComposeImageFilter(outer, inner);
+ SkAutoUnref aur2(compose);
+
+ SkColorFilter* cf = SkColorFilter::CreateModeFilter(0x880000FF,
+ SkXfermode::kSrcIn_Mode);
+ SkAutoUnref aur3(cf);
+ SkImageFilter* blue = new SkColorFilterImageFilter(cf);
+ SkAutoUnref aur4(blue);
+
return new SkMergeImageFilter(compose, blue);
}
@@ -59,7 +82,7 @@
SkPaint p;
p.setAntiAlias(true);
SkRect r = SkRect::MakeWH(FILTER_WIDTH, FILTER_HEIGHT);
- r.inset(SK_Scalar1, SK_Scalar1);
+ r.inset(SK_Scalar1 * 12, SK_Scalar1 * 12);
p.setColor(SK_ColorRED);
canvas->drawOval(r, p);
}
@@ -74,11 +97,13 @@
return SkString("testimagefilters");
}
- virtual SkISize onISize() { return SkISize::Make(640, 480); }
+ virtual SkISize onISize() { return SkISize::Make(700, 460); }
virtual void onDraw(SkCanvas* canvas) {
+// this->drawSizeBounds(canvas, 0xFFCCCCCC);
+
static SkImageFilter* (*gFilterProc[])() = {
- make0, make1, make2, make3, make4, make5
+ make0, make1, make2, make3, make4, make5, make6, make7
};
const SkRect bounds = SkRect::MakeWH(FILTER_WIDTH, FILTER_HEIGHT);
@@ -86,20 +111,21 @@
const SkScalar dx = bounds.width() * 8 / 7;
const SkScalar dy = bounds.height() * 8 / 7;
- for (size_t i = 0; i < SK_ARRAY_COUNT(gFilterProc); ++i) {
- int ix = i % 3;
- int iy = i / 3;
+ canvas->translate(SkIntToScalar(8), SkIntToScalar(8));
- SkPaint paint;
- paint.setImageFilter(gFilterProc[i]())->unref();
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gFilterProc); ++i) {
+ int ix = i % 4;
+ int iy = i / 4;
SkAutoCanvasRestore acr(canvas, true);
canvas->translate(ix * dx, iy * dy);
SkPaint p;
- p.setColor(0xFFCCCCCC);
+ p.setStyle(SkPaint::kStroke_Style);
canvas->drawRect(bounds, p);
+ SkPaint paint;
+ paint.setImageFilter(gFilterProc[i]())->unref();
canvas->saveLayer(&bounds, &paint);
draw0(canvas);
}
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index f817c65..8c351f9 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -309,6 +309,15 @@
virtual void lockPixels();
virtual void unlockPixels();
+ /**
+ * Override and return true for filters that the device handles
+ * intrinsically. Returning false means call the filter.
+ * Default impl returns false.
+ */
+ virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset);
+
// This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if
// either is identical to kNative_Premul_Config8888. Otherwise, -1.
static const SkCanvas::Config8888 kPMColorAlias;
@@ -319,6 +328,7 @@
friend class SkDraw;
friend class SkDrawIter;
friend class SkDeviceFilteredPaint;
+ friend class DeviceImageFilterProxy;
// just called by SkCanvas when built as a layer
void setOrigin(int x, int y) { fOrigin.set(x, y); }
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 1858791..1bb723f 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -11,6 +11,7 @@
#include "SkFlattenable.h"
class SkBitmap;
+class SkDevice;
class SkMatrix;
struct SkPoint;
@@ -37,6 +38,16 @@
*/
class SK_API SkImageFilter : public SkFlattenable {
public:
+ class Proxy {
+ public:
+ virtual SkDevice* createDevice(int width, int height) = 0;
+
+ // returns true if the proxy handled the filter itself. if this returns
+ // false then the filter's code will be called.
+ virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) = 0;
+ };
/**
* Request a new (result) image to be created from the src image.
@@ -51,7 +62,7 @@
* If the result image cannot be created, return false, in which case both
* the result and offset parameters will be ignored by the caller.
*/
- bool filterImage(const SkBitmap& src, const SkMatrix& ctm,
+ bool filterImage(Proxy*, const SkBitmap& src, const SkMatrix& ctm,
SkBitmap* result, SkIPoint* offset);
/**
@@ -73,7 +84,7 @@
explicit SkImageFilter(SkFlattenableReadBuffer& rb) : INHERITED(rb) {}
// Default impl returns false
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* offset);
// Default impl copies src into dst and returns true
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
diff --git a/include/effects/SkBlurImageFilter.h b/include/effects/SkBlurImageFilter.h
index 2139b2f..4c9798b 100644
--- a/include/effects/SkBlurImageFilter.h
+++ b/include/effects/SkBlurImageFilter.h
@@ -14,20 +14,23 @@
class SK_API SkBlurImageFilter : public SkImageFilter {
public:
SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY);
- virtual bool asABlur(SkSize* sigma) const;
+
+ virtual bool asABlur(SkSize* sigma) const SK_OVERRIDE;
+
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW_ARGS(SkBlurImageFilter, (buffer));
}
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
- SkBitmap* result, SkIPoint* offset);
-
SK_DECLARE_FLATTENABLE_REGISTRAR()
protected:
explicit SkBlurImageFilter(SkFlattenableReadBuffer& buffer);
- virtual void flatten(SkFlattenableWriteBuffer& buffer);
- virtual Factory getFactory() { return CreateProc; }
+
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+ virtual void flatten(SkFlattenableWriteBuffer& buffer) SK_OVERRIDE;
+ virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
+
private:
SkSize fSigma;
typedef SkImageFilter INHERITED;
diff --git a/include/effects/SkTestImageFilters.h b/include/effects/SkTestImageFilters.h
index 4ec697e..db020ad 100755
--- a/include/effects/SkTestImageFilters.h
+++ b/include/effects/SkTestImageFilters.h
@@ -17,7 +17,7 @@
protected:
SkOffsetImageFilter(SkFlattenableReadBuffer& buffer);
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
// overrides from SkFlattenable
@@ -47,7 +47,7 @@
protected:
SkComposeImageFilter(SkFlattenableReadBuffer& buffer);
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
// overrides from SkFlattenable
@@ -78,7 +78,7 @@
protected:
SkMergeImageFilter(SkFlattenableReadBuffer& buffer);
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) SK_OVERRIDE;
// overrides from SkFlattenable
@@ -116,7 +116,7 @@
protected:
SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer);
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
// overrides from SkFlattenable
virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
@@ -142,7 +142,7 @@
protected:
SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer);
- virtual bool onFilterImage(const SkBitmap& src, const SkMatrix&,
+ virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
// overrides from SkFlattenable
virtual void flatten(SkFlattenableWriteBuffer&) SK_OVERRIDE;
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 6bafa94..6c4285e 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -110,6 +110,10 @@
*/
virtual void makeRenderTargetCurrent();
+ virtual bool filterImage(SkImageFilter*, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
+
protected:
typedef GrContext::TextureCacheEntry TexCache;
enum TexType {
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
}
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 4cad466..578d0c8 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -101,6 +101,12 @@
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::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 eeb8669..f7b3ae3 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1982,11 +1982,18 @@
//////////// 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 @@
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;
}
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 490a5b6..1446e92 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -133,12 +133,18 @@
}
}
-bool SkBlurImageFilter::onFilterImage(const SkBitmap& src, const SkMatrix&,
+bool SkBlurImageFilter::onFilterImage(Proxy*,
+ const SkBitmap& src, const SkMatrix&,
SkBitmap* dst, SkIPoint*) {
if (src.config() != SkBitmap::kARGB_8888_Config) {
return false;
}
+ SkAutoLockPixels alp(src);
+ if (!src.getPixels()) {
+ return false;
+ }
+
dst->setConfig(src.config(), src.width(), src.height());
dst->allocPixels();
int kernelSizeX, kernelSizeX3, lowOffsetX, highOffsetX;
diff --git a/src/effects/SkTestImageFilters.cpp b/src/effects/SkTestImageFilters.cpp
index c974365..a772f64 100755
--- a/src/effects/SkTestImageFilters.cpp
+++ b/src/effects/SkTestImageFilters.cpp
@@ -1,7 +1,15 @@
#include "SkTestImageFilters.h"
#include "SkCanvas.h"
+#include "SkDevice.h"
-bool SkOffsetImageFilter::onFilterImage(const SkBitmap& src,
+class OwnDeviceCanvas : public SkCanvas {
+public:
+ OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) {
+ SkSafeUnref(device);
+ }
+};
+
+bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* loc) {
@@ -46,7 +54,8 @@
SkSafeUnref(fOuter);
}
-bool SkComposeImageFilter::onFilterImage(const SkBitmap& src,
+bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
+ const SkBitmap& src,
const SkMatrix& ctm,
SkBitmap* result,
SkIPoint* loc) {
@@ -55,12 +64,12 @@
}
if (!fOuter || !fInner) {
- return (fOuter ? fOuter : fInner)->filterImage(src, ctm, result, loc);
+ return (fOuter ? fOuter : fInner)->filterImage(proxy, src, ctm, result, loc);
}
SkBitmap tmp;
- return fInner->filterImage(src, ctm, &tmp, loc) &&
- fOuter->filterImage(tmp, ctm, result, loc);
+ return fInner->filterImage(proxy, src, ctm, &tmp, loc) &&
+ fOuter->filterImage(proxy, tmp, ctm, result, loc);
}
bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
@@ -186,7 +195,8 @@
return true;
}
-bool SkMergeImageFilter::onFilterImage(const SkBitmap& src, const SkMatrix& ctm,
+bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
+ const SkMatrix& ctm,
SkBitmap* result, SkIPoint* loc) {
if (fCount < 1) {
return false;
@@ -202,12 +212,11 @@
const int x0 = bounds.left();
const int y0 = bounds.top();
- SkBitmap dst;
- dst.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
- dst.allocPixels();
- dst.eraseColor(0);
-
- SkCanvas canvas(dst);
+ SkDevice* dst = proxy->createDevice(bounds.width(), bounds.height());
+ if (NULL == dst) {
+ return false;
+ }
+ OwnDeviceCanvas canvas(dst);
SkPaint paint;
for (int i = 0; i < fCount; ++i) {
@@ -216,7 +225,7 @@
SkIPoint pos = *loc;
SkImageFilter* filter = fFilters[i];
if (filter) {
- if (!filter->filterImage(src, ctm, &tmp, &pos)) {
+ if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
return false;
}
srcPtr = &tmp;
@@ -233,7 +242,7 @@
}
loc->set(bounds.left(), bounds.top());
- result->swap(dst);
+ *result = dst->accessBitmap(false);
return true;
}
@@ -285,36 +294,28 @@
SkSafeUnref(fColorFilter);
}
-bool SkColorFilterImageFilter::onFilterImage(const SkBitmap& src,
+bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* loc) {
- if (SkBitmap::kARGB_8888_Config != src.config()) {
- return false;
- }
-
SkColorFilter* cf = fColorFilter;
if (NULL == cf) {
*result = src;
return true;
}
- SkAutoLockPixels alpsrc(src);
- if (!src.readyToDraw()) {
+ SkDevice* dev = proxy->createDevice(src.width(), src.height());
+ if (NULL == dev) {
return false;
}
+ OwnDeviceCanvas canvas(dev);
+ SkPaint paint;
- SkBitmap dst(src);
- dst.allocPixels();
- if (!dst.readyToDraw()) {
- return false;
- }
-
- for (int y = 0; y < src.height(); ++y) {
- cf->filterSpan(src.getAddr32(0, y), src.width(), dst.getAddr32(0, y));
- }
-
- result->swap(dst);
+ paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+ paint.setColorFilter(fColorFilter);
+ canvas.drawSprite(src, 0, 0, &paint);
+
+ *result = dev->accessBitmap(false);
return true;
}
@@ -334,7 +335,7 @@
///////////////////////////////////////////////////////////////////////////////
-bool SkDownSampleImageFilter::onFilterImage(const SkBitmap& src,
+bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
const SkMatrix& matrix,
SkBitmap* result, SkIPoint*) {
SkScalar scale = fScale;
@@ -350,32 +351,36 @@
if (dstH < 1) {
dstH = 1;
}
-
- SkBitmap dst;
- dst.setConfig(SkBitmap::kARGB_8888_Config, dstW, dstH);
- dst.allocPixels();
- dst.eraseColor(0);
-
+
+ SkBitmap tmp;
+
// downsample
{
+ SkDevice* dev = proxy->createDevice(dstW, dstH);
+ if (NULL == dev) {
+ return false;
+ }
+ OwnDeviceCanvas canvas(dev);
SkPaint paint;
+
paint.setFilterBitmap(true);
-
- SkCanvas canvas(dst);
canvas.scale(scale, scale);
canvas.drawBitmap(src, 0, 0, &paint);
+ tmp = dev->accessBitmap(false);
}
-
- result->setConfig(SkBitmap::kARGB_8888_Config, src.width(), src.height());
- result->allocPixels();
- result->eraseColor(0);
-
+
// upscale
{
- SkRect r = SkRect::MakeWH(SkIntToScalar(result->width()),
- SkIntToScalar(result->height()));
- SkCanvas canvas(*result);
- canvas.drawBitmapRect(dst, NULL, r, NULL);
+ SkDevice* dev = proxy->createDevice(src.width(), src.height());
+ if (NULL == dev) {
+ return false;
+ }
+ OwnDeviceCanvas canvas(dev);
+
+ SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()),
+ SkIntToScalar(src.height()));
+ canvas.drawBitmapRect(tmp, NULL, r, NULL);
+ *result = dev->accessBitmap(false);
}
return true;
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 709aaba..42a76e4 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1461,6 +1461,9 @@
return;
}
+ int w = bitmap.width();
+ int h = bitmap.height();
+
GrPaint grPaint;
if(!this->skPaint2GrPaintNoShader(paint, true, &grPaint, false)) {
return;
@@ -1474,14 +1477,29 @@
sampler->reset();
SkAutoCachedTexture act(this, bitmap, sampler, &texture);
- grPaint.setTexture(kBitmapTextureIdx, texture);
+ SkImageFilter* imageFilter = paint.getImageFilter();
+ SkSize blurSize;
+ if (NULL != imageFilter && imageFilter->asABlur(&blurSize)) {
+ GrAutoScratchTexture temp1, temp2;
+ GrTexture* blurTexture = gaussianBlur(fContext,
+ texture, &temp1, &temp2,
+ GrRect::MakeWH(w, h),
+ blurSize.width(),
+ blurSize.height());
+ texture = blurTexture;
+ grPaint.setTexture(kBitmapTextureIdx, texture);
+ GrPrintf("%d %d | %d %d\n", w, h, texture->width(), texture->height());
+ } else {
+ grPaint.setTexture(kBitmapTextureIdx, texture);
+ }
fContext->drawRectToRect(grPaint,
- GrRect::MakeXYWH(GrIntToScalar(left),
- GrIntToScalar(top),
- GrIntToScalar(bitmap.width()),
- GrIntToScalar(bitmap.height())),
- GrRect::MakeWH(GR_Scalar1, GR_Scalar1));
+ GrRect::MakeXYWH(GrIntToScalar(left),
+ GrIntToScalar(top),
+ GrIntToScalar(w),
+ GrIntToScalar(h)),
+ GrRect::MakeWH(GR_Scalar1 * w / texture->width(),
+ GR_Scalar1 * h / texture->height()));
}
void SkGpuDevice::drawDevice(const SkDraw& draw, SkDevice* dev,
@@ -1509,18 +1527,7 @@
GrIntToScalar(y),
GrIntToScalar(w),
GrIntToScalar(h));
- SkImageFilter* imageFilter = paint.getImageFilter();
- SkSize size;
- if (NULL != imageFilter && imageFilter->asABlur(&size)) {
- GrAutoScratchTexture temp1, temp2;
- GrTexture* blurTexture = gaussianBlur(fContext,
- devTex, &temp1, &temp2,
- GrRect::MakeWH(w, h),
- size.width(),
- size.height());
- grPaint.setTexture(kBitmapTextureIdx, blurTexture);
- devTex = blurTexture;
- }
+
// The device being drawn may not fill up its texture (saveLayer uses
// the approximate ).
GrRect srcRect = GrRect::MakeWH(GR_Scalar1 * w / devTex->width(),
@@ -1529,6 +1536,29 @@
fContext->drawRectToRect(grPaint, dstRect, srcRect);
}
+bool SkGpuDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
+ const SkMatrix& ctm,
+ SkBitmap* result, SkIPoint* offset) {
+ SkSize size;
+ if (!filter->asABlur(&size)) {
+ return false;
+ }
+ SkDevice* dev = this->createCompatibleDevice(SkBitmap::kARGB_8888_Config,
+ src.width(),
+ src.height(),
+ false);
+ if (NULL == dev) {
+ return false;
+ }
+ SkAutoUnref aur(dev);
+ SkCanvas canvas(dev);
+ SkPaint paint;
+ paint.setImageFilter(filter);
+ canvas.drawSprite(src, 0, 0, &paint);
+ *result = dev->accessBitmap(false);
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
// must be in SkCanvas::VertexMode order