Index: src/core/SkCanvas.cpp |
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
index 1e49fe272df04a9b8af1e8afd50cb7642488c7c5..88dddf412a7ae663c1e34d343a8ddd953f8ca1dc 100644 |
--- a/src/core/SkCanvas.cpp |
+++ b/src/core/SkCanvas.cpp |
@@ -17,6 +17,8 @@ |
#include "SkDrawLooper.h" |
#include "SkErrorInternals.h" |
#include "SkImage.h" |
+#include "SkImage_Base.h" |
+#include "SkMatrixUtils.h" |
#include "SkMetaData.h" |
#include "SkNinePatchIter.h" |
#include "SkPaintPriv.h" |
@@ -592,6 +594,13 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { |
////////// macros to place around the internal draw calls ////////////////// |
+#define LOOPER_BEGIN_DRAWBITMAP(paint, skipLayerForFilter, bounds) \ |
+ this->predrawNotify(); \ |
+ AutoDrawLooper looper(this, fProps, paint, skipLayerForFilter, bounds); \ |
+ while (looper.next(SkDrawFilter::kBitmap_Type)) { \ |
+ SkDrawIter iter(this); |
+ |
+ |
#define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ |
this->predrawNotify(); \ |
AutoDrawLooper looper(this, fProps, paint, true); \ |
@@ -1404,28 +1413,8 @@ void SkCanvas::onDrawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint* |
LOOPER_BEGIN_DRAWDEVICE(*paint, SkDrawFilter::kBitmap_Type) |
while (iter.next()) { |
- paint = &looper.paint(); |
- SkImageFilter* filter = paint->getImageFilter(); |
- SkIPoint pos = { x - iter.getX(), y - iter.getY() }; |
- if (filter && !iter.fDevice->canHandleImageFilter(filter)) { |
- SkImageFilter::DeviceProxy proxy(iter.fDevice); |
- SkBitmap dst; |
- SkIPoint offset = SkIPoint::Make(0, 0); |
- SkMatrix matrix = *iter.fMatrix; |
- matrix.postTranslate(SkIntToScalar(-pos.x()), SkIntToScalar(-pos.y())); |
- const SkIRect clipBounds = bitmap.bounds(); |
- SkAutoTUnref<SkImageFilter::Cache> cache(iter.fDevice->getImageFilterCache()); |
- SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), |
- SkImageFilter::kApprox_SizeConstraint); |
- if (filter->filterImage(&proxy, bitmap, ctx, &dst, &offset)) { |
- SkPaint tmpUnfiltered(*paint); |
- tmpUnfiltered.setImageFilter(nullptr); |
- iter.fDevice->drawSprite(iter, dst, pos.x() + offset.x(), pos.y() + offset.y(), |
- tmpUnfiltered); |
- } |
- } else { |
- iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); |
- } |
+ const SkIPoint pos = { x - iter.getX(), y - iter.getY() }; |
+ iter.fDevice->drawBitmapAsSprite(iter, bitmap, pos.x(), pos.y(), looper.paint()); |
} |
LOOPER_END |
} |
@@ -2197,6 +2186,32 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { |
LOOPER_END |
} |
+bool SkCanvas::canDrawBitmapAsSprite(SkScalar x, SkScalar y, int w, int h, const SkPaint& paint) { |
+#ifdef SK_SUPPORT_LEGACY_LAYER_BITMAP_IMAGEFILTERS |
+ return false; |
+#endif |
+ |
+ if (!paint.getImageFilter()) { |
+ return false; |
+ } |
+ |
+ const SkMatrix& ctm = this->getTotalMatrix(); |
+ const unsigned kSubpixelBits = 0; // matching SkDraw::drawBitmap() |
+ if (!SkTreatAsSprite(ctm, w, h, kSubpixelBits)) { |
+ return false; |
+ } |
+ |
+ // Currently we can only use the filterSprite code if we are clipped to the bitmap's bounds. |
+ // Once we can filter and the filter will return a result larger than itself, we should be |
+ // able to remove this constraint. |
+ // skbug.com/4526 |
+ // |
+ SkPoint pt; |
+ ctm.mapXY(x, y, &pt); |
+ SkIRect ir = SkIRect::MakeXYWH(SkScalarRoundToInt(pt.x()), SkScalarRoundToInt(pt.y()), w, h); |
+ return ir.contains(fMCRec->fRasterClip.getBounds()); |
+} |
+ |
void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint* paint) { |
TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawImage()"); |
SkRect bounds = SkRect::MakeXYWH(x, y, |
@@ -2215,11 +2230,25 @@ void SkCanvas::onDrawImage(const SkImage* image, SkScalar x, SkScalar y, const S |
if (nullptr == paint) { |
paint = lazy.init(); |
} |
- |
- LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, &bounds) |
- |
+ |
+ const bool drawAsSprite = this->canDrawBitmapAsSprite(x, y, image->width(), image->height(), |
+ *paint); |
+ LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, &bounds) |
+ |
while (iter.next()) { |
- iter.fDevice->drawImage(iter, image, x, y, looper.paint()); |
+ const SkPaint& pnt = looper.paint(); |
+ if (drawAsSprite && pnt.getImageFilter()) { |
+ SkBitmap bitmap; |
+ if (as_IB(image)->asBitmapForImageFilters(&bitmap)) { |
+ SkPoint pt; |
+ iter.fMatrix->mapXY(x, y, &pt); |
+ iter.fDevice->drawBitmapAsSprite(iter, bitmap, |
+ SkScalarRoundToInt(pt.fX), |
+ SkScalarRoundToInt(pt.fY), pnt); |
+ } |
+ } else { |
+ iter.fDevice->drawImage(iter, image, x, y, pnt); |
+ } |
} |
LOOPER_END |
@@ -2281,12 +2310,23 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons |
bounds = &storage; |
} |
- LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) |
+ const bool drawAsSprite = bounds && this->canDrawBitmapAsSprite(x, y, bitmap.width(), |
+ bitmap.height(), *paint); |
+ LOOPER_BEGIN_DRAWBITMAP(*paint, drawAsSprite, bounds) |
while (iter.next()) { |
- iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); |
+ const SkPaint& pnt = looper.paint(); |
+ if (drawAsSprite && pnt.getImageFilter()) { |
+ SkPoint pt; |
+ iter.fMatrix->mapXY(x, y, &pt); |
+ iter.fDevice->drawBitmapAsSprite(iter, bitmap, |
+ SkScalarRoundToInt(pt.fX), |
+ SkScalarRoundToInt(pt.fY), pnt); |
+ } else { |
+ iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); |
+ } |
} |
- |
+ |
LOOPER_END |
} |