Chromium Code Reviews| Index: src/image/SkImage.cpp |
| diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp |
| index af9c27592c527e1383136f999ba56ede955eb07d..0fd95027f1b577677b0b3a85aa664a8b2dd82b46 100644 |
| --- a/src/image/SkImage.cpp |
| +++ b/src/image/SkImage.cpp |
| @@ -67,6 +67,81 @@ void SkImage::preroll(GrContext* ctx) const { |
| } |
| } |
| +SkImage* SkImage::applyFilter(SkImageFilter* filter, SkIPoint* offset, |
| + bool forceResultToOriginalSize) const { |
| + if (!filter) { |
|
robertphillips
2015/10/12 16:43:32
Just return this with offset set to 0,0 ?
reed1
2015/10/12 17:08:45
Will update dox to say out-params are undefined if
|
| + return nullptr; |
| + } |
| + |
| + SkIPoint offsetStorage; |
| + if (!offset) { |
|
robertphillips
2015/10/12 16:43:32
init offsetStorage to 0,0 here ?
reed1
2015/10/12 18:02:19
Not needed.
|
| + offset = &offsetStorage; |
| + } |
| + return as_IB(this)->onApplyFilter(filter, offset, forceResultToOriginalSize); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| +#include "SkImageFilter.h" |
| +#include "SkBitmapDevice.h" |
| + |
|
robertphillips
2015/10/12 16:43:32
const SkIRect& srcBounds ?
reed1
2015/10/12 18:02:19
Done.
|
| +static SkIRect compute_fast_ibounds(SkImageFilter* filter, const SkIRect srcBounds) { |
| + SkRect fastBounds; |
| + fastBounds.set(srcBounds); |
| + filter->computeFastBounds(fastBounds, &fastBounds); |
| + return fastBounds.roundOut(); |
| +} |
| + |
| +class SkRasterImageFilterProxy : public SkImageFilter::Proxy { |
| +public: |
| + SkBaseDevice* createDevice(int width, int height) override { |
| + return SkBitmapDevice::Create(SkImageInfo::MakeN32Premul(width, height)); |
| + } |
| + |
| + bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&, |
| + SkBitmap*, SkIPoint*) override { |
| + return false; |
| + } |
| +}; |
| + |
| +SkImage* SkImage_Base::onApplyFilter(SkImageFilter* filter, SkIPoint* offsetResult, |
| + bool forceResultToOriginalSize) const { |
| + SkBitmap src; |
| + if (!this->getROPixels(&src)) { |
| + return nullptr; |
| + } |
| + |
| + const SkIRect srcBounds = SkIRect::MakeWH(this->width(), this->height()); |
| + |
| + if (forceResultToOriginalSize) { |
| + const SkIRect clipBounds = srcBounds; |
| + SkRasterImageFilterProxy proxy; |
| + SkImageFilter::Context ctx(SkMatrix::I(), clipBounds, SkImageFilter::Cache::Get()); |
| + |
| + SkBitmap dst; |
| + if (filter->filterImage(&proxy, src, ctx, &dst, offsetResult)) { |
| + dst.setImmutable(); |
| + return SkImage::NewFromBitmap(dst); |
| + } |
| + } else { |
| + const SkIRect dstR = compute_fast_ibounds(filter, srcBounds); |
| + |
| + SkImageInfo info = SkImageInfo::MakeN32Premul(dstR.width(), dstR.height()); |
| + SkAutoTUnref<SkSurface> surface(this->onNewSurface(info)); |
| + |
| + SkPaint paint; |
| + paint.setImageFilter(filter); |
| + surface->getCanvas()->drawImage(this, SkIntToScalar(-dstR.x()), SkIntToScalar(-dstR.y()), |
| + &paint); |
| + |
| + offsetResult->set(dstR.x(), dstR.y()); |
| + return surface->newImageSnapshot(); |
| + } |
| + return nullptr; |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////////////////////////// |
| + |
| SkShader* SkImage::newShader(SkShader::TileMode tileX, |
| SkShader::TileMode tileY, |
| const SkMatrix* localMatrix) const { |