From 77b6ba3b6e23b84a3a4f3a62812e4a9eb6de4c23 Mon Sep 17 00:00:00 2001 From: ajuma Date: Fri, 8 Jan 2016 14:58:35 -0800 Subject: Implement an SkPaint-based image filter This implements SkPaintImageFilter, and is intended to replace SkRectShaderImageFilter. By allowing a paint and not just a shader as input, this allows consumers to control dithering. BUG=skia:4780 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1556553002 Review URL: https://codereview.chromium.org/1556553002 --- src/core/SkPathEffect.cpp | 12 +++- src/effects/SkPaintImageFilter.cpp | 81 +++++++++++++++++++++++++++ src/ports/SkGlobalInitialization_chromium.cpp | 2 + src/ports/SkGlobalInitialization_default.cpp | 2 + 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/effects/SkPaintImageFilter.cpp (limited to 'src') diff --git a/src/core/SkPathEffect.cpp b/src/core/SkPathEffect.cpp index 2403ffcb30..293bb53b2c 100644 --- a/src/core/SkPathEffect.cpp +++ b/src/core/SkPathEffect.cpp @@ -67,7 +67,11 @@ void SkPairPathEffect::toString(SkString* str) const { SkFlattenable* SkComposePathEffect::CreateProc(SkReadBuffer& buffer) { SkAutoTUnref pe0(buffer.readPathEffect()); SkAutoTUnref pe1(buffer.readPathEffect()); - return SkComposePathEffect::Create(pe0, pe1); + if (pe0 && pe1) { + return SkComposePathEffect::Create(pe0, pe1); + } else { + return nullptr; + } } bool SkComposePathEffect::filterPath(SkPath* dst, const SkPath& src, @@ -100,7 +104,11 @@ void SkComposePathEffect::toString(SkString* str) const { SkFlattenable* SkSumPathEffect::CreateProc(SkReadBuffer& buffer) { SkAutoTUnref pe0(buffer.readPathEffect()); SkAutoTUnref pe1(buffer.readPathEffect()); - return SkSumPathEffect::Create(pe0, pe1); + if (pe0 && pe1) { + return SkSumPathEffect::Create(pe0, pe1); + } else { + return nullptr; + } } bool SkSumPathEffect::filterPath(SkPath* dst, const SkPath& src, diff --git a/src/effects/SkPaintImageFilter.cpp b/src/effects/SkPaintImageFilter.cpp new file mode 100644 index 0000000000..d141f34dfb --- /dev/null +++ b/src/effects/SkPaintImageFilter.cpp @@ -0,0 +1,81 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkPaintImageFilter.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkReadBuffer.h" +#include "SkWriteBuffer.h" + +SkImageFilter* SkPaintImageFilter::Create(const SkPaint& paint, const CropRect* cropRect) { + return new SkPaintImageFilter(paint, cropRect); +} + +SkPaintImageFilter::SkPaintImageFilter(const SkPaint& paint, const CropRect* cropRect) + : INHERITED(0, nullptr, cropRect) + , fPaint(paint) { +} + +SkFlattenable* SkPaintImageFilter::CreateProc(SkReadBuffer& buffer) { + SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 0); + SkPaint paint; + buffer.readPaint(&paint); + return Create(paint, &common.cropRect()); +} + +void SkPaintImageFilter::flatten(SkWriteBuffer& buffer) const { + this->INHERITED::flatten(buffer); + buffer.writePaint(fPaint); +} + +bool SkPaintImageFilter::onFilterImage(Proxy* proxy, + const SkBitmap& source, + const Context& ctx, + SkBitmap* result, + SkIPoint* offset) const { + SkIRect bounds; + if (!this->applyCropRect(ctx, source, SkIPoint::Make(0, 0), &bounds)) { + return false; + } + + SkAutoTUnref device(proxy->createDevice(bounds.width(), + bounds.height())); + if (nullptr == device.get()) { + return false; + } + SkCanvas canvas(device.get()); + + SkMatrix matrix(ctx.ctm()); + matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top())); + SkRect rect = SkRect::MakeWH(SkIntToScalar(bounds.width()), SkIntToScalar(bounds.height())); + SkMatrix inverse; + if (matrix.invert(&inverse)) { + inverse.mapRect(&rect); + } + canvas.setMatrix(matrix); + canvas.drawRect(rect, fPaint); + + *result = device.get()->accessBitmap(false); + offset->fX = bounds.fLeft; + offset->fY = bounds.fTop; + return true; +} + +bool SkPaintImageFilter::canComputeFastBounds() const { + // http:skbug.com/4627: "make computeFastBounds and onFilterBounds() CropRect-aware" + // computeFastBounds() doesn't currently take the crop rect into account, + // so we can't compute it. If a full crop rect is set, we should return true here. + return false; +} + +#ifndef SK_IGNORE_TO_STRING +void SkPaintImageFilter::toString(SkString* str) const { + str->appendf("SkPaintImageFilter: ("); + str->append(")"); +} +#endif diff --git a/src/ports/SkGlobalInitialization_chromium.cpp b/src/ports/SkGlobalInitialization_chromium.cpp index f86fdedf43..a756743d1f 100644 --- a/src/ports/SkGlobalInitialization_chromium.cpp +++ b/src/ports/SkGlobalInitialization_chromium.cpp @@ -55,6 +55,7 @@ #include "SkMorphologyImageFilter.h" #include "SkOffsetImageFilter.h" #include "SkOnce.h" +#include "SkPaintImageFilter.h" #include "SkPerlinNoiseShader.h" #include "SkPictureImageFilter.h" #include "SkPictureShader.h" @@ -116,6 +117,7 @@ public: SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPaintImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter) diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp index e710806698..2b7fda021c 100644 --- a/src/ports/SkGlobalInitialization_default.cpp +++ b/src/ports/SkGlobalInitialization_default.cpp @@ -51,6 +51,7 @@ #include "SkMorphologyImageFilter.h" #include "SkOffsetImageFilter.h" #include "SkOnce.h" +#include "SkPaintImageFilter.h" #include "SkPerlinNoiseShader.h" #include "SkPictureImageFilter.h" #include "SkPictureShader.h" @@ -95,6 +96,7 @@ public: SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPaintImageFilter) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader) SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter) -- cgit v1.2.3