Fix SkComposeImageFilter's bounds computation and offset handling
This makes SkComposeImageFilter::computeFastBounds compose its filters' bounds (rather than falling back to SkImageFilter::computeFastBounds, which takes the union of the bounds). This also makes SkComposeImageFilter::onFilterImage correctly handle an offset produced when applying the inner filter; such offsets were previously ignored. BUG=chromium:453924 Review URL: https://codereview.chromium.org/908273002
This commit is contained in:
parent
95f192d199
commit
5788faaa2a
@ -24,6 +24,7 @@ public:
|
||||
SkImageFilter* inputs[2] = { outer, inner };
|
||||
return SkNEW_ARGS(SkComposeImageFilter, (inputs));
|
||||
}
|
||||
void computeFastBounds(const SkRect& src, SkRect* dst) const SK_OVERRIDE;
|
||||
|
||||
SK_TO_STRING_OVERRIDE()
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeImageFilter)
|
||||
|
@ -13,6 +13,15 @@
|
||||
SkComposeImageFilter::~SkComposeImageFilter() {
|
||||
}
|
||||
|
||||
void SkComposeImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
|
||||
SkImageFilter* outer = getInput(0);
|
||||
SkImageFilter* inner = getInput(1);
|
||||
|
||||
SkRect tmp;
|
||||
inner->computeFastBounds(src, &tmp);
|
||||
outer->computeFastBounds(tmp, dst);
|
||||
}
|
||||
|
||||
bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
|
||||
const SkBitmap& src,
|
||||
const Context& ctx,
|
||||
@ -22,8 +31,20 @@ bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
|
||||
SkImageFilter* inner = getInput(1);
|
||||
|
||||
SkBitmap tmp;
|
||||
return inner->filterImage(proxy, src, ctx, &tmp, offset) &&
|
||||
outer->filterImage(proxy, tmp, ctx, result, offset);
|
||||
SkIPoint innerOffset = SkIPoint::Make(0, 0);
|
||||
SkIPoint outerOffset = SkIPoint::Make(0, 0);
|
||||
if (!inner->filterImage(proxy, src, ctx, &tmp, &innerOffset))
|
||||
return false;
|
||||
|
||||
SkMatrix outerMatrix(ctx.ctm());
|
||||
outerMatrix.postTranslate(SkIntToScalar(-innerOffset.x()), SkIntToScalar(-innerOffset.y()));
|
||||
Context outerContext(outerMatrix, ctx.clipBounds(), ctx.cache());
|
||||
if (!outer->filterImage(proxy, tmp, outerContext, result, &outerOffset)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*offset = innerOffset + outerOffset;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
#include "SkColorMatrixFilter.h"
|
||||
#include "SkComposeImageFilter.h"
|
||||
#include "SkDeviceImageFilterProxy.h"
|
||||
#include "SkDisplacementMapEffect.h"
|
||||
#include "SkDropShadowImageFilter.h"
|
||||
@ -584,6 +585,20 @@ DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) {
|
||||
REPORTER_ASSERT(reporter, bounds == expectedBounds);
|
||||
}
|
||||
|
||||
DEF_TEST(ImageFilterComposedBlurFastBounds, reporter) {
|
||||
SkAutoTUnref<SkImageFilter> filter1(makeBlur());
|
||||
SkAutoTUnref<SkImageFilter> filter2(makeBlur());
|
||||
SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(filter1.get(), filter2.get()));
|
||||
|
||||
SkRect boundsSrc = SkRect::MakeWH(SkIntToScalar(100), SkIntToScalar(100));
|
||||
SkRect expectedBounds = SkRect::MakeXYWH(
|
||||
SkIntToScalar(-6), SkIntToScalar(-6), SkIntToScalar(112), SkIntToScalar(112));
|
||||
SkRect boundsDst = SkRect::MakeEmpty();
|
||||
composedFilter->computeFastBounds(boundsSrc, &boundsDst);
|
||||
|
||||
REPORTER_ASSERT(reporter, boundsDst == expectedBounds);
|
||||
}
|
||||
|
||||
static void draw_blurred_rect(SkCanvas* canvas) {
|
||||
SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0));
|
||||
SkPaint filterPaint;
|
||||
@ -1068,6 +1083,23 @@ DEF_TEST(XfermodeImageFilterCroppedInput, reporter) {
|
||||
test_xfermode_cropped_input(&device, reporter);
|
||||
}
|
||||
|
||||
DEF_TEST(ComposedImageFilterOffset, reporter) {
|
||||
SkBitmap bitmap;
|
||||
bitmap.allocN32Pixels(100, 100);
|
||||
bitmap.eraseARGB(0, 0, 0, 0);
|
||||
SkBitmapDevice device(bitmap);
|
||||
SkDeviceImageFilterProxy proxy(&device, SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType));
|
||||
|
||||
SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(1, 0, 20, 20));
|
||||
SkAutoTUnref<SkImageFilter> offsetFilter(SkOffsetImageFilter::Create(0, 0, NULL, &cropRect));
|
||||
SkAutoTUnref<SkImageFilter> composedFilter(SkComposeImageFilter::Create(makeBlur(), offsetFilter.get()));
|
||||
SkBitmap result;
|
||||
SkIPoint offset;
|
||||
SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL);
|
||||
REPORTER_ASSERT(reporter, composedFilter->filterImage(&proxy, bitmap, ctx, &result, &offset));
|
||||
REPORTER_ASSERT(reporter, offset.fX == 1 && offset.fY == 0);
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
const SkSurfaceProps gProps = SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user