| Index: src/image/SkImage.cpp
|
| diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
|
| index af9c27592c527e1383136f999ba56ede955eb07d..3ad80043da2f49e841e546346efca82a0f712171 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) {
|
| + return nullptr;
|
| + }
|
| +
|
| + SkIPoint offsetStorage;
|
| + if (!offset) {
|
| + offset = &offsetStorage;
|
| + }
|
| + return as_IB(this)->onApplyFilter(filter, offset, forceResultToOriginalSize);
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////////////////////////
|
| +
|
| +#include "SkImageFilter.h"
|
| +#include "SkBitmapDevice.h"
|
| +
|
| +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 {
|
|
|