add compose-colorfilter

now with serialization registration

This reverts commit 5bd055c038.

BUG=skia:
TBR=

Review URL: https://codereview.chromium.org/970753002
This commit is contained in:
reed 2015-03-01 19:53:47 -08:00 committed by Commit bot
parent 5bd055c038
commit db873d8677
7 changed files with 273 additions and 106 deletions

View File

@ -11,6 +11,15 @@
#include "SkGradientShader.h"
#include "SkTableColorFilter.h"
static SkShader* make_shader0(int w, int h) {
SkPoint pts[] = { {0, 0}, {SkIntToScalar(w), SkIntToScalar(h)} };
SkColor colors[] = {
SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
};
return SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
SkShader::kClamp_TileMode);
}
static void make_bm0(SkBitmap* bm) {
int W = 120;
int H = 120;
@ -19,34 +28,29 @@ static void make_bm0(SkBitmap* bm) {
SkCanvas canvas(*bm);
SkPaint paint;
SkPoint pts[] = { {0, 0}, {SkIntToScalar(W), SkIntToScalar(H)} };
SkColor colors[] = {
SK_ColorBLACK, SK_ColorGREEN, SK_ColorCYAN,
SK_ColorRED, 0, SK_ColorBLUE, SK_ColorWHITE
};
SkShader* s = SkGradientShader::CreateLinear(pts, colors, NULL, SK_ARRAY_COUNT(colors),
SkShader::kClamp_TileMode);
paint.setShader(s)->unref();
paint.setShader(make_shader0(W, H))->unref();
canvas.drawPaint(paint);
}
static SkShader* make_shader1(int w, int h) {
SkScalar cx = SkIntToScalar(w)/2;
SkScalar cy = SkIntToScalar(h)/2;
SkColor colors[] = {
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
};
return SkGradientShader::CreateRadial(SkPoint::Make(cx, cy), cx, colors, NULL,
SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode);
}
static void make_bm1(SkBitmap* bm) {
int W = 120;
int H = 120;
SkScalar cx = SkIntToScalar(W)/2;
SkScalar cy = SkIntToScalar(H)/2;
bm->allocN32Pixels(W, H);
bm->eraseColor(SK_ColorTRANSPARENT);
SkCanvas canvas(*bm);
SkPaint paint;
SkScalar cx = SkIntToScalar(W)/2;
SkScalar cy = SkIntToScalar(H)/2;
SkColor colors[] = {
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
};
SkShader* s = SkGradientShader::CreateRadial(SkPoint::Make(SkIntToScalar(W)/2,
SkIntToScalar(H)/2),
SkIntToScalar(W)/2, colors, NULL, SK_ARRAY_COUNT(colors),
SkShader::kClamp_TileMode);
paint.setShader(s)->unref();
paint.setShader(make_shader1(W, H))->unref();
paint.setAntiAlias(true);
canvas.drawCircle(cx, cy, cx, paint);
}
@ -184,8 +188,69 @@ protected:
private:
typedef GM INHERITED;
};
DEF_GM( return new TableColorFilterGM; )
//////////////////////////////////////////////////////////////////////////////
static skiagm::GM* MyFactory(void*) { return new TableColorFilterGM; }
static skiagm::GMRegistry reg(MyFactory);
class ComposeColorFilterGM : public skiagm::GM {
public:
ComposeColorFilterGM() {}
protected:
virtual SkString onShortName() {
return SkString("composecolorfilter");
}
virtual SkISize onISize() {
return SkISize::Make(730, 730);
}
virtual void onDraw(SkCanvas* canvas) {
SkBitmap bm;
make_bm1(&bm);
canvas->drawColor(0xFFDDDDDD);
SkColor colors[] = { SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW };
SkXfermode::Mode modes[] = {
SkXfermode::kOverlay_Mode,
SkXfermode::kDarken_Mode,
SkXfermode::kColorBurn_Mode,
SkXfermode::kExclusion_Mode,
};
const int MODES = SK_ARRAY_COUNT(modes) * SK_ARRAY_COUNT(colors);
SkAutoTUnref<SkColorFilter> filters[MODES];
int index = 0;
for (size_t i = 0; i < SK_ARRAY_COUNT(modes); ++i) {
for (size_t j = 0; j < SK_ARRAY_COUNT(colors); ++j) {
filters[index++].reset(SkColorFilter::CreateModeFilter(colors[j], modes[i]));
}
}
SkPaint paint;
paint.setShader(make_shader1(50, 50))->unref();
SkRect r = SkRect::MakeWH(50, 50);
const SkScalar spacer = 10;
canvas->translate(spacer, spacer);
for (size_t y = 0; y < MODES; ++y) {
canvas->save();
for (size_t x = 0; x < MODES; ++x) {
SkAutoTUnref<SkColorFilter> compose(SkColorFilter::CreateComposeFilter(filters[y],
filters[x]));
paint.setColorFilter(compose);
canvas->drawRect(r, paint);
canvas->translate(r.width() + spacer, 0);
}
canvas->restore();
canvas->translate(0, r.height() + spacer);
}
}
private:
typedef GM INHERITED;
};
DEF_GM( return new ComposeColorFilterGM; )

