fix asMode() to always succeed if the xfermode was built from a Mode

update dox to reflect this
update test



git-svn-id: http://skia.googlecode.com/svn/trunk@1121 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-04-13 21:12:04 +00:00
Родитель 80adceb39a
Коммит c0d4aa2088
3 изменённых файлов: 61 добавлений и 74 удалений

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

@ -115,10 +115,10 @@ public:
kLastMode = kExclusion_Mode kLastMode = kExclusion_Mode
}; };
/** If the xfermode is one of the modes in the Mode enum, then asMode() /**
returns true and sets (if not null) mode accordingly. * If the xfermode is one of the modes in the Mode enum, then asMode()
This is a better version of IsMode(), which is only able to report * returns true and sets (if not null) mode accordingly. Otherwise it
about modes that are expressible as coefficients. * returns false and ignores the mode parameter.
*/ */
virtual bool asMode(Mode* mode); virtual bool asMode(Mode* mode);
@ -138,10 +138,9 @@ public:
*/ */
static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor); static SkXfermodeProc16 GetProc16(Mode mode, SkColor srcColor);
/** If the specified xfermode advertises itself as one of the porterduff /**
modes (via SkXfermode::Coeff), return true and if not null, set mode * The same as calling xfermode->asMode(mode), except that this also checks
to the corresponding porterduff mode. If it is not recognized as a one, * if the xfermode is NULL, and if so, treats its as kSrcOver_Mode.
return false and ignore the mode parameter.
*/ */
static bool IsMode(SkXfermode*, Mode* mode); static bool IsMode(SkXfermode*, Mode* mode);
@ -189,7 +188,6 @@ public:
// overrides from SkFlattenable // overrides from SkFlattenable
virtual Factory getFactory() { return CreateProc; } virtual Factory getFactory() { return CreateProc; }
virtual void flatten(SkFlattenableWriteBuffer&); virtual void flatten(SkFlattenableWriteBuffer&);
virtual bool asMode(SkXfermode::Mode* mode);
protected: protected:
SkProcXfermode(SkFlattenableReadBuffer&); SkProcXfermode(SkFlattenableReadBuffer&);

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

