add reflection asColorMode to SkColorFilter (for gpu)

git-svn-id: http://skia.googlecode.com/svn/trunk@1126 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-04-14 15:50:52 +00:00
Родитель 586f48cfa8
Коммит 43c50c8c77
7 изменённых файлов: 255 добавлений и 47 удалений

Просмотреть файл

@ -23,6 +23,13 @@
class SkColorFilter : public SkFlattenable {
public:
/**
* If the filter can be represented by a source color plus Mode, this
* returns true, and sets (if not NULL) the color and mode appropriately.
* If not, this returns false and ignores the parameters.
*/
virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode);
/** Called with a scanline of colors, as if there was a shader installed.
The implementation writes out its filtered version into result[].
Note: shader and result may be the same buffer.

Просмотреть файл

@ -75,6 +75,12 @@ public:
*/
virtual bool asCoeff(Coeff* src, Coeff* dst);
/**
* The same as calling xfermode->asCoeff(..), except that this also checks
* if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
*/
static bool AsCoeff(SkXfermode*, Coeff* src, Coeff* dst);
/** List of predefined xfermodes.
The algebra for the modes uses the following symbols:
Sa, Sc - source alpha and color
@ -122,6 +128,12 @@ public:
*/
virtual bool asMode(Mode* mode);
/**
* The same as calling xfermode->asMode(mode), except that this also checks
* if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
*/
static bool AsMode(SkXfermode*, Mode* mode);
/** Return an SkXfermode object for the specified mode.
*/
static SkXfermode* Create(Mode mode);
@ -137,13 +149,20 @@ public:
16bit proc, and this will return NULL.
*/
static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
/**
* The same as calling xfermode->asMode(mode), except that this also checks
* if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
* If the specified mode can be represented by a pair of Coeff, then return
* true and set (if not NULL) the corresponding coeffs. If the mode is
* not representable as a pair of Coeffs, return false and ignore the
* src and dst parameters.
*/
static bool IsMode(SkXfermode*, Mode* mode);
static bool ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst);
// DEPRECATED: call AsMode(...)
static bool IsMode(SkXfermode* xfer, Mode* mode) {
return AsMode(xfer, mode);
}
protected:
SkXfermode(SkFlattenableReadBuffer& rb) : SkFlattenable(rb) {}

Просмотреть файл

