Chromium Code Reviews| Index: src/core/SkCanvas.cpp |
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp |
| index 1e49fe272df04a9b8af1e8afd50cb7642488c7c5..dc7a127a77a81e371bb0b5ca2131c78e45622e0e 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)) { \ |
|
robertphillips
2015/12/02 22:37:18
indent this ?
reed1
2015/12/03 21:26:51
Done.
|
| + SkDrawIter iter(this); |
| + |
| + |
| #define LOOPER_BEGIN_DRAWDEVICE(paint, type) \ |
| this->predrawNotify(); \ |
| AutoDrawLooper looper(this, fProps, paint, true); \ |
| @@ -1404,27 +1412,38 @@ 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); |
| + if (true) { |
|
Stephen White
2015/12/02 23:45:15
Remove this?
reed1
2015/12/03 21:26:51
Done.
|
| + const SkPaint& pnt = looper.paint(); |
| + const SkIPoint pos = { x - iter.getX(), y - iter.getY() }; |
| + if (iter.fDevice->canCallFilterSprite(nullptr, pnt)) { |
| + iter.fDevice->filterSprite(iter, bitmap, pos.x(), pos.y(), |
|
robertphillips
2015/12/02 22:37:18
looper.paint() -> pnt & all on one line ?
Stephen White
2015/12/02 23:45:15
Do we have any benches which exercise these differ
reed1
2015/12/03 21:26:51
Done.
reed1
2015/12/03 21:26:51
Done.
|
| + looper.paint()); |
| + } else { |
| + iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), pnt); |
| } |
| } else { |
| - iter.fDevice->drawSprite(iter, bitmap, pos.x(), pos.y(), *paint); |
| + 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); |
| + } |
| } |
| } |
| LOOPER_END |
| @@ -2197,6 +2216,30 @@ 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 |
| + |
| + const SkMatrix& ctm = this->getTotalMatrix(); |
| + SkBaseDevice* baseDevice = this->getDevice(); |
| + bool handleFilter = baseDevice->canCallFilterSprite(&ctm, paint); |
| + // 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. |
| + if (handleFilter) { |
| + SkPoint pt; |
| + ctm.mapXY(bounds.x(), bounds.y(), &pt); |
| + SkIRect ibounds = bounds.makeOffset(pt.fX, pt.fY).round(); |
| + if (!ibounds.contains(fMCRec->fRasterClip.getBounds())) { |
| + handleFilter = false; |
| + } else { |
| +// SkDebugf("------- handleFilter survived!\n"); |
| + } |
| + } |
| + return handleFilter; |
| +} |
| + |
| 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 +2258,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 handleFilter = this->canCallFilterSprite(bounds, *paint); |
| + LOOPER_BEGIN_DRAWBITMAP(*paint, handleFilter, &bounds) |
| + |
| while (iter.next()) { |
| - iter.fDevice->drawImage(iter, image, x, y, looper.paint()); |
| + const SkPaint& pnt = looper.paint(); |
| + if (handleFilter && 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 +2337,22 @@ void SkCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, cons |
| bounds = &storage; |
| } |
| - LOOPER_BEGIN(*paint, SkDrawFilter::kBitmap_Type, bounds) |
| + const bool handleFilter = bounds && this->canCallFilterSprite(*bounds, *paint); |
| + LOOPER_BEGIN_DRAWBITMAP(*paint, handleFilter, bounds) |
| while (iter.next()) { |
| - iter.fDevice->drawBitmap(iter, bitmap, matrix, looper.paint()); |
| + const SkPaint& pnt = looper.paint(); |
| + if (handleFilter && 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 |
| } |