New SkRectShaderImageFilter image filter

This new changelist also introduces a new image filter called SkRectShaderImageFilter which is make to simply apply a shader on a region without using any inputs.

TEST=Added ShaderImageFilter test
Review URL: https://codereview.appspot.com/7300046

git-svn-id: http://skia.googlecode.com/svn/trunk@7808 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
sugoi@google.com 2013-02-21 15:02:28 +00:00
parent ee3bc3b267
commit a1c511b870
9 changed files with 193 additions and 17 deletions

View File

@ -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',

View File

@ -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',

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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)