@ -18,6 +18,10 @@
#include "SkColorFilter.h"
#include "SkShader.h"
bool SkColorFilter::asColorMode(SkColor* color, SkXfermode::Mode* mode) {
return false;
}
void SkColorFilter::filterSpan16(const uint16_t s[], int count, uint16_t d[])
{
SkASSERT(this->getFlags() & SkColorFilter::kHasFilter16_Flag);

Просмотреть файл

@ -977,7 +977,39 @@ SkXfermode* SkXfermode::Create(Mode mode) {
}
}
bool SkXfermode::IsMode(SkXfermode* xfer, Mode* mode) {
SkXfermodeProc SkXfermode::GetProc(Mode mode) {
SkXfermodeProc proc = NULL;
if ((unsigned)mode < kModeCount) {
proc = gProcCoeffs[mode].fProc;
}
return proc;
}
bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
if ((unsigned)mode >= (unsigned)kModeCount) {
// illegal mode parameter
return false;
}
const ProcCoeff& rec = gProcCoeffs[mode];
if (CANNOT_USE_COEFF == rec.fSC) {
return false;
}
SkASSERT(CANNOT_USE_COEFF != rec.fDC);
if (src) {
*src = rec.fSC;
}
if (dst) {
*dst = rec.fDC;
}
return true;
}
bool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) {
if (NULL == xfer) {
if (mode) {
*mode = kSrcOver_Mode;
@ -987,12 +1019,11 @@ bool SkXfermode::IsMode(SkXfermode* xfer, Mode* mode) {
return xfer->asMode(mode);
}
SkXfermodeProc SkXfermode::GetProc(Mode mode) {
SkXfermodeProc proc = NULL;
if ((unsigned)mode < kModeCount) {
proc = gProcCoeffs[mode].fProc;
bool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) {
if (NULL == xfer) {
return ModeAsCoeff(kSrcOver_Mode, src, dst);
}
return proc;
return xfer->asCoeff(src, dst);
}
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -19,26 +19,67 @@
#include "SkColorPriv.h"
#include "SkUtils.h"
// common baseclass
class Sk_XfermodeColorFilter : public SkColorFilter {
#define ILLEGAL_XFERMODE_MODE ((SkXfermode::Mode)-1)
// baseclass for filters that store a color and mode
class SkModeColorFilter : public SkColorFilter {
public:
SkModeColorFilter(SkColor color) {
fColor = color;
fMode = ILLEGAL_XFERMODE_MODE;
fPMColor = SkPreMultiplyColor(fColor);
}
SkModeColorFilter(SkColor color, SkXfermode::Mode mode) {
fColor = color;
fMode = mode;
fPMColor = SkPreMultiplyColor(fColor);
};
virtual bool asColorMode(SkColor* color, SkXfermode::Mode* mode) {
if (ILLEGAL_XFERMODE_MODE == fMode) {
return false;
}
if (color) {
*color = fColor;
}
if (mode) {
*mode = fMode;
}
return true;
}
SkColor getColor() const { return fColor; }
SkXfermode::Mode getMode() const { return fMode; }
bool isModeValid() const { return ILLEGAL_XFERMODE_MODE != fMode; }
protected:
Sk_XfermodeColorFilter(SkColor color)
: fPMColor(SkPreMultiplyColor(color)) {}
virtual void flatten(SkFlattenableWriteBuffer& buffer) {
buffer.write32(fPMColor);
}
Sk_XfermodeColorFilter(SkFlattenableReadBuffer& buffer) {
fPMColor = buffer.readU32();
buffer.write32(fColor);
buffer.write32(fMode);
}
SkModeColorFilter(SkFlattenableReadBuffer& buffer) {
fColor = buffer.readU32();
fMode = (SkXfermode::Mode)buffer.readU32();
fPMColor = SkPreMultiplyColor(fColor);
}
// cache of fColor in premultiply space
SkPMColor fPMColor;
private:
SkColor fColor;
SkXfermode::Mode fMode;
};
class SkSrc_XfermodeColorFilter : public Sk_XfermodeColorFilter {
class Src_SkModeColorFilter : public SkModeColorFilter {
public:
SkSrc_XfermodeColorFilter(SkColor color) : INHERITED(color) {}
Src_SkModeColorFilter(SkColor color) : INHERITED(color, SkXfermode::kSrc_Mode) {}
virtual uint32_t getFlags() {
if (SkGetPackedA32(fPMColor) == 0xFF) {
@ -62,21 +103,23 @@ public:
protected:
virtual Factory getFactory() { return CreateProc; }
SkSrc_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
Src_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) {}
private:
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (buffer));
return SkNEW_ARGS(Src_SkModeColorFilter, (buffer));
}
typedef Sk_XfermodeColorFilter INHERITED;
typedef SkModeColorFilter INHERITED;
};
class SkSrcOver_XfermodeColorFilter : public Sk_XfermodeColorFilter {
class SrcOver_SkModeColorFilter : public SkModeColorFilter {
public:
SkSrcOver_XfermodeColorFilter(SkColor color)
: INHERITED(color), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
SrcOver_SkModeColorFilter(SkColor color)
: INHERITED(color, SkXfermode::kSrcOver_Mode) {
fColor32Proc = NULL;
}
virtual uint32_t getFlags() {
if (SkGetPackedA32(fPMColor) == 0xFF) {
@ -88,6 +131,9 @@ public:
virtual void filterSpan(const SkPMColor shader[], int count,
SkPMColor result[]) {
if (NULL == fColor32Proc) {
fColor32Proc = SkBlitRow::ColorProcFactory();
}
fColor32Proc(result, shader, count, fPMColor);
}
@ -100,24 +146,31 @@ public:
protected:
virtual Factory getFactory() { return CreateProc; }
SkSrcOver_XfermodeColorFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer), fColor32Proc(SkBlitRow::ColorProcFactory()) {}
SrcOver_SkModeColorFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer), fColor32Proc(NULL) {}
private:
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (buffer));
return SkNEW_ARGS(SrcOver_SkModeColorFilter, (buffer));
}
typedef Sk_XfermodeColorFilter INHERITED;
SkBlitRow::ColorProc fColor32Proc;
typedef SkModeColorFilter INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
class SkXfermodeColorFilter : public Sk_XfermodeColorFilter {
class Proc_SkModeColorFilter : public SkModeColorFilter {
public:
SkXfermodeColorFilter(SkColor color, SkXfermodeProc proc,
SkXfermodeProc16 proc16) : INHERITED(color) {
Proc_SkModeColorFilter(SkColor color, SkXfermode::Mode mode) : INHERITED(color, mode) {
fProc = SkXfermode::GetProc(mode);
fProc16 = SkXfermode::GetProc16(mode, color);
}
Proc_SkModeColorFilter(SkColor color,
SkXfermodeProc proc, SkXfermodeProc16 proc16)
: INHERITED(color, ILLEGAL_XFERMODE_MODE) {
fProc = proc;
fProc16 = proc16;
}
@ -159,26 +212,27 @@ protected:
return CreateProc;
}
SkXfermodeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
Proc_SkModeColorFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
fProc = (SkXfermodeProc) buffer.readFunctionPtr();
fProc16 = (SkXfermodeProc16) buffer.readFunctionPtr();
}
private:
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
return SkNEW_ARGS(SkXfermodeColorFilter, (buffer));
return SkNEW_ARGS(Proc_SkModeColorFilter, (buffer));
}
SkXfermodeProc fProc;
SkXfermodeProc16 fProc16;
typedef Sk_XfermodeColorFilter INHERITED;
typedef SkModeColorFilter INHERITED;
};
SkColorFilter* SkColorFilter::CreateProcFilter(SkColor color,
SkXfermodeProc proc,
SkXfermodeProc16 proc16) {
return proc ?
SkNEW_ARGS(SkXfermodeColorFilter, (color, proc, proc16)) :
SkNEW_ARGS(Proc_SkModeColorFilter, (color, proc, proc16)) :
NULL;
}
@ -215,13 +269,12 @@ SkColorFilter* SkColorFilter::CreateModeFilter(SkColor color,
}
switch (mode) {
case SkXfermode::kSrc_Mode:
return SkNEW_ARGS(SkSrc_XfermodeColorFilter, (color));
case SkXfermode::kSrcOver_Mode:
return SkNEW_ARGS(SkSrcOver_XfermodeColorFilter, (color));
default:
return SkColorFilter::CreateProcFilter(color, SkXfermode::GetProc(mode),
SkXfermode::GetProc16(mode, color));
case SkXfermode::kSrc_Mode:
return SkNEW_ARGS(Src_SkModeColorFilter, (color));
case SkXfermode::kSrcOver_Mode:
return SkNEW_ARGS(SrcOver_SkModeColorFilter, (color));
default:
return SkNEW_ARGS(Proc_SkModeColorFilter, (color, mode));
}
}

93
tests/ColorFilterTest.cpp Normal file
Просмотреть файл

@ -0,0 +1,93 @@
#include "Test.h"
#include "SkColor.h"
#include "SkColorFilter.h"
#include "SkRandom.h"
#include "SkXfermode.h"
static SkFlattenable* reincarnate_flattenable(SkFlattenable* obj) {
SkFlattenable::Factory fact = obj->getFactory();
if (NULL == fact) {
return NULL;
}
SkFlattenableWriteBuffer wb(1024);
obj->flatten(wb);
size_t size = wb.size();
SkAutoSMalloc<1024> storage(size);
// make a copy into storage
wb.flatten(storage.get());
SkFlattenableReadBuffer rb(storage.get(), size);
return fact(rb);
}
template <typename T> T* reincarnate(T* obj) {
return (T*)reincarnate_flattenable(obj);
}
///////////////////////////////////////////////////////////////////////////////
#define ILLEGAL_MODE ((SkXfermode::Mode)-1)
static void test_asColorMode(skiatest::Reporter* reporter) {
SkRandom rand;
for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
SkColor color = rand.nextU();
// ensure we always get a filter, by avoiding the possibility of a
// special case that would return NULL (if color's alpha is 0 or 0xFF)
color = SkColorSetA(color, 0x7F);
SkColorFilter* cf = SkColorFilter::CreateModeFilter(color,
(SkXfermode::Mode)mode);
// allow for no filter if we're in Dst mode (its a no op)
if (SkXfermode::kDst_Mode == mode && NULL == cf) {
continue;
}
SkAutoUnref aur(cf);
REPORTER_ASSERT(reporter, cf);
SkColor c = ~color;
SkXfermode::Mode m = ILLEGAL_MODE;
SkColor expectedColor = color;
SkXfermode::Mode expectedMode = (SkXfermode::Mode)mode;
// SkDebugf("--- mc [%d %x] ", mode, color);
REPORTER_ASSERT(reporter, cf->asColorMode(&c, &m));
// handle special-case folding by the factory
if (SkXfermode::kClear_Mode == mode) {
if (c != expectedColor) {
expectedColor = 0;
}
if (m != expectedMode) {
expectedMode = SkXfermode::kSrc_Mode;
}
}
// SkDebugf("--- got [%d %x] expected [%d %x]\n", m, c, expectedMode, expectedColor);
REPORTER_ASSERT(reporter, c == expectedColor);
REPORTER_ASSERT(reporter, m == expectedMode);
{
SkColorFilter* cf2 = reincarnate(cf);
SkAutoUnref aur2(cf2);
REPORTER_ASSERT(reporter, cf2);
SkColor c2 = ~color;
SkXfermode::Mode m2 = ILLEGAL_MODE;
REPORTER_ASSERT(reporter, cf2->asColorMode(&c2, &m2));
REPORTER_ASSERT(reporter, c2 == expectedColor);
REPORTER_ASSERT(reporter, m2 == expectedMode);
}
}
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("ColorFilter", ColorFilterTestClass, test_asColorMode)

Просмотреть файл

@ -5,6 +5,7 @@ SOURCE := \
ClipCubicTest.cpp \
ClipStackTest.cpp \
ClipperTest.cpp \
ColorFilterTest.cpp \
DequeTest.cpp \
DrawBitmapRectTest.cpp \
FillPathTest.cpp \