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 |