static void test_asMode(skiatest::Reporter* reporter) { for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode); SkXfermode::Mode reportedMode = ILLEGAL_MODE; REPORTER_ASSERT(reporter, reportedMode != mode); // test IsMode REPORTER_ASSERT(reporter, SkXfermode::AsMode(xfer, &reportedMode)); REPORTER_ASSERT(reporter, reportedMode == mode); // repeat that test, but with asMode instead if (xfer) { reportedMode = (SkXfermode::Mode) -1; REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, reportedMode == mode); xfer->unref(); } else { REPORTER_ASSERT(reporter, SkXfermode::kSrcOver_Mode == mode); } } SkXfermode* bogusXfer = new SkProcXfermode(bogusXfermodeProc); SkXfermode::Mode reportedMode = ILLEGAL_MODE; REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, reportedMode == ILLEGAL_MODE); REPORTER_ASSERT(reporter, !SkXfermode::AsMode(bogusXfer, &reportedMode)); REPORTER_ASSERT(reporter, reportedMode == ILLEGAL_MODE); bogusXfer->unref(); }
// Returns true if the xfermode will keep the dst opaque, assuming the dst is already opaque. static inline bool xfermodePreservesOpaque(const SkPaint& paint, bool srcIsOpaque) { SkXfermode* xfermode = paint.getXfermode(); if (!xfermode) return true; // default to kSrcOver_Mode SkXfermode::Mode mode; if (!xfermode->asMode(&mode)) return false; switch (mode) { case SkXfermode::kDst_Mode: // dest case SkXfermode::kSrcOver_Mode: // source + dest - source*dest case SkXfermode::kDstOver_Mode: // source + dest - source*dest case SkXfermode::kSrcATop_Mode: // dest case SkXfermode::kPlus_Mode: // source+dest default: // the rest are all source + dest - source*dest return true; case SkXfermode::kClear_Mode: // 0 case SkXfermode::kSrcOut_Mode: // source * (1-dest) case SkXfermode::kDstOut_Mode: // dest * (1-source) case SkXfermode::kXor_Mode: // source + dest - 2*(source*dest) return false; case SkXfermode::kSrc_Mode: // source case SkXfermode::kSrcIn_Mode: // source * dest case SkXfermode::kDstIn_Mode: // dest * source case SkXfermode::kDstATop_Mode: // source return srcIsOpaque; } }
SkXfermode::Mode CanvasRenderingContext2DState::globalComposite() const { SkXfermode* xferMode = m_strokePaint.getXfermode(); SkXfermode::Mode mode; if (!xferMode || !xferMode->asMode(&mode)) return SkXfermode::kSrcOver_Mode; return mode; }
static void test_asMode(skiatest::Reporter* reporter) { for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) { SkXfermode* xfer = SkXfermode::Create((SkXfermode::Mode) mode); SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; REPORTER_ASSERT(reporter, xfer != NULL || mode == SkXfermode::kSrcOver_Mode); if (xfer) { REPORTER_ASSERT(reporter, xfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, reportedMode == mode); xfer->unref(); } } SkXfermode* bogusXfer = new SkProcXfermode(bogusXfermodeProc); SkXfermode::Mode reportedMode = (SkXfermode::Mode) -1; REPORTER_ASSERT(reporter, !bogusXfer->asMode(&reportedMode)); REPORTER_ASSERT(reporter, reportedMode == -1); bogusXfer->unref(); }
// We're only interested in some fields of the SkPaint, so we have a custom // operator== function. bool SkPDFGraphicState::GSCanonicalEntry::operator==( const SkPDFGraphicState::GSCanonicalEntry& gs) const { const SkPaint* a = fPaint; const SkPaint* b = gs.fPaint; SkASSERT(a != NULL); SkASSERT(b != NULL); if (SkColorGetA(a->getColor()) != SkColorGetA(b->getColor()) || a->getStrokeCap() != b->getStrokeCap() || a->getStrokeJoin() != b->getStrokeJoin() || a->getStrokeWidth() != b->getStrokeWidth() || a->getStrokeMiter() != b->getStrokeMiter()) { return false; } SkXfermode::Mode aXfermodeName = SkXfermode::kSrcOver_Mode; SkXfermode* aXfermode = a->getXfermode(); if (aXfermode) { aXfermode->asMode(&aXfermodeName); } if (aXfermodeName < 0 || aXfermodeName > SkXfermode::kLastMode || blend_mode_from_xfermode(aXfermodeName) == NULL) { aXfermodeName = SkXfermode::kSrcOver_Mode; } const char* aXfermodeString = blend_mode_from_xfermode(aXfermodeName); SkASSERT(aXfermodeString != NULL); SkXfermode::Mode bXfermodeName = SkXfermode::kSrcOver_Mode; SkXfermode* bXfermode = b->getXfermode(); if (bXfermode) { bXfermode->asMode(&bXfermodeName); } if (bXfermodeName < 0 || bXfermodeName > SkXfermode::kLastMode || blend_mode_from_xfermode(bXfermodeName) == NULL) { bXfermodeName = SkXfermode::kSrcOver_Mode; } const char* bXfermodeString = blend_mode_from_xfermode(bXfermodeName); SkASSERT(bXfermodeString != NULL); return strcmp(aXfermodeString, bXfermodeString) == 0; }
static bool PaintMayAffectTransparentBlack(const SkPaint* paint) { if (paint) { // FIXME: this is very conservative if (paint->getImageFilter() || paint->getColorFilter()) { return true; } // Unusual Xfermodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 SkXfermode* xfermode = paint->getXfermode(); SkXfermode::Mode mode; // SrcOver is ok, and is also the common case with a NULL xfermode. // So we should make that the fast path and bypass the mode extraction // and test. if (xfermode && xfermode->asMode(&mode)) { switch (mode) { // For each of the following transfer modes, if the source // alpha is zero (our transparent black), the resulting // blended alpha is not necessarily equal to the original // destination alpha. case SkXfermode::kClear_Mode: case SkXfermode::kSrc_Mode: case SkXfermode::kSrcIn_Mode: case SkXfermode::kDstIn_Mode: case SkXfermode::kSrcOut_Mode: case SkXfermode::kDstATop_Mode: case SkXfermode::kModulate_Mode: return true; break; default: break; } } } return false; }