void SkGL::SetPaint(const SkPaint& paint, bool isPremul, bool justAlpha) { if (justAlpha) { SkGL::SetAlpha(paint.getAlpha()); } else { SkGL::SetColor(paint.getColor()); } GLenum sm = GL_ONE; GLenum dm = GL_ONE_MINUS_SRC_ALPHA; SkXfermode* mode = paint.getXfermode(); SkXfermode::Coeff sc, dc; if (mode && mode->asCoeff(&sc, &dc)) { sm = gXfermodeCoeff2Blend[sc]; dm = gXfermodeCoeff2Blend[dc]; } // hack for text, which is not-premul (afaik) if (!isPremul) { if (GL_ONE == sm) { sm = GL_SRC_ALPHA; } } glEnable(GL_BLEND); glBlendFunc(sm, dm); if (paint.isDither()) { glEnable(GL_DITHER); } else { glDisable(GL_DITHER); } }
virtual void blitRect(int x, int y, int width, int height) { SkASSERT(width > 0 && height > 0); SK_RESTRICT SkPMColor* dst = fDevice->getAddr32(x, y); const SK_RESTRICT SkPMColor16* src = fSource->getAddr16(x - fLeft, y - fTop); unsigned dstRB = fDevice->rowBytes(); unsigned srcRB = fSource->rowBytes(); SK_RESTRICT SkPMColor* buffer = fBuffer; SkColorFilter* colorFilter = fColorFilter; SkXfermode* xfermode = fXfermode; do { fillbuffer(buffer, src, width); if (NULL != colorFilter) { colorFilter->filterSpan(buffer, width, buffer); } if (NULL != xfermode) { xfermode->xfer32(dst, buffer, width, NULL); } else { fProc32(dst, buffer, width, fAlpha); } dst = (SK_RESTRICT SkPMColor*)((char*)dst + dstRB); src = (const SK_RESTRICT SkPMColor16*)((const char*)src + srcRB); } while (--height != 0); }
// 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; } }
ShaderView() { SkImageDecoder::DecodeFile("/cover.png", &fBitmap); SkPoint pts[2]; SkColor colors[2]; pts[0].set(0, 0); pts[1].set(SkIntToScalar(100), 0); colors[0] = SK_ColorRED; colors[1] = SK_ColorBLUE; SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); pts[0].set(0, 0); pts[1].set(0, SkIntToScalar(100)); colors[0] = SK_ColorBLACK; colors[1] = SkColorSetARGB(0x80, 0, 0, 0); SkShader* shaderB = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode); fShader = new SkComposeShader(shaderA, shaderB, mode); shaderA->unref(); shaderB->unref(); mode->unref(); }
void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { SkShader::Context* shaderContextA = fShaderContextA; SkShader::Context* shaderContextB = fShaderContextB; SkBlendMode mode = static_cast<const SkComposeShader&>(fShader).fMode; unsigned scale = SkAlpha255To256(this->getPaintAlpha()); SkPMColor tmp[TMP_COLOR_COUNT]; SkXfermode* xfer = SkXfermode::Peek(mode); if (nullptr == xfer) { // implied SRC_OVER // TODO: when we have a good test-case, should use SkBlitRow::Proc32 // for these loops do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderContextA->shadeSpan(x, y, result, n); shaderContextB->shadeSpan(x, y, tmp, n); if (256 == scale) { for (int i = 0; i < n; i++) { result[i] = SkPMSrcOver(tmp[i], result[i]); } } else { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), scale); } } result += n; x += n; count -= n; } while (count > 0); } else { // use mode for the composition do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderContextA->shadeSpan(x, y, result, n); shaderContextB->shadeSpan(x, y, tmp, n); xfer->xfer32(result, tmp, n, nullptr); if (256 != scale) { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(result[i], scale); } } result += n; x += n; count -= n; } while (count > 0); } }
SkXfermode::Mode CanvasRenderingContext2DState::globalComposite() const { SkXfermode* xferMode = m_strokePaint.getXfermode(); SkXfermode::Mode mode; if (!xferMode || !xferMode->asMode(&mode)) return SkXfermode::kSrcOver_Mode; return mode; }
void SkComposeShader::shadeSpan(int x, int y, SkPMColor result[], int count) { SkShader* shaderA = fShaderA; SkShader* shaderB = fShaderB; SkXfermode* mode = fMode; unsigned scale = SkAlpha255To256(this->getPaintAlpha()); SkPMColor tmp[TMP_COLOR_COUNT]; if (NULL == mode) { // implied SRC_OVER // TODO: when we have a good test-case, should use SkBlitRow::Proc32 // for these loops do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderA->shadeSpan(x, y, result, n); shaderB->shadeSpan(x, y, tmp, n); if (256 == scale) { for (int i = 0; i < n; i++) { result[i] = SkPMSrcOver(tmp[i], result[i]); } } else { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), scale); } } result += n; x += n; count -= n; } while (count > 0); } else { // use mode for the composition do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderA->shadeSpan(x, y, result, n); shaderB->shadeSpan(x, y, tmp, n); mode->xfer32(result, tmp, n, NULL); if (256 == scale) { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(result[i], scale); } } result += n; x += n; count -= n; } while (count > 0); } }
void SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { // we only handle kA8 with an xfermode if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) { this->INHERITED::blitMask(mask, clip); return; } SkASSERT(mask.fBounds.contains(clip)); SkBlitMask::RowProc proc = NULL; if (!fXfermode) { unsigned flags = 0; if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { flags |= SkBlitMask::kSrcIsOpaque_RowFlag; } proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat, (SkBlitMask::RowFlags)flags); if (NULL == proc) { this->INHERITED::blitMask(mask, clip); return; } } const int x = clip.fLeft; const int width = clip.width(); int y = clip.fTop; int height = clip.height(); char* dstRow = (char*)fDevice.getAddr32(x, y); const size_t dstRB = fDevice.rowBytes(); const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y); const size_t maskRB = mask.fRowBytes; SkShader* shader = fShader; SkPMColor* span = fBuffer; if (fXfermode) { SkASSERT(SkMask::kA8_Format == mask.fFormat); SkXfermode* xfer = fXfermode; do { shader->shadeSpan(x, y, span, width); xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow); dstRow += dstRB; maskRow += maskRB; y += 1; } while (--height > 0); } else { do { shader->shadeSpan(x, y, span, width); proc(dstRow, maskRow, span, width); dstRow += dstRB; maskRow += maskRB; y += 1; } while (--height > 0); } }
void mbe_copy_source(mbe_t *src, mbe_t *dst) { SkPaint *paint = dst->paint; const SkBitmap *bmap; SkXfermode *mode; /* _prepare_paint(dst, SkPaint::kFill_Style); */ mode = SkXfermode::Create(SkXfermode::kSrc_Mode); paint->setXfermode(mode); bmap = &src->canvas->getDevice()->accessBitmap(false); dst->canvas->drawBitmap(*bmap, 0, 0, paint); paint->reset(); mode->unref(); /* _finish_paint(dst); */ }
void onDraw(SkCanvas* canvas) override { // start with the center of a 3x3 grid static const uint16_t fan[] = { 4, 0, 1, 2, 5, 8, 7, 6, 3, 0 }; const struct { const SkColor* fColors; const SkPoint* fTexs; } rec[] = { { fColors, NULL }, { NULL, fTexs }, { fColors, fTexs }, }; const SkXfermode::Mode modes[] = { SkXfermode::kSrc_Mode, SkXfermode::kDst_Mode, SkXfermode::kModulate_Mode, }; SkPaint paint; paint.setShader(fShader); paint.setAlpha(fAlpha); canvas->translate(20, 20); for (size_t j = 0; j < SK_ARRAY_COUNT(modes); ++j) { SkXfermode* xfer = SkXfermode::Create(modes[j]); canvas->save(); for (size_t i = 0; i < SK_ARRAY_COUNT(rec); ++i) { canvas->drawVertices(SkCanvas::kTriangleFan_VertexMode, SK_ARRAY_COUNT(fPts), fPts, rec[i].fTexs, rec[i].fColors, xfer, fan, SK_ARRAY_COUNT(fan), paint); canvas->translate(200, 0); } canvas->restore(); canvas->translate(0, 200); xfer->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 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(); }
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; }
static SkShader* make_bitmapfade(const SkBitmap& bm) { SkPoint pts[2]; SkColor colors[2]; pts[0].set(0, 0); pts[1].set(0, SkIntToScalar(bm.height())); colors[0] = SK_ColorBLACK; colors[1] = SkColorSetARGB(0, 0, 0, 0); SkShader* shaderA = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kClamp_TileMode); SkShader* shaderB = SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); SkXfermode* mode = SkPorterDuff::CreateXfermode(SkPorterDuff::kDstIn_Mode); SkShader* shader = new SkComposeShader(shaderB, shaderA, mode); shaderA->unref(); shaderB->unref(); mode->unref(); return shader; }
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(); }
static inline bool skpaint_to_grpaint_impl(GrContext* context, const SkPaint& skPaint, const SkMatrix& viewM, const GrFragmentProcessor** shaderProcessor, SkXfermode::Mode* primColorMode, bool primitiveIsSrc, GrPaint* grPaint) { grPaint->setAntiAlias(skPaint.isAntiAlias()); // Setup the initial color considering the shader, the SkPaint color, and the presence or not // of per-vertex colors. SkAutoTUnref<const GrFragmentProcessor> aufp; const GrFragmentProcessor* shaderFP = nullptr; if (!primColorMode || blend_requires_shader(*primColorMode, primitiveIsSrc)) { if (shaderProcessor) { shaderFP = *shaderProcessor; } else if (const SkShader* shader = skPaint.getShader()) { aufp.reset(shader->asFragmentProcessor(context, viewM, nullptr, skPaint.getFilterQuality())); shaderFP = aufp; if (!shaderFP) { return false; } } } // Set this in below cases if the output of the shader/paint-color/paint-alpha/primXfermode is // a known constant value. In that case we can simply apply a color filter during this // conversion without converting the color filter to a GrFragmentProcessor. bool applyColorFilterToPaintColor = false; if (shaderFP) { if (primColorMode) { // There is a blend between the primitive color and the shader color. The shader sees // the opaque paint color. The shader's output is blended using the provided mode by // the primitive color. The blended color is then modulated by the paint's alpha. // The geometry processor will insert the primitive color to start the color chain, so // the GrPaint color will be ignored. GrColor shaderInput = SkColorToOpaqueGrColor(skPaint.getColor()); shaderFP = GrFragmentProcessor::OverrideInput(shaderFP, shaderInput); aufp.reset(shaderFP); if (primitiveIsSrc) { shaderFP = GrXfermodeFragmentProcessor::CreateFromDstProcessor(shaderFP, *primColorMode); } else { shaderFP = GrXfermodeFragmentProcessor::CreateFromSrcProcessor(shaderFP, *primColorMode); } aufp.reset(shaderFP); // The above may return null if compose results in a pass through of the prim color. if (shaderFP) { grPaint->addColorFragmentProcessor(shaderFP); } GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); if (GrColor_WHITE != paintAlpha) { grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create( paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref(); } } else { // The shader's FP sees the paint unpremul color grPaint->setColor(SkColorToUnpremulGrColor(skPaint.getColor())); grPaint->addColorFragmentProcessor(shaderFP); } } else { if (primColorMode) { // There is a blend between the primitive color and the paint color. The blend considers // the opaque paint color. The paint's alpha is applied to the post-blended color. SkAutoTUnref<const GrFragmentProcessor> processor( GrConstColorProcessor::Create(SkColorToOpaqueGrColor(skPaint.getColor()), GrConstColorProcessor::kIgnore_InputMode)); if (primitiveIsSrc) { processor.reset(GrXfermodeFragmentProcessor::CreateFromDstProcessor(processor, *primColorMode)); } else { processor.reset(GrXfermodeFragmentProcessor::CreateFromSrcProcessor(processor, *primColorMode)); } if (processor) { grPaint->addColorFragmentProcessor(processor); } grPaint->setColor(SkColorToOpaqueGrColor(skPaint.getColor())); GrColor paintAlpha = SkColorAlphaToGrColor(skPaint.getColor()); if (GrColor_WHITE != paintAlpha) { grPaint->addColorFragmentProcessor(GrConstColorProcessor::Create( paintAlpha, GrConstColorProcessor::kModulateRGBA_InputMode))->unref(); } } else { // No shader, no primitive color. grPaint->setColor(SkColorToPremulGrColor(skPaint.getColor())); applyColorFilterToPaintColor = true; } } SkColorFilter* colorFilter = skPaint.getColorFilter(); if (colorFilter) { if (applyColorFilterToPaintColor) { grPaint->setColor(SkColorToPremulGrColor(colorFilter->filterColor(skPaint.getColor()))); } else { SkAutoTUnref<const GrFragmentProcessor> cfFP( colorFilter->asFragmentProcessor(context)); if (cfFP) { grPaint->addColorFragmentProcessor(cfFP); } else { return false; } } } // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on // the GrPaint to also be null (also kSrcOver). SkASSERT(!grPaint->getXPFactory()); SkXfermode* xfermode = skPaint.getXfermode(); if (xfermode) { // SafeUnref in case a new xfermode is added that returns null. // In such cases we will fall back to kSrcOver_Mode. SkSafeUnref(grPaint->setXPFactory(xfermode->asXPFactory())); } #ifndef SK_IGNORE_GPU_DITHER if (skPaint.isDither() && grPaint->numColorFragmentProcessors() > 0) { grPaint->addColorFragmentProcessor(GrDitherEffect::Create())->unref(); } #endif return true; }
void SkComposeShader::ComposeShaderContext::shadeSpan(int x, int y, SkPMColor result[], int count) { SkShader::Context* shaderContextA = fShaderContextA; SkShader::Context* shaderContextB = fShaderContextB; SkXfermode* mode = static_cast<const SkComposeShader&>(fShader).fMode; unsigned scale = SkAlpha255To256(this->getPaintAlpha()); #ifdef SK_BUILD_FOR_ANDROID scale = 256; // ugh -- maintain old bug/behavior for now #endif SkPMColor tmp[TMP_COLOR_COUNT]; if (NULL == mode) { // implied SRC_OVER // TODO: when we have a good test-case, should use SkBlitRow::Proc32 // for these loops do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderContextA->shadeSpan(x, y, result, n); shaderContextB->shadeSpan(x, y, tmp, n); if (256 == scale) { for (int i = 0; i < n; i++) { result[i] = SkPMSrcOver(tmp[i], result[i]); } } else { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(SkPMSrcOver(tmp[i], result[i]), scale); } } result += n; x += n; count -= n; } while (count > 0); } else { // use mode for the composition do { int n = count; if (n > TMP_COLOR_COUNT) { n = TMP_COLOR_COUNT; } shaderContextA->shadeSpan(x, y, result, n); shaderContextB->shadeSpan(x, y, tmp, n); mode->xfer32(result, tmp, n, NULL); if (256 != scale) { for (int i = 0; i < n; i++) { result[i] = SkAlphaMulQ(result[i], scale); } } result += n; x += n; count -= n; } while (count > 0); } }
void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) { SkPMColor* span = fBuffer; uint32_t* device = fDevice.getAddr32(x, y); SkShader* shader = fShader; if (fXfermode) { for (;;) { SkXfermode* xfer = fXfermode; int count = *runs; if (count <= 0) break; int aa = *antialias; if (aa) { shader->shadeSpan(x, y, span, count); if (aa == 255) { xfer->xfer32(device, span, count, NULL); } else { // count is almost always 1 for (int i = count - 1; i >= 0; --i) { xfer->xfer32(&device[i], &span[i], 1, antialias); } } } device += count; runs += count; antialias += count; x += count; } } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { for (;;) { int count = *runs; if (count <= 0) { break; } int aa = *antialias; if (aa) { if (aa == 255) { // cool, have the shader draw right into the device shader->shadeSpan(x, y, device, count); } else { shader->shadeSpan(x, y, span, count); fProc32Blend(device, span, count, aa); } } device += count; runs += count; antialias += count; x += count; } } else { // no xfermode but the shader not opaque for (;;) { int count = *runs; if (count <= 0) { break; } int aa = *antialias; if (aa) { fShader->shadeSpan(x, y, span, count); if (aa == 255) { fProc32(device, span, count, 255); } else { fProc32Blend(device, span, count, aa); } } device += count; runs += count; antialias += count; x += count; } } }