Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
| index 1e49fe272df04a9b8af1e8afd50cb7642488c7c5..327c616db4b4e46865e4f8708fd0e61cad7bf8db 100644 |
| --- a/src/core/SkCanvas.cpp |
| +++ b/src/core/SkCanvas.cpp |
| @@ -17,6 +17,7 @@ |
| #include "SkDrawLooper.h" |
| #include "SkErrorInternals.h" |
| #include "SkImage.h" |
| +#include "SkImage_Base.h" |
| #include "SkMetaData.h" |
| #include "SkNinePatchIter.h" |
| #include "SkPaintPriv.h" |
| @@ -592,6 +593,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 +1412,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->filterSprite(iter, bitmap, pos.x(), pos.y(), looper.paint()); |
| } |
| LOOPER_END |
| } |
| @@ -2197,6 +2185,28 @@ void SkCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { |
| LOOPER_END |
| } |
| +bool SkCanvas::canCallFilterSprite(const SkRect& bounds, const SkPaint& paint) { |
| +#ifdef SK_SUPPORT_LEGACY_LAYER_BITMAP_IMAGEFILTERS |
| + return false; |
| +#endif |
| + |
| + if (!paint.getImageFilter()) { |
| + return false; |
| + } |
| + |
| + const SkMatrix& ctm = this->getTotalMatrix(); |
| + if (ctm.getType() & ~SkMatrix::kTranslate_Mask) { |
| + return false; |
| + } |
|
robertphillips
2015/12/04 15:15:48
Add a bug # ?
|
| + // 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. |
| + SkPoint pt; |
| + ctm.mapXY(bounds.x(), bounds.y(), &pt); |
| + SkIRect ibounds = bounds.makeOffset(pt.fX, pt.fY).round(); |
| + return ibounds.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 +2225,24 @@ 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->canCallFilterSprite(bounds, *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->filterSprite(iter, bitmap, |
| + SkScalarRoundToInt(pt.fX), |
| + SkScalarRoundToInt(pt.fY), pnt); |
| + } |
| + } else { |
| + iter.fDevice->drawImage(iter, image, x, y, pnt); |
| + } |
| } |
| LOOPER_END |
| @@ -2281,12 +2304,22 @@ 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->canCallFilterSprite(*bounds, *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->filterSprite(iter, bitmap, |
| + SkScalarRoundToInt(pt.fX), |
| + SkScalarRoundToInt(pt.fY), pnt); |
| + } else { |
| + iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); |
| + } |
| } |
| - |
| + |
| LOOPER_END |
| } |