| Index: src/effects/SkMorphologyImageFilter.cpp
|
| diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
|
| index 5d5f29058b705a704053d3c1873a81286e1f2cf9..ee998df673f24878b0c95da7845da056e01e7232 100644
|
| --- a/src/effects/SkMorphologyImageFilter.cpp
|
| +++ b/src/effects/SkMorphologyImageFilter.cpp
|
| @@ -30,8 +30,8 @@ SkMorphologyImageFilter::SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer
|
| (fRadius.fHeight >= 0));
|
| }
|
|
|
| -SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input)
|
| - : INHERITED(input), fRadius(SkISize::Make(radiusX, radiusY)) {
|
| +SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const SkIRect* cropRect)
|
| + : INHERITED(input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) {
|
| }
|
|
|
|
|
| @@ -75,17 +75,17 @@ static void erode(const SkPMColor* src, SkPMColor* dst,
|
| }
|
| }
|
|
|
| -static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX)
|
| +static void erodeX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
|
| {
|
| - erode(src.getAddr32(0, 0), dst->getAddr32(0, 0),
|
| - radiusX, src.width(), src.height(),
|
| + erode(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
|
| + radiusX, bounds.width(), bounds.height(),
|
| 1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels());
|
| }
|
|
|
| -static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY)
|
| +static void erodeY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
|
| {
|
| - erode(src.getAddr32(0, 0), dst->getAddr32(0, 0),
|
| - radiusY, src.height(), src.width(),
|
| + erode(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
|
| + radiusY, bounds.height(), bounds.width(),
|
| src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1);
|
| }
|
|
|
| @@ -123,17 +123,17 @@ static void dilate(const SkPMColor* src, SkPMColor* dst,
|
| }
|
| }
|
|
|
| -static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX)
|
| +static void dilateX(const SkBitmap& src, SkBitmap* dst, int radiusX, const SkIRect& bounds)
|
| {
|
| - dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0),
|
| - radiusX, src.width(), src.height(),
|
| + dilate(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
|
| + radiusX, bounds.width(), bounds.height(),
|
| 1, src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels());
|
| }
|
|
|
| -static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY)
|
| +static void dilateY(const SkBitmap& src, SkBitmap* dst, int radiusY, const SkIRect& bounds)
|
| {
|
| - dilate(src.getAddr32(0, 0), dst->getAddr32(0, 0),
|
| - radiusY, src.height(), src.width(),
|
| + dilate(src.getAddr32(bounds.left(), bounds.top()), dst->getAddr32(0, 0),
|
| + radiusY, bounds.height(), bounds.width(),
|
| src.rowBytesAsPixels(), 1, dst->rowBytesAsPixels(), 1);
|
| }
|
|
|
| @@ -149,12 +149,18 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
|
| return false;
|
| }
|
|
|
| + SkIRect bounds;
|
| + src.getBounds(&bounds);
|
| + if (!this->applyCropRect(&bounds, ctm)) {
|
| + return false;
|
| + }
|
| +
|
| SkAutoLockPixels alp(src);
|
| if (!src.getPixels()) {
|
| return false;
|
| }
|
|
|
| - dst->setConfig(src.config(), src.width(), src.height());
|
| + dst->setConfig(src.config(), bounds.width(), bounds.height());
|
| dst->allocPixels();
|
|
|
| int width = radius().width();
|
| @@ -165,7 +171,9 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
|
| }
|
|
|
| if (width == 0 && height == 0) {
|
| - src.copyTo(dst, dst->config());
|
| + src.extractSubset(dst, bounds);
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| return true;
|
| }
|
|
|
| @@ -176,13 +184,16 @@ bool SkErodeImageFilter::onFilterImage(Proxy* proxy,
|
| }
|
|
|
| if (width > 0 && height > 0) {
|
| - erodeX(src, &temp, width);
|
| - erodeY(temp, dst, height);
|
| + erodeX(src, &temp, width, bounds);
|
| + SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
|
| + erodeY(temp, dst, height, tmpBounds);
|
| } else if (width > 0) {
|
| - erodeX(src, dst, width);
|
| + erodeX(src, dst, width, bounds);
|
| } else if (height > 0) {
|
| - erodeY(src, dst, height);
|
| + erodeY(src, dst, height, bounds);
|
| }
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| return true;
|
| }
|
|
|
| @@ -197,12 +208,18 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
|
| return false;
|
| }
|
|
|
| + SkIRect bounds;
|
| + src.getBounds(&bounds);
|
| + if (!this->applyCropRect(&bounds, ctm)) {
|
| + return false;
|
| + }
|
| +
|
| SkAutoLockPixels alp(src);
|
| if (!src.getPixels()) {
|
| return false;
|
| }
|
|
|
| - dst->setConfig(src.config(), src.width(), src.height());
|
| + dst->setConfig(src.config(), bounds.width(), bounds.height());
|
| dst->allocPixels();
|
|
|
| int width = radius().width();
|
| @@ -213,7 +230,9 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
|
| }
|
|
|
| if (width == 0 && height == 0) {
|
| - src.copyTo(dst, dst->config());
|
| + src.extractSubset(dst, bounds);
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| return true;
|
| }
|
|
|
| @@ -224,13 +243,16 @@ bool SkDilateImageFilter::onFilterImage(Proxy* proxy,
|
| }
|
|
|
| if (width > 0 && height > 0) {
|
| - dilateX(src, &temp, width);
|
| - dilateY(temp, dst, height);
|
| + dilateX(src, &temp, width, bounds);
|
| + SkIRect tmpBounds = SkIRect::MakeWH(bounds.width(), bounds.height());
|
| + dilateY(temp, dst, height, tmpBounds);
|
| } else if (width > 0) {
|
| - dilateX(src, dst, width);
|
| + dilateX(src, dst, width, bounds);
|
| } else if (height > 0) {
|
| - dilateY(src, dst, height);
|
| + dilateY(src, dst, height, bounds);
|
| }
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| return true;
|
| }
|
|
|
| @@ -450,7 +472,8 @@ namespace {
|
|
|
| void apply_morphology_pass(GrContext* context,
|
| GrTexture* texture,
|
| - const SkIRect& rect,
|
| + const SkIRect& srcRect,
|
| + const SkIRect& dstRect,
|
| int radius,
|
| GrMorphologyEffect::MorphologyType morphType,
|
| Gr1DKernelEffect::Direction direction) {
|
| @@ -459,15 +482,19 @@ void apply_morphology_pass(GrContext* context,
|
| direction,
|
| radius,
|
| morphType))->unref();
|
| - context->drawRect(paint, SkRect::MakeFromIRect(rect));
|
| + context->drawRectToRect(paint, SkRect::MakeFromIRect(dstRect), SkRect::MakeFromIRect(srcRect));
|
| }
|
|
|
| -GrTexture* apply_morphology(GrTexture* srcTexture,
|
| - const SkIRect& rect,
|
| - GrMorphologyEffect::MorphologyType morphType,
|
| - SkISize radius) {
|
| +bool apply_morphology(const SkBitmap& input,
|
| + const SkIRect& rect,
|
| + GrMorphologyEffect::MorphologyType morphType,
|
| + SkISize radius,
|
| + SkBitmap* dst) {
|
| + GrTexture* srcTexture = input.getTexture();
|
| + SkASSERT(NULL != srcTexture);
|
| GrContext* context = srcTexture->getContext();
|
| srcTexture->ref();
|
| + SkAutoTUnref<GrTexture> src(srcTexture);
|
|
|
| GrContext::AutoMatrix am;
|
| am.setIdentity(context);
|
| @@ -475,62 +502,101 @@ GrTexture* apply_morphology(GrTexture* srcTexture,
|
| GrContext::AutoClip acs(context, SkRect::MakeWH(SkIntToScalar(srcTexture->width()),
|
| SkIntToScalar(srcTexture->height())));
|
|
|
| + SkIRect dstRect = SkIRect::MakeWH(rect.width(), rect.height());
|
| GrTextureDesc desc;
|
| desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
|
| desc.fWidth = rect.width();
|
| desc.fHeight = rect.height();
|
| desc.fConfig = kSkia8888_GrPixelConfig;
|
| + SkIRect srcRect = rect;
|
|
|
| if (radius.fWidth > 0) {
|
| GrAutoScratchTexture ast(context, desc);
|
| GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
|
| - apply_morphology_pass(context, srcTexture, rect, radius.fWidth,
|
| + apply_morphology_pass(context, src, srcRect, dstRect, radius.fWidth,
|
| morphType, Gr1DKernelEffect::kX_Direction);
|
| - SkIRect clearRect = SkIRect::MakeXYWH(rect.fLeft, rect.fBottom,
|
| - rect.width(), radius.fHeight);
|
| + SkIRect clearRect = SkIRect::MakeXYWH(dstRect.fLeft, dstRect.fBottom,
|
| + dstRect.width(), radius.fHeight);
|
| context->clear(&clearRect, 0x0);
|
| - srcTexture->unref();
|
| - srcTexture = ast.detach();
|
| + src.reset(ast.detach());
|
| + srcRect = dstRect;
|
| }
|
| if (radius.fHeight > 0) {
|
| GrAutoScratchTexture ast(context, desc);
|
| GrContext::AutoRenderTarget art(context, ast.texture()->asRenderTarget());
|
| - apply_morphology_pass(context, srcTexture, rect, radius.fHeight,
|
| + apply_morphology_pass(context, src, srcRect, dstRect, radius.fHeight,
|
| morphType, Gr1DKernelEffect::kY_Direction);
|
| - srcTexture->unref();
|
| - srcTexture = ast.detach();
|
| + src.reset(ast.detach());
|
| }
|
| - return srcTexture;
|
| + return SkImageFilterUtils::WrapTexture(src, rect.width(), rect.height(), dst);
|
| }
|
|
|
| };
|
|
|
| bool SkDilateImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
|
| SkBitmap* result, SkIPoint* offset) {
|
| - SkBitmap inputBM;
|
| - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) {
|
| + SkBitmap input;
|
| + if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
|
| return false;
|
| }
|
| - GrTexture* input = inputBM.getTexture();
|
| SkIRect bounds;
|
| src.getBounds(&bounds);
|
| - SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds,
|
| - GrMorphologyEffect::kDilate_MorphologyType, radius()));
|
| - return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result);
|
| + if (!this->applyCropRect(&bounds, ctm)) {
|
| + return false;
|
| + }
|
| + int width = radius().width();
|
| + int height = radius().height();
|
| +
|
| + if (width < 0 || height < 0) {
|
| + return false;
|
| + }
|
| +
|
| + if (width == 0 && height == 0) {
|
| + src.extractSubset(result, bounds);
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| + return true;
|
| + }
|
| +
|
| + if (!apply_morphology(input, bounds, GrMorphologyEffect::kDilate_MorphologyType, radius(), result)) {
|
| + return false;
|
| + }
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| + return true;
|
| }
|
|
|
| bool SkErodeImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
|
| SkBitmap* result, SkIPoint* offset) {
|
| - SkBitmap inputBM;
|
| - if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &inputBM, offset)) {
|
| + SkBitmap input;
|
| + if (!SkImageFilterUtils::GetInputResultGPU(getInput(0), proxy, src, ctm, &input, offset)) {
|
| return false;
|
| }
|
| - GrTexture* input = inputBM.getTexture();
|
| SkIRect bounds;
|
| src.getBounds(&bounds);
|
| - SkAutoTUnref<GrTexture> resultTex(apply_morphology(input, bounds,
|
| - GrMorphologyEffect::kErode_MorphologyType, radius()));
|
| - return SkImageFilterUtils::WrapTexture(resultTex, src.width(), src.height(), result);
|
| + if (!this->applyCropRect(&bounds, ctm)) {
|
| + return false;
|
| + }
|
| + int width = radius().width();
|
| + int height = radius().height();
|
| +
|
| + if (width < 0 || height < 0) {
|
| + return false;
|
| + }
|
| +
|
| + if (width == 0 && height == 0) {
|
| + src.extractSubset(result, bounds);
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| + return true;
|
| + }
|
| +
|
| + if (!apply_morphology(input, bounds, GrMorphologyEffect::kErode_MorphologyType, radius(), result)) {
|
| + return false;
|
| + }
|
| + offset->fX += bounds.left();
|
| + offset->fY += bounds.top();
|
| + return true;
|
| }
|
|
|
| #endif
|
|
|