aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/effects.gypi2
-rw-r--r--gyp/tests.gyp1
-rw-r--r--include/core/SkImageFilter.h9
-rwxr-xr-xinclude/effects/SkColorFilterImageFilter.h2
-rw-r--r--include/effects/SkRectShaderImageFilter.h43
-rw-r--r--src/core/SkImageFilter.cpp4
-rwxr-xr-xsrc/effects/SkColorFilterImageFilter.cpp27
-rw-r--r--src/effects/SkRectShaderImageFilter.cpp58
-rw-r--r--tests/ShaderImageFilterTest.cpp64
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)