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); } }
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); } }
static void srcover_row(SK_RESTRICT SkPMColor dst[], const SK_RESTRICT SkPMColor16 src[], int count) { do { *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); src += 1; dst += 1; } while (--count != 0); }
void alphaBlendPremultiplied(blink::ImageFrame& src, blink::ImageFrame& dst, int canvasY, int left, int width) { for (int x = 0; x < width; ++x) { int canvasX = left + x; blink::ImageFrame::PixelData& pixel = *src.getAddr(canvasX, canvasY); if (SkGetPackedA32(pixel) != 0xff) { blink::ImageFrame::PixelData prevPixel = *dst.getAddr(canvasX, canvasY); pixel = SkPMSrcOver(pixel, prevPixel); } } }
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); for (int i = count - 1; i >= 0; --i) { if (span[i]) { device[i] = SkBlendARGB32(span[i], device[i], aa); } } } } device += count; runs += count; antialias += count; x += count; } } else { // no xfermode but we are not opaque for (;;) { int count = *runs; if (count <= 0) { break; } int aa = *antialias; if (aa) { fShader->shadeSpan(x, y, span, count); if (aa == 255) { for (int i = count - 1; i >= 0; --i) { if (span[i]) { device[i] = SkPMSrcOver(span[i], device[i]); } } } else { for (int i = count - 1; i >= 0; --i) { if (span[i]) { device[i] = SkBlendARGB32(span[i], device[i], aa); } } } } device += count; runs += count; antialias += count; x += count; } } }
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); } }