diff options
author | robertphillips <robertphillips@google.com> | 2016-03-07 04:51:10 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-07 04:51:10 -0800 |
commit | eaf086e3ce1b8351a8cd01762ca5144254bddbc4 (patch) | |
tree | f1b96183eb698c79a1d04641fecd79f3a184cc21 /src | |
parent | a5ab9ec295b2e6dca166775a98db67a9a8c18c37 (diff) |
Add SkSpecialImage-based methods to SkImageFilter
This is calved off of https://codereview.chromium.org/1695823002/ (Get OffsetImageFilter really working with SkSpecialImages)
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1757983002
Review URL: https://codereview.chromium.org/1757983002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkImageFilter.cpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 13401af378..5f905285bb 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -18,6 +18,7 @@ #include "SkReadBuffer.h" #include "SkRect.h" #include "SkSpecialImage.h" +#include "SkSpecialSurface.h" #include "SkTDynamicHash.h" #include "SkTInternalLList.h" #include "SkValidationUtils.h" @@ -213,6 +214,28 @@ void SkImageFilter::flatten(SkWriteBuffer& buffer) const { buffer.writeUInt(fCropRect.flags()); } +SkSpecialImage* SkImageFilter::filterImage(SkSpecialImage* src, const Context& context, + SkIPoint* offset) const { + SkASSERT(src && offset); + + uint32_t srcGenID = fUsesSrcInput ? src->uniqueID() : 0; + const SkIRect srcSubset = fUsesSrcInput ? src->subset() : SkIRect::MakeWH(0, 0); + Cache::Key key(fUniqueID, context.ctm(), context.clipBounds(), srcGenID, srcSubset); + if (context.cache()) { + SkSpecialImage* result = context.cache()->get(key, offset); + if (result) { + return SkRef(result); + } + } + + SkSpecialImage* result = this->onFilterImage(src, context, offset); + if (result && context.cache()) { + context.cache()->set(key, result, *offset); + } + + return result; +} + bool SkImageFilter::filterImageDeprecated(Proxy* proxy, const SkBitmap& src, const Context& context, SkBitmap* result, SkIPoint* offset) const { @@ -307,6 +330,21 @@ bool SkImageFilter::onFilterImageDeprecated(Proxy*, const SkBitmap&, const Conte return false; } +SkSpecialImage* SkImageFilter::onFilterImage(SkSpecialImage* src, const Context& ctx, + SkIPoint* offset) const { + SkBitmap srcBM, resultBM; + + if (!src->internal_getBM(&srcBM)) { + return nullptr; + } + + if (!this->filterImageDeprecated(src->internal_getProxy(), srcBM, ctx, &resultBM, offset)) { + return nullptr; + } + + return SkSpecialImage::internal_fromBM(src->internal_getProxy(), resultBM); +} + bool SkImageFilter::canFilterImageGPU() const { return this->asFragmentProcessor(nullptr, nullptr, SkMatrix::I(), SkIRect()); } @@ -419,6 +457,53 @@ bool SkImageFilter::applyCropRectDeprecated(const Context& ctx, Proxy* proxy, co } } +// Return a larger (newWidth x newHeight) copy of 'src' with black padding +// around it. +static SkSpecialImage* pad_image(SkSpecialImage* src, + int newWidth, int newHeight, int offX, int offY) { + + SkImageInfo info = SkImageInfo::MakeN32Premul(newWidth, newHeight); + SkAutoTUnref<SkSpecialSurface> surf(src->newSurface(info)); + if (!surf) { + return nullptr; + } + + SkCanvas* canvas = surf->getCanvas(); + SkASSERT(canvas); + + canvas->clear(0x0); + + src->draw(canvas, offX, offY, nullptr); + + return surf->newImageSnapshot(); +} + +SkSpecialImage* SkImageFilter::applyCropRect(const Context& ctx, + SkSpecialImage* src, + SkIPoint* srcOffset, + SkIRect* bounds) const { + SkIRect srcBounds; + srcBounds = SkIRect::MakeXYWH(srcOffset->fX, srcOffset->fY, src->width(), src->height()); + + SkIRect dstBounds; + this->onFilterNodeBounds(srcBounds, ctx.ctm(), &dstBounds, kForward_MapDirection); + fCropRect.applyTo(dstBounds, ctx.ctm(), bounds); + if (!bounds->intersect(ctx.clipBounds())) { + return nullptr; + } + + if (srcBounds.contains(*bounds)) { + return SkRef(src); + } else { + SkSpecialImage* img = pad_image(src, + bounds->width(), bounds->height(), + srcOffset->x() - bounds->x(), + srcOffset->y() - bounds->y()); + *srcOffset = SkIPoint::Make(bounds->x(), bounds->y()); + return img; + } +} + bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, SkIRect* dst, MapDirection direction) const { if (fInputCount < 1) { @@ -477,6 +562,18 @@ SkImageFilter* SkImageFilter::newWithLocalMatrix(const SkMatrix& matrix) const { return SkLocalMatrixImageFilter::Create(matrix, const_cast<SkImageFilter*>(this)); } +SkSpecialImage* SkImageFilter::filterInput(int index, + SkSpecialImage* src, + const Context& ctx, + SkIPoint* offset) const { + SkImageFilter* input = this->getInput(index); + if (!input) { + return SkRef(src); + } + + return input->filterImage(src, this->mapContext(ctx), offset); +} + #if SK_SUPPORT_GPU bool SkImageFilter::filterInputGPUDeprecated(int index, SkImageFilter::Proxy* proxy, |