@ -469,7 +469,7 @@ bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
} }
bool SkXfermode::asMode(Mode* mode) { bool SkXfermode::asMode(Mode* mode) {
return IsMode(this, mode); return false;
} }
SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) { SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
@ -706,28 +706,31 @@ void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
buffer.writeFunctionPtr((void*)fProc); buffer.writeFunctionPtr((void*)fProc);
} }
bool SkProcXfermode::asMode(SkXfermode::Mode* mode) {
for (size_t i = 0; i < SK_ARRAY_COUNT(gProcCoeffs); i++) {
if (gProcCoeffs[i].fProc == fProc) {
if (mode) {
*mode = static_cast<Mode>(i);
}
return true;
}
}
return false;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class SkProcCoeffXfermode : public SkProcXfermode { class SkProcCoeffXfermode : public SkProcXfermode {
public: public:
SkProcCoeffXfermode(SkXfermodeProc proc, Coeff sc, Coeff dc) SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
: INHERITED(proc), fSrcCoeff(sc), fDstCoeff(dc) { : INHERITED(rec.fProc) {
fMode = mode;
// these may be valid, or may be CANNOT_USE_COEFF
fSrcCoeff = rec.fSC;
fDstCoeff = rec.fDC;
} }
virtual bool asMode(Mode* mode) {
if (mode) {
*mode = fMode;
}
return true;
}
virtual bool asCoeff(Coeff* sc, Coeff* dc) { virtual bool asCoeff(Coeff* sc, Coeff* dc) {
if (CANNOT_USE_COEFF == fSrcCoeff) {
return false;
}
if (sc) { if (sc) {
*sc = fSrcCoeff; *sc = fSrcCoeff;
} }
@ -740,6 +743,7 @@ public:
virtual Factory getFactory() { return CreateProc; } virtual Factory getFactory() { return CreateProc; }
virtual void flatten(SkFlattenableWriteBuffer& buffer) { virtual void flatten(SkFlattenableWriteBuffer& buffer) {
this->INHERITED::flatten(buffer); this->INHERITED::flatten(buffer);
buffer.write32(fMode);
buffer.write32(fSrcCoeff); buffer.write32(fSrcCoeff);
buffer.write32(fDstCoeff); buffer.write32(fDstCoeff);
} }
@ -747,11 +751,13 @@ public:
protected: protected:
SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
: INHERITED(buffer) { : INHERITED(buffer) {
fMode = (SkXfermode::Mode)buffer.readU32();
fSrcCoeff = (Coeff)buffer.readU32(); fSrcCoeff = (Coeff)buffer.readU32();
fDstCoeff = (Coeff)buffer.readU32(); fDstCoeff = (Coeff)buffer.readU32();
} }
private: private:
Mode fMode;
Coeff fSrcCoeff, fDstCoeff; Coeff fSrcCoeff, fDstCoeff;
static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
@ -764,8 +770,7 @@ private:
class SkClearXfermode : public SkProcCoeffXfermode { class SkClearXfermode : public SkProcCoeffXfermode {
public: public:
SkClearXfermode() : SkProcCoeffXfermode(clear_modeproc, SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
kZero_Coeff, kZero_Coeff) {}
virtual void xfer32(SK_RESTRICT SkPMColor dst[], virtual void xfer32(SK_RESTRICT SkPMColor dst[],
const SK_RESTRICT SkPMColor[], int count, const SK_RESTRICT SkPMColor[], int count,
@ -819,8 +824,7 @@ private:
class SkSrcXfermode : public SkProcCoeffXfermode { class SkSrcXfermode : public SkProcCoeffXfermode {
public: public:
SkSrcXfermode() : SkProcCoeffXfermode(src_modeproc, SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
kOne_Coeff, kZero_Coeff) {}
virtual void xfer32(SK_RESTRICT SkPMColor dst[], virtual void xfer32(SK_RESTRICT SkPMColor dst[],
const SK_RESTRICT SkPMColor src[], int count, const SK_RESTRICT SkPMColor src[], int count,
@ -878,8 +882,7 @@ private:
class SkDstInXfermode : public SkProcCoeffXfermode { class SkDstInXfermode : public SkProcCoeffXfermode {
public: public:
SkDstInXfermode() : SkProcCoeffXfermode(dstin_modeproc, SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
kZero_Coeff, kSA_Coeff) {}
virtual void xfer32(SK_RESTRICT SkPMColor dst[], virtual void xfer32(SK_RESTRICT SkPMColor dst[],
const SK_RESTRICT SkPMColor src[], int count, const SK_RESTRICT SkPMColor src[], int count,
@ -915,8 +918,7 @@ private:
class SkDstOutXfermode : public SkProcCoeffXfermode { class SkDstOutXfermode : public SkProcCoeffXfermode {
public: public:
SkDstOutXfermode() : SkProcCoeffXfermode(dstout_modeproc, SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
kZero_Coeff, kISA_Coeff) {}
virtual void xfer32(SK_RESTRICT SkPMColor dst[], virtual void xfer32(SK_RESTRICT SkPMColor dst[],
const SK_RESTRICT SkPMColor src[], int count, const SK_RESTRICT SkPMColor src[], int count,
@ -957,29 +959,21 @@ SkXfermode* SkXfermode::Create(Mode mode) {
SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
SkASSERT((unsigned)mode < kModeCount); SkASSERT((unsigned)mode < kModeCount);
const ProcCoeff& rec = gProcCoeffs[mode];
switch (mode) { switch (mode) {
case kClear_Mode: case kClear_Mode:
return SkNEW(SkClearXfermode); return SkNEW_ARGS(SkClearXfermode, (rec));
case kSrc_Mode: case kSrc_Mode:
return SkNEW(SkSrcXfermode); return SkNEW_ARGS(SkSrcXfermode, (rec));
case kSrcOver_Mode: case kSrcOver_Mode:
return NULL; return NULL;
case kDstIn_Mode: case kDstIn_Mode:
return SkNEW(SkDstInXfermode); return SkNEW_ARGS(SkDstInXfermode, (rec));
case kDstOut_Mode: case kDstOut_Mode:
return SkNEW(SkDstOutXfermode); return SkNEW_ARGS(SkDstOutXfermode, (rec));
// use the table default:
default: { return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
const ProcCoeff& rec = gProcCoeffs[mode];
if ((unsigned)rec.fSC < SkXfermode::kCoeffCount &&
(unsigned)rec.fDC < SkXfermode::kCoeffCount) {
return SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc,
rec.fSC,
rec.fDC));
} else {
return SkNEW_ARGS(SkProcXfermode, (rec.fProc));
}
}
} }
} }
@ -990,25 +984,7 @@ bool SkXfermode::IsMode(SkXfermode* xfer, Mode* mode) {
} }
return true; return true;
} }
return xfer->asMode(mode);
SkXfermode::Coeff sc, dc;
if (xfer->asCoeff(&sc, &dc)) {
SkASSERT((unsigned)sc < (unsigned)SkXfermode::kCoeffCount);
SkASSERT((unsigned)dc < (unsigned)SkXfermode::kCoeffCount);
const ProcCoeff* rec = gProcCoeffs;
for (size_t i = 0; i < SK_ARRAY_COUNT(gProcCoeffs); i++) {
if (rec[i].fSC == sc && rec[i].fDC == dc) {
if (mode) {
*mode = static_cast<Mode>(i);
}
return true;
}
}
}
// no coefficients, or not found in our table
return false;
} }
SkXfermodeProc SkXfermode::GetProc(Mode mode) { SkXfermodeProc SkXfermode::GetProc(Mode mode) {

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

@ -6,16 +6,27 @@ SkPMColor bogusXfermodeProc(SkPMColor src, SkPMColor dst) {
return 42; return 42;
} }
#define ILLEGAL_MODE ((SkXfermode::Mode)-1)
static void test_asMode(skiatest::Reporter* reporter) { static void test_asMode(skiatest::Reporter* reporter) {
for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode); SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode);
SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1;
REPORTER_ASSERT(reporter, SkXfermode::Mode reportedMode = ILLEGAL_MODE;
xfer != NULL || mode == SkXfermode::kSrcOver_Mode); REPORTER_ASSERT(reporter, reportedMode != mode);
// test IsMode
REPORTER_ASSERT(reporter, SkXfermode::IsMode(xfer, &reportedMode));
REPORTER_ASSERT(reporter, reportedMode == mode);
// repeat that test, but with asMode instead
if (xfer) { if (xfer) {
REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); reportedMode = (SkXfermode::Mode) -1;
REPORTER_ASSERT(reporter, reportedMode == mode); REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode));
xfer->unref(); REPORTER_ASSERT(reporter, reportedMode == mode);
xfer->unref();
} else {
REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode);
} }
} }
@ -23,6 +34,8 @@ static void test_asMode(skiatest::Reporter* reporter) {
SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1;
REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode));
REPORTER_ASSERT(reporter, reportedMode == -1); REPORTER_ASSERT(reporter, reportedMode == -1);
REPORTER_ASSERT(reporter, !SkXfermode::IsMode(bogusXfer, &reportedMode));
REPORTER_ASSERT(reporter, reportedMode == -1);
bogusXfer->unref(); bogusXfer->unref();
} }