diff options
author | Florin Malita <fmalita@chromium.org> | 2017-04-28 13:48:37 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-01 14:07:10 +0000 |
commit | 53f77bd4fdd76525b66b7f26d1c5c550858120df (patch) | |
tree | d7516fa1c29a35a3e6b62aae82f3bb6e72928cf4 /src/core/SkBitmapDevice.cpp | |
parent | 57061eea444a8d85189827f014a451de63b49d1a (diff) |
Initial clip-mask-layer support
SkBitmapDevice-only implementation.
Will add A8 fast path specializations in a follow-up.
Change-Id: I2ccb1ffba3689e92ac90a23e94737471dfb121a1
BUG=skia:6005
Change-Id: I2ccb1ffba3689e92ac90a23e94737471dfb121a1
Reviewed-on: https://skia-review.googlesource.com/14183
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Florin Malita <fmalita@chromium.org>
Diffstat (limited to 'src/core/SkBitmapDevice.cpp')
-rw-r--r-- | src/core/SkBitmapDevice.cpp | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 09f25fb332..f6286210aa 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -20,6 +20,7 @@ #include "SkShader.h" #include "SkSpecialImage.h" #include "SkSurface.h" +#include "SkTLazy.h" #include "SkVertices.h" class SkColorTable; @@ -387,35 +388,71 @@ void SkBitmapDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPain /////////////////////////////////////////////////////////////////////////////// -void SkBitmapDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y, - const SkPaint& paint) { - SkASSERT(!srcImg->isTextureBacked()); +void SkBitmapDevice::drawSpecial(SkSpecialImage* src, int x, int y, const SkPaint& origPaint, + SkImage* clipImage, const SkMatrix& clipMatrix) { + SkASSERT(!src->isTextureBacked()); - SkBitmap resultBM; + sk_sp<SkSpecialImage> filteredImage; + SkTCopyOnFirstWrite<SkPaint> paint(origPaint); - SkImageFilter* filter = paint.getImageFilter(); - if (filter) { + if (SkImageFilter* filter = paint->getImageFilter()) { SkIPoint offset = SkIPoint::Make(0, 0); - SkMatrix matrix = this->ctm(); - matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); + const SkMatrix matrix = SkMatrix::Concat( + SkMatrix::MakeTrans(SkIntToScalar(-x), SkIntToScalar(-y)), this->ctm()); const SkIRect clipBounds = fRCStack.rc().getBounds().makeOffset(-x, -y); sk_sp<SkImageFilterCache> cache(this->getImageFilterCache()); SkImageFilter::OutputProperties outputProperties(fBitmap.colorSpace()); SkImageFilter::Context ctx(matrix, clipBounds, cache.get(), outputProperties); - sk_sp<SkSpecialImage> resultImg(filter->filterImage(srcImg, ctx, &offset)); - if (resultImg) { - SkPaint tmpUnfiltered(paint); - tmpUnfiltered.setImageFilter(nullptr); - if (resultImg->getROPixels(&resultBM)) { - this->drawSprite(resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered); - } + filteredImage = filter->filterImage(src, ctx, &offset); + if (!filteredImage) { + return; } - } else { - if (srcImg->getROPixels(&resultBM)) { - this->drawSprite(resultBM, x, y, paint); + + src = filteredImage.get(); + paint.writable()->setImageFilter(nullptr); + x += offset.x(); + y += offset.y(); + } + + if (!clipImage) { + SkBitmap resultBM; + if (src->getROPixels(&resultBM)) { + this->drawSprite(resultBM, x, y, *paint); } + return; + } + + // Clip image case. + sk_sp<SkImage> srcImage(src->asImage()); + if (!srcImage) { + return; } + + const SkMatrix totalMatrix = SkMatrix::Concat(this->ctm(), clipMatrix); + + SkRect clipBounds; + totalMatrix.mapRect(&clipBounds, SkRect::Make(clipImage->bounds())); + const SkIRect srcBounds = srcImage->bounds().makeOffset(x, y); + + SkIRect maskBounds = fRCStack.rc().getBounds(); + if (!maskBounds.intersect(clipBounds.roundOut()) || !maskBounds.intersect(srcBounds)) { + return; + } + + sk_sp<SkSurface> surf = SkSurface::MakeRaster(SkImageInfo::MakeA8(maskBounds.width(), + maskBounds.height())); + SkCanvas* canvas = surf->getCanvas(); + canvas->translate(-maskBounds.x(), -maskBounds.y()); + canvas->concat(totalMatrix); + canvas->drawImage(clipImage, 0, 0); + sk_sp<SkImage> mask = surf->makeImageSnapshot(); + + const SkMatrix m = SkMatrix::MakeTrans(x - maskBounds.x(), y - maskBounds.y()); + paint.writable()->setShader(srcImage->makeShader(&m)); + + SkAutoDeviceCTMRestore adctmr(this, SkMatrix::I()); + this->drawImage(mask.get(), maskBounds.x(), maskBounds.y(), *paint); } sk_sp<SkSpecialImage> SkBitmapDevice::makeSpecial(const SkBitmap& bitmap) { |