View File

@ -123,6 +123,12 @@ public:
*/
static SkColorFilter* CreateLightingFilter(SkColor mul, SkColor add);
/** Construct a colorfilter whose effect is to first apply the inner filter and then apply
* the outer filter to the result of the inner's.
* The reference counts for outer and inner are incremented.
*/
static SkColorFilter* CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner);
/** A subclass may implement this factory function to work with the GPU backend. If the return
is non-NULL then the caller owns a ref on the returned object.
*/

View File

@ -0,0 +1,63 @@
/*
* Copyright 2015 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkModeColorFilter_DEFINED
#define SkModeColorFilter_DEFINED
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkString.h"
#include "SkXfermode.h"
class SkModeColorFilter : public SkColorFilter {
public:
SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
fColor = color;
fMode = mode;
this->updateCache();
};
SkColor getColor() const { return fColor; }
SkXfermode::Mode getMode() const { return fMode; }
SkPMColor getPMColor() const { return fPMColor; }
bool asColorMode(SkColor*, SkXfermode::Mode*) const SK_OVERRIDE;
uint32_t getFlags() const SK_OVERRIDE;
void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE;
void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE;
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const SK_OVERRIDE {
str->append("SkModeColorFilter: color: 0x");
str->appendHex(fColor);
str->append(" mode: ");
str->append(SkXfermode::ModeName(fMode));
}
#endif
#if SK_SUPPORT_GPU
GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
void flatten(SkWriteBuffer&) const SK_OVERRIDE;
private:
SkColor fColor;
SkXfermode::Mode fMode;
// cache
SkPMColor fPMColor;
SkXfermodeProc fProc;
SkXfermodeProc16 fProc16;
void updateCache();
typedef SkColorFilter INHERITED;
};
#endif

View File

@ -6,12 +6,9 @@
*/
#include "SkColorFilter.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkShader.h"
#include "SkUnPreMultiply.h"
#include "SkString.h"
#include "SkWriteBuffer.h"
bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
return false;
@ -43,3 +40,81 @@ SkColor SkColorFilter::filterColor(SkColor c) const {
GrFragmentProcessor* SkColorFilter::asFragmentProcessor(GrContext*) const {
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
class SkComposeColorFilter : public SkColorFilter {
public:
SkComposeColorFilter(SkColorFilter* outer, SkColorFilter* inner)
: fOuter(SkRef(outer))
, fInner(SkRef(inner))
{}
uint32_t getFlags() const SK_OVERRIDE {
// Can only claim alphaunchanged and 16bit support if both our proxys do.
return fOuter->getFlags() & fInner->getFlags();
}
void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const SK_OVERRIDE {
fInner->filterSpan(shader, count, result);
fOuter->filterSpan(result, count, result);
}
void filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const SK_OVERRIDE {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
fInner->filterSpan16(shader, count, result);
fOuter->filterSpan16(result, count, result);
}
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const SK_OVERRIDE {
SkString outerS, innerS;
fOuter->toString(&outerS);
fInner->toString(&innerS);
str->appendf("SkComposeColorFilter: outer(%s) inner(%s)", outerS.c_str(), innerS.c_str());
}
#endif
#if 0 // TODO: should we support composing the fragments?
#if SK_SUPPORT_GPU
GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
#endif
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkComposeColorFilter)
protected:
void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
buffer.writeFlattenable(fOuter);
buffer.writeFlattenable(fInner);
}
private:
SkAutoTUnref<SkColorFilter> fOuter;
SkAutoTUnref<SkColorFilter> fInner;
friend class SkColorFilter;
typedef SkColorFilter INHERITED;
};
SkFlattenable* SkComposeColorFilter::CreateProc(SkReadBuffer& buffer) {
SkAutoTUnref<SkColorFilter> outer(buffer.readColorFilter());
SkAutoTUnref<SkColorFilter> inner(buffer.readColorFilter());
return CreateComposeFilter(outer, inner);
}
SkColorFilter* SkColorFilter::CreateComposeFilter(SkColorFilter* outer, SkColorFilter* inner) {
if (!outer) {
return SkSafeRef(inner);
}
if (!inner) {
return SkSafeRef(outer);
}
return SkNEW_ARGS(SkComposeColorFilter, (outer, inner));
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkComposeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

View File

@ -8,6 +8,7 @@
#include "SkBlitRow.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
#include "SkModeColorFilter.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkUtils.h"
@ -15,93 +16,49 @@
#include "SkValidationUtils.h"
#include "SkColorMatrixFilter.h"
// baseclass for filters that store a color and mode
class SkModeColorFilter : public SkColorFilter {
public:
SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
fColor = color;
fMode = mode;
this->updateCache();
};
SkColor getColor() const { return fColor; }
SkXfermode::Mode getMode() const { return fMode; }
SkPMColor getPMColor() const { return fPMColor; }
bool asColorMode(SkColor* color, SkXfermode::Mode* mode) const SK_OVERRIDE {
if (color) {
*color = fColor;
}
if (mode) {
*mode = fMode;
}
return true;
bool SkModeColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) const {
if (color) {
*color = fColor;
}
uint32_t getFlags() const SK_OVERRIDE {
return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
if (mode) {
*mode = fMode;
}
return true;
}
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) const SK_OVERRIDE {
SkPMColor color = fPMColor;
SkXfermodeProc proc = fProc;
uint32_t SkModeColorFilter::getFlags() const {
return fProc16 ? (kAlphaUnchanged_Flag | kHasFilter16_Flag) : 0;
}
for (int i = 0; i < count; i++) {
result[i] = proc(color, shader[i]);
}
void SkModeColorFilter::filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const {
SkPMColor color = fPMColor;
SkXfermodeProc proc = fProc;
for (int i = 0; i < count; i++) {
result[i] = proc(color, shader[i]);
}
}
virtual void filterSpan16(const uint16_t shader[], int count,
uint16_t result[]) const SK_OVERRIDE {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
SkPMColor color = fPMColor;
SkXfermodeProc16 proc16 = fProc16;
for (int i = 0; i < count; i++) {
result[i] = proc16(color, shader[i]);
}
void SkModeColorFilter::filterSpan16(const uint16_t shader[], int count, uint16_t result[]) const {
SkASSERT(this->getFlags() & kHasFilter16_Flag);
SkPMColor color = fPMColor;
SkXfermodeProc16 proc16 = fProc16;
for (int i = 0; i < count; i++) {
result[i] = proc16(color, shader[i]);
}
}
void SkModeColorFilter::flatten(SkWriteBuffer& buffer) const {
buffer.writeColor(fColor);
buffer.writeUInt(fMode);
}
#ifndef SK_IGNORE_TO_STRING
void toString(SkString* str) const SK_OVERRIDE {
str->append("SkModeColorFilter: color: 0x");
str->appendHex(fColor);
str->append(" mode: ");
str->append(SkXfermode::ModeName(fMode));
}
#endif
#if SK_SUPPORT_GPU
GrFragmentProcessor* asFragmentProcessor(GrContext*) const SK_OVERRIDE;
#endif
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkModeColorFilter)
protected:
void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
buffer.writeColor(fColor);
buffer.writeUInt(fMode);
}
private:
SkColor fColor;
SkXfermode::Mode fMode;
// cache
SkPMColor fPMColor;
SkXfermodeProc fProc;
SkXfermodeProc16 fProc16;
void updateCache() {
fPMColor = SkPreMultiplyColor(fColor);
fProc = SkXfermode::GetProc(fMode);
fProc16 = SkXfermode::GetProc16(fMode, fColor);
}
friend class SkColorFilter;
typedef SkColorFilter INHERITED;
};
void SkModeColorFilter::updateCache() {
fPMColor = SkPreMultiplyColor(fColor);
fProc = SkXfermode::GetProc(fMode);
fProc16 = SkXfermode::GetProc16(fMode, fColor);
}
SkFlattenable* SkModeColorFilter::CreateProc(SkReadBuffer& buffer) {
SkColor color = buffer.readColor();
@ -549,6 +506,3 @@ SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) {
return SkColorMatrixFilter::Create(matrix);
}
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

View File

@ -46,6 +46,7 @@
#include "SkMagnifierImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
#include "SkMergeImageFilter.h"
#include "SkModeColorFilter.h"
#include "SkMorphologyImageFilter.h"
#include "SkOffsetImageFilter.h"
#include "SkOnce.h"
@ -89,6 +90,7 @@ public:
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)

View File

@ -46,6 +46,7 @@
#include "SkMagnifierImageFilter.h"
#include "SkMatrixConvolutionImageFilter.h"
#include "SkMergeImageFilter.h"
#include "SkModeColorFilter.h"
#include "SkMorphologyImageFilter.h"
#include "SkOffsetImageFilter.h"
#include "SkOnce.h"
@ -89,6 +90,7 @@ public:
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLumaColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath1DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkLine2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkModeColorFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPath2DPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPictureImageFilter)