diff options
-rw-r--r-- | gyp/effects.gypi | 2 | ||||
-rw-r--r-- | gyp/tests.gyp | 1 | ||||
-rw-r--r-- | include/core/SkImageFilter.h | 9 | ||||
-rwxr-xr-x | include/effects/SkColorFilterImageFilter.h | 2 | ||||
-rw-r--r-- | include/effects/SkRectShaderImageFilter.h | 43 | ||||
-rw-r--r-- | src/core/SkImageFilter.cpp | 4 | ||||
-rwxr-xr-x | src/effects/SkColorFilterImageFilter.cpp | 27 | ||||
-rw-r--r-- | src/effects/SkRectShaderImageFilter.cpp | 58 | ||||
-rw-r--r-- | tests/ShaderImageFilterTest.cpp | 64 |
9 files changed, 193 insertions, 17 deletions
diff --git a/gyp/effects.gypi b/gyp/effects.gypi index 31584dff13..7dede6e441 100644 --- a/gyp/effects.gypi +++ b/gyp/effects.gypi @@ -43,6 +43,7 @@ '<(skia_src_path)/effects/SkPaintFlagsDrawFilter.cpp', '<(skia_src_path)/effects/SkPixelXorXfermode.cpp', '<(skia_src_path)/effects/SkPorterDuff.cpp', + '<(skia_src_path)/effects/SkRectShaderImageFilter.cpp', '<(skia_src_path)/effects/SkStippleMaskFilter.cpp', '<(skia_src_path)/effects/SkTableColorFilter.cpp', '<(skia_src_path)/effects/SkTableMaskFilter.cpp', @@ -97,6 +98,7 @@ '<(skia_include_path)/effects/SkPaintFlagsDrawFilter.h', '<(skia_include_path)/effects/SkPixelXorXfermode.h', '<(skia_include_path)/effects/SkPorterDuff.h', + '<(skia_include_path)/effects/SkRectShaderImageFilter.h', '<(skia_include_path)/effects/SkStippleMaskFilter.h', '<(skia_include_path)/effects/SkTableColorFilter.h', '<(skia_include_path)/effects/SkTableMaskFilter.h', diff --git a/gyp/tests.gyp b/gyp/tests.gyp index 082336fbd5..247148b253 100644 --- a/gyp/tests.gyp +++ b/gyp/tests.gyp @@ -88,6 +88,7 @@ '../tests/RTreeTest.cpp', '../tests/SHA1Test.cpp', '../tests/ScalarTest.cpp', + '../tests/ShaderImageFilterTest.cpp', '../tests/ShaderOpacityTest.cpp', '../tests/Sk64Test.cpp', '../tests/skia_test.cpp', diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h index 5066c7b775..6f89bc26f0 100644 --- a/include/core/SkImageFilter.h +++ b/include/core/SkImageFilter.h @@ -16,6 +16,7 @@ class SkDevice; class SkMatrix; struct SkIPoint; struct SkIRect; +class SkShader; class GrEffectRef; class GrTexture; @@ -112,10 +113,12 @@ public: virtual bool filterImageGPU(Proxy*, const SkBitmap& src, SkBitmap* result); /** - * Returns this image filter as a color filter if possible, - * NULL otherwise. + * Returns whether this image filter is a color filter and puts the color filter into the + * "filter" parameter if it can. Does nothing otherwise. + * If this function returns a non NULL *filter value, then the SkColorFilter object has been + * refed within this function and the caller will need to call unref() later on. */ - virtual SkColorFilter* asColorFilter() const; + virtual bool asColorFilter(SkColorFilter** filter) const; /** * Returns the number of inputs this filter will accept (some inputs can diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h index 362e04f200..2e5e59c3c0 100755 --- a/include/effects/SkColorFilterImageFilter.h +++ b/include/effects/SkColorFilterImageFilter.h @@ -26,7 +26,7 @@ protected: virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; - virtual SkColorFilter* asColorFilter() const SK_OVERRIDE; + virtual bool asColorFilter(SkColorFilter**) const SK_OVERRIDE; private: SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input); diff --git a/include/effects/SkRectShaderImageFilter.h b/include/effects/SkRectShaderImageFilter.h new file mode 100644 index 0000000000..c5800a7de7 --- /dev/null +++ b/include/effects/SkRectShaderImageFilter.h @@ -0,0 +1,43 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkRectShaderImageFilter_DEFINED +#define SkRectShaderImageFilter_DEFINED + +#include "SkImageFilter.h" +#include "SkRect.h" + +class SkShader; + +class SK_API SkRectShaderImageFilter : public SkImageFilter { +public: + /** + * The SkShader object will have its refcnt increased as it becomes a member of the + * SkRectShaderImageFilter object returned by this function. It cannot be NULL. + * The region parameter is used to specify on which region the shader is applied. + */ + static SkRectShaderImageFilter* Create(SkShader* s, SkRect region); + virtual ~SkRectShaderImageFilter(); + + SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRectShaderImageFilter) + +protected: + SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer); + virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE; + + virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, + SkBitmap* result, SkIPoint* loc) SK_OVERRIDE; + +private: + SkRectShaderImageFilter(SkShader* s, SkRect region); + SkShader* fShader; + SkRect fRegion; + + typedef SkImageFilter INHERITED; +}; + +#endif diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 616b8b9174..56fb1ae47e 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -122,6 +122,6 @@ bool SkImageFilter::asNewEffect(GrEffectRef**, GrTexture*) const { return false; } -SkColorFilter* SkImageFilter::asColorFilter() const { - return NULL; +bool SkImageFilter::asColorFilter(SkColorFilter**) const { + return false; } diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp index 549a6867df..b5ab255ce7 100755 --- a/src/effects/SkColorFilterImageFilter.cpp +++ b/src/effects/SkColorFilterImageFilter.cpp @@ -62,16 +62,17 @@ SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf, SkScalar colorMatrix[20], inputMatrix[20]; SkColorFilter* inputColorFilter; if (input && cf->asColorMatrix(colorMatrix) - && (inputColorFilter = input->asColorFilter()) - && inputColorFilter->asColorMatrix(inputMatrix) - && !matrix_needs_clamping(inputMatrix)) { - SkScalar combinedMatrix[20]; - mult_color_matrix(inputMatrix, colorMatrix, combinedMatrix); - SkAutoTUnref<SkColorFilter> newCF(SkNEW_ARGS(SkColorMatrixFilter, (combinedMatrix))); - return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0))); - } else { - return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input)); + && input->asColorFilter(&inputColorFilter) + && (NULL != inputColorFilter)) { + SkAutoUnref autoUnref(inputColorFilter); + if (inputColorFilter->asColorMatrix(inputMatrix) && !matrix_needs_clamping(inputMatrix)) { + SkScalar combinedMatrix[20]; + mult_color_matrix(inputMatrix, colorMatrix, combinedMatrix); + SkAutoTUnref<SkColorFilter> newCF(SkNEW_ARGS(SkColorMatrixFilter, (combinedMatrix))); + return SkNEW_ARGS(SkColorFilterImageFilter, (newCF, input->getInput(0))); + } } + return SkNEW_ARGS(SkColorFilterImageFilter, (cf, input)); } SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input) : INHERITED(input), fColorFilter(cf) { @@ -110,6 +111,10 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc return true; } -SkColorFilter* SkColorFilterImageFilter::asColorFilter() const { - return fColorFilter; +bool SkColorFilterImageFilter::asColorFilter(SkColorFilter** filter) const { + if (filter) { + *filter = fColorFilter; + fColorFilter->ref(); + } + return true; } diff --git a/src/effects/SkRectShaderImageFilter.cpp b/src/effects/SkRectShaderImageFilter.cpp new file mode 100644 index 0000000000..b6c78efd0f --- /dev/null +++ b/src/effects/SkRectShaderImageFilter.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkRectShaderImageFilter.h" +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkFlattenableBuffers.h" +#include "SkShader.h" + +SkRectShaderImageFilter* SkRectShaderImageFilter::Create(SkShader* s, SkRect region) { + SkASSERT(s); + return SkNEW_ARGS(SkRectShaderImageFilter, (s, region)); +} + +SkRectShaderImageFilter::SkRectShaderImageFilter(SkShader* s, SkRect region) + : INHERITED(NULL) + , fShader(s) + , fRegion(region) { + SkASSERT(s); + SkSafeRef(s); +} + +SkRectShaderImageFilter::SkRectShaderImageFilter(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer) { + fShader = buffer.readFlattenableT<SkShader>(); + buffer.readRect(&fRegion); +} + +void SkRectShaderImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const { + this->INHERITED::flatten(buffer); + + buffer.writeFlattenable(fShader); + buffer.writeRect(fRegion); +} + +SkRectShaderImageFilter::~SkRectShaderImageFilter() { + SkSafeUnref(fShader); +} + +bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy, + const SkBitmap& source, + const SkMatrix& matrix, + SkBitmap* result, + SkIPoint* loc) { + SkAutoTUnref<SkDevice> device(proxy->createDevice(fRegion.width(), fRegion.height())); + SkCanvas canvas(device.get()); + SkPaint paint; + paint.setShader(fShader); + canvas.drawRect(fRegion, paint); + *result = device.get()->accessBitmap(false); + return true; +} + diff --git a/tests/ShaderImageFilterTest.cpp b/tests/ShaderImageFilterTest.cpp new file mode 100644 index 0000000000..934e8c23e6 --- /dev/null +++ b/tests/ShaderImageFilterTest.cpp @@ -0,0 +1,64 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +#include "Test.h" +#include "SkCanvas.h" +#include "SkShader.h" +#include "SkRectShaderImageFilter.h" +#include "SkGradientShader.h" + +static void test_asShaderMode(skiatest::Reporter* reporter) { + SkRect r = SkRect::MakeWH(10, 10); // Make small 10x10 gradient + + SkBitmap filterResult, shaderResult; + + filterResult.setConfig(SkBitmap::kARGB_8888_Config, r.width(), r.height()); + filterResult.allocPixels(); + SkCanvas canvasFilter(filterResult); + canvasFilter.clear(0x00000000); + + shaderResult.setConfig(SkBitmap::kARGB_8888_Config, r.width(), r.height()); + shaderResult.allocPixels(); + SkCanvas canvasShader(shaderResult); + canvasShader.clear(0x00000000); + + SkPoint center = SkPoint::Make(SkIntToScalar(5), SkIntToScalar(5)); + SkColor colors[] = {SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN}; + SkScalar pos[] = {0, SK_ScalarHalf, SK_Scalar1}; + SkScalar radius = SkIntToScalar(5); + + // Test using the image filter + { + SkShader* s = SkGradientShader::CreateRadial( + center, radius, colors, pos, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); + SkPaint paint; + paint.setImageFilter(SkRectShaderImageFilter::Create(s, r))->unref(); + canvasFilter.drawRect(r, paint); + s->unref(); + } + + // Test using the shader directly + { + SkShader* s = SkGradientShader::CreateRadial( + center, radius, colors, pos, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); + SkPaint paint; + paint.setShader(s)->unref(); + canvasShader.drawRect(r, paint); + } + + // Assert that both paths yielded the same result + for (int y = 0; y < r.height(); ++y) { + const SkPMColor* filterPtr = filterResult.getAddr32(0, y); + const SkPMColor* shaderPtr = shaderResult.getAddr32(0, y); + for (int x = 0; x < r.width(); ++x, ++filterPtr, ++shaderPtr) { + REPORTER_ASSERT(reporter, *filterPtr == *shaderPtr); + } + } +} + +#include "TestClassDef.h" +DEFINE_TESTCLASS("ShaderImageFilter", ShaderImageFilterTestClass, test_asShaderMode) |