return false;
}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+ const uint8_t* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ int i, octuple = (count + 7) >> 3;
+ for (i = 0; i < octuple; ++i) {
+ int m = *mask++;
+ if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+ if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
+ if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
+ if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
+ if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
+ if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
+ if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
+ if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
+ src += 8;
+ dst += 8;
+ }
+ count &= 7;
+ if (count > 0) {
+ int m = *mask;
+ do {
+ if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+ m <<= 1;
+ src += 1;
+ dst += 1;
+ } while (--count > 0);
+ }
+}
+
+static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+ const uint8_t* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ int i, octuple = (count + 7) >> 3;
+ for (i = 0; i < octuple; ++i) {
+ int m = *mask++;
+ if (m & 0x80) { dst[0] = src[0]; }
+ if (m & 0x40) { dst[1] = src[1]; }
+ if (m & 0x20) { dst[2] = src[2]; }
+ if (m & 0x10) { dst[3] = src[3]; }
+ if (m & 0x08) { dst[4] = src[4]; }
+ if (m & 0x04) { dst[5] = src[5]; }
+ if (m & 0x02) { dst[6] = src[6]; }
+ if (m & 0x01) { dst[7] = src[7]; }
+ src += 8;
+ dst += 8;
+ }
+ count &= 7;
+ if (count > 0) {
+ int m = *mask;
+ do {
+ if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
+ m <<= 1;
+ src += 1;
+ dst += 1;
+ } while (--count > 0);
+ }
+}
+
+static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+ const uint8_t* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ for (int i = 0; i < count; ++i) {
+ if (mask[i]) {
+ dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
+ }
+ }
+}
+
+// expand the steps that SkAlphaMulQ performs, but this way we can
+// exand.. add.. combine
+// instead of
+// expand..combine add expand..combine
+//
+#define EXPAND0(v, m, s) ((v) & (m)) * (s)
+#define EXPAND1(v, m, s) (((v) >> 8) & (m)) * (s)
+#define COMBINE(e0, e1, m) ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
+
+static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+ const uint8_t* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ const uint32_t rbmask = gMask_00FF00FF;
+ for (int i = 0; i < count; ++i) {
+ int m = mask[i];
+ if (m) {
+ m += (m >> 7);
+#if 0
+ dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
+#else
+ uint32_t v = src[i];
+ uint32_t s0 = EXPAND0(v, rbmask, m);
+ uint32_t s1 = EXPAND1(v, rbmask, m);
+ v = dst[i];
+ uint32_t d0 = EXPAND0(v, rbmask, m);
+ uint32_t d1 = EXPAND1(v, rbmask, m);
+ dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
+#endif
+ }
+ }
+}
+
+static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ for (int i = 0; i < count; ++i) {
+ uint16_t m = mask[i];
+ if (0 == m) {
+ continue;
+ }
+
+ SkPMColor s = src[i];
+ SkPMColor d = dst[i];
+
+ int srcA = SkGetPackedA32(s);
+ int srcR = SkGetPackedR32(s);
+ int srcG = SkGetPackedB32(s);
+ int srcB = SkGetPackedB32(s);
+
+ /* We want all of these in 5bits, hence the shifts in case one of them
+ * (green) is 6bits.
+ */
+ int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
+ int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
+ int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
+
+ // Now upscale them to 0..32, so we can use blend32
+ maskR = upscale31To32(maskR);
+ maskG = upscale31To32(maskG);
+ maskB = upscale31To32(maskB);
+
+ maskR = maskR * srcA >> 8;
+ maskG = maskG * srcA >> 8;
+ maskB = maskB * srcA >> 8;
+
+ int dstR = SkGetPackedR32(d);
+ int dstG = SkGetPackedG32(d);
+ int dstB = SkGetPackedB32(d);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ dst[i] = SkPackARGB32(0xFF,
+ blend32(srcR, dstR, maskR),
+ blend32(srcG, dstG, maskG),
+ blend32(srcB, dstB, maskB));
+ }
+}
+
+static void LCD16_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ for (int i = 0; i < count; ++i) {
+ uint16_t m = mask[i];
+ if (0 == m) {
+ continue;
+ }
+
+ SkPMColor s = src[i];
+ SkPMColor d = dst[i];
+
+ int srcR = SkGetPackedR32(s);
+ int srcG = SkGetPackedB32(s);
+ int srcB = SkGetPackedB32(s);
+
+ /* We want all of these in 5bits, hence the shifts in case one of them
+ * (green) is 6bits.
+ */
+ int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
+ int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
+ int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
+
+ // Now upscale them to 0..32, so we can use blend32
+ maskR = upscale31To32(maskR);
+ maskG = upscale31To32(maskG);
+ maskB = upscale31To32(maskB);
+
+ int dstR = SkGetPackedR32(d);
+ int dstG = SkGetPackedG32(d);
+ int dstB = SkGetPackedB32(d);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ dst[i] = SkPackARGB32(0xFF,
+ blend32(srcR, dstR, maskR),
+ blend32(srcG, dstG, maskG),
+ blend32(srcB, dstB, maskB));
+ }
+}
+
+static void LCD32_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ for (int i = 0; i < count; ++i) {
+ SkPMColor m = mask[i];
+ if (0 == m) {
+ continue;
+ }
+
+ SkPMColor s = src[i];
+ int srcA = SkGetPackedA32(s);
+ int srcR = SkGetPackedR32(s);
+ int srcG = SkGetPackedB32(s);
+ int srcB = SkGetPackedB32(s);
+
+ srcA = SkAlpha255To256(srcA);
+
+ SkPMColor d = dst[i];
+
+ int maskR = SkGetPackedR32(m);
+ int maskG = SkGetPackedG32(m);
+ int maskB = SkGetPackedB32(m);
+
+ // Now upscale them to 0..256, so we can use SkAlphaBlend
+ maskR = SkAlpha255To256(maskR);
+ maskG = SkAlpha255To256(maskG);
+ maskB = SkAlpha255To256(maskB);
+
+ maskR = maskR * srcA >> 8;
+ maskG = maskG * srcA >> 8;
+ maskB = maskB * srcA >> 8;
+
+ int dstR = SkGetPackedR32(d);
+ int dstG = SkGetPackedG32(d);
+ int dstB = SkGetPackedB32(d);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ dst[i] = SkPackARGB32(0xFF,
+ SkAlphaBlend(srcR, dstR, maskR),
+ SkAlphaBlend(srcG, dstG, maskG),
+ SkAlphaBlend(srcB, dstB, maskB));
+ }
+}
+
+static void LCD32_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
+ const SkPMColor* SK_RESTRICT mask,
+ const SkPMColor* SK_RESTRICT src, int count) {
+ for (int i = 0; i < count; ++i) {
+ SkPMColor m = mask[i];
+ if (0 == m) {
+ continue;
+ }
+
+ SkPMColor s = src[i];
+ SkPMColor d = dst[i];
+
+ int maskR = SkGetPackedR32(m);
+ int maskG = SkGetPackedG32(m);
+ int maskB = SkGetPackedB32(m);
+ int srcR = SkGetPackedR32(s);
+ int srcG = SkGetPackedB32(s);
+ int srcB = SkGetPackedB32(s);
+ int dstR = SkGetPackedR32(d);
+ int dstG = SkGetPackedG32(d);
+ int dstB = SkGetPackedB32(d);
+
+ // Now upscale them to 0..256, so we can use SkAlphaBlend
+ maskR = SkAlpha255To256(maskR);
+ maskG = SkAlpha255To256(maskG);
+ maskB = SkAlpha255To256(maskB);
+
+ // LCD blitting is only supported if the dst is known/required
+ // to be opaque
+ dst[i] = SkPackARGB32(0xFF,
+ SkAlphaBlend(srcR, dstR, maskR),
+ SkAlphaBlend(srcG, dstG, maskG),
+ SkAlphaBlend(srcB, dstB, maskB));
+ }
+}
+
+SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
+ SkMask::Format format,
+ RowFlags flags) {
+ RowProc proc = PlatformRowProcs(config, format, flags);
+ if (proc) {
+ return proc;
+ }
+
+ static const RowProc gProcs[] = {
+ // need X coordinate to handle BW
+ NULL, NULL, //(RowProc)BW_RowProc_Blend, (RowProc)BW_RowProc_Opaque,
+ (RowProc)A8_RowProc_Blend, (RowProc)A8_RowProc_Opaque,
+ (RowProc)LCD16_RowProc_Blend, (RowProc)LCD16_RowProc_Opaque,
+ (RowProc)LCD32_RowProc_Blend, (RowProc)LCD32_RowProc_Opaque,
+ };
+
+ int index;
+ switch (config) {
+ case SkBitmap::kARGB_8888_Config:
+ switch (format) {
+ case SkMask::kBW_Format: index = 0; break;
+ case SkMask::kA8_Format: index = 2; break;
+ case SkMask::kLCD16_Format: index = 4; break;
+ case SkMask::kLCD32_Format: index = 6; break;
+ default:
+ return NULL;
+ }
+ if (flags & kSrcIsOpaque_RowFlag) {
+ index |= 1;
+ }
+ SkASSERT((size_t)index < SK_ARRAY_COUNT(gProcs));
+ return gProcs[index];
+ default:
+ break;
+ }
+ return NULL;
+}
}
}
-//////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
const SkPaint& paint) : INHERITED(device, paint) {
}
}
-///////////////////////////////////////////////////////////////////////////////////////////////
-
void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
const int16_t runs[]) {
SkPMColor* span = fBuffer;
}
}
}
+
+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);
+ }
+}
+