SkBlitter_A8.cpp revision b95d9f566b08ba400cca027f639e400ef7384b38
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) 16eadc8072aaa8f6fc71f47cd41fab1ed3b4bc1c68mike@reedtribe.org : INHERITED(device) { 17eadc8072aaa8f6fc71f47cd41fab1ed3b4bc1c68mike@reedtribe.org fSrcA = paint.getAlpha(); 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { 2182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (255 == fSrcA) { 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *value = 255; 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return &fDevice; 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Blitter::blitH(int x, int y, int width) { 2982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkASSERT(x >= 0 && y >= 0 && 3082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com (unsigned)(x + width) <= (unsigned)fDevice.width()); 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0) { 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 255) { 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0xFF, width); 4082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = 256 - SkAlpha255To256(fSrcA); 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned srcA = fSrcA; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < width; i++) { 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 5182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 5282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0) { 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned srcA = fSrcA; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (;;) { 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = runs[0]; 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 0); 6282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (count == 0) { 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = antialias[0]; 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (aa == 255 && srcA == 255) { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0xFF, count); 6982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = 256 - sa; 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < count; i++) { 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define solid_8_pixels(mask, dst) \ 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { \ 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x80) dst[0] = 0xFF; \ 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x40) dst[1] = 0xFF; \ 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x20) dst[2] = 0xFF; \ 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x10) dst[3] = 0xFF; \ 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x08) dst[4] = 0xFF; \ 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x04) dst[5] = 0xFF; \ 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x02) dst[6] = 0xFF; \ 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x01) dst[7] = 0xFF; \ 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (0) 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME SkA8_BlitBW 9882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com#define SK_BLITBWMASK_ARGS 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst) 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR getAddr8 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE uint8_t 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h" 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, 10582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com unsigned dst_scale) { 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale)); 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale)); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale)); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale)); 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale)); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale)); 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale)); 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale)); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME SkA8_BlendBW 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_scale) 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR getAddr8 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE uint8_t 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h" 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 12482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0) { 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (mask.fFormat == SkMask::kBW_Format) { 12982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0xFF) { 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkA8_BlitBW(fDevice, mask, clip); 13182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 13282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkA8_BlendBW(fDevice, mask, clip, fSrcA, 13382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkAlpha255To256(255 - fSrcA)); 13482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = clip.fLeft; 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = clip.fTop; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = clip.width(); 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = clip.height(); 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 1437989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com const uint8_t* alpha = mask.getAddr8(x, y); 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned srcA = fSrcA; 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 14782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = width - 1; i >= 0; --i) { 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned sa; 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // scale our src by the alpha value 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = alpha[i]; 15282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (aa == 0) { 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 15482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 15582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (aa == 255) { 15682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (srcA == 255) { 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = 0xFF; 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sa = srcA; 16182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 16382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = 256 - SkAlpha255To256(sa); 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += fDevice.rowBytes(); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha += mask.fRowBytes; 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 17782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0) { 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha)); 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 183e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com size_t rowBytes = fDevice.rowBytes(); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (sa == 0xFF) { 18682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < height; i++) { 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkToU8(sa); 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += rowBytes; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = 256 - SkAlpha255To256(sa); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < height; i++) { 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkToU8(sa + SkAlphaMul(*device, scale)); 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += rowBytes; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Blitter::blitRect(int x, int y, int width, int height) { 20182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkASSERT(x >= 0 && y >= 0 && 20282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com (unsigned)(x + width) <= (unsigned)fDevice.width() && 20382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com (unsigned)(y + height) <= (unsigned)fDevice.height()); 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fSrcA == 0) { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 20782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned srcA = fSrcA; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (srcA == 255) { 21382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0xFF, width); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += fDevice.rowBytes(); 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = 256 - SkAlpha255To256(srcA); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 22182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = 0; i < width; i++) { 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += fDevice.rowBytes(); 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////// 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) 23282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com : INHERITED(device, paint) { 23382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if ((fXfermode = paint.getXfermode()) != NULL) { 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode->ref(); 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fShader); 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = device.width(); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2))); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAAExpand = (uint8_t*)(fBuffer + width); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkA8_Shader_Blitter::~SkA8_Shader_Blitter() { 24457f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com if (fXfermode) SkSafeUnref(fXfermode); 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(fBuffer); 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Shader_Blitter::blitH(int x, int y, int width) { 24982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkASSERT(x >= 0 && y >= 0 && 25082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com (unsigned)(x + width) <= (unsigned)fDevice.width()); 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0xFF, width); 25682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* span = fBuffer; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->shadeSpan(x, y, span, width); 26082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (fXfermode) { 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode->xferA8(device, span, width, NULL); 26282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 26382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = width - 1; i >= 0; --i) { 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned srcA = SkGetPackedA32(span[i]); 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = 256 - SkAlpha255To256(srcA); 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) { 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)aa <= 255); 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int src_scale = SkAlpha255To256(aa); 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sa = SkGetPackedA32(src); 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dst_scale = 256 - SkAlphaMul(sa, src_scale); 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkToU8((sa * src_scale + da * dst_scale) >> 8); 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 28482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fShader; 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXfermode* mode = fXfermode; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* aaExpand = fAAExpand; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* span = fBuffer; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag; 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 29282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (;;) { 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = *runs; 29482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (count == 0) { 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 29682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = *antialias; 29882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (aa) { 29982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (opaque && aa == 255 && mode == NULL) { 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0xFF, count); 30182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan(x, y, span, count); 30382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (mode) { 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(aaExpand, aa, count); 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mode->xferA8(device, span, count, aaExpand); 30682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 30782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (int i = count - 1; i >= 0; --i) { 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = aa_blend8(span[i], device[i], aa); 30982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 31782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 32082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 32182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (mask.fFormat == SkMask::kBW_Format) { 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->INHERITED::blitMask(mask, clip); 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 32582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = clip.fLeft; 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = clip.fTop; 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = clip.width(); 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = clip.height(); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* device = fDevice.getAddr8(x, y); 3317989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com const uint8_t* alpha = mask.getAddr8(x, y); 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* span = fBuffer; 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->shadeSpan(x, y, span, width); 33757f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com if (fXfermode) { 33857f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com fXfermode->xferA8(device, span, width, alpha); 33996583db7990ec524b6410c539518ebbc9844c5eccommit-bot@chromium.org } else { 34096583db7990ec524b6410c539518ebbc9844c5eccommit-bot@chromium.org for (int i = width - 1; i >= 0; --i) { 34196583db7990ec524b6410c539518ebbc9844c5eccommit-bot@chromium.org device[i] = aa_blend8(span[i], device[i], alpha[i]); 34296583db7990ec524b6410c539518ebbc9844c5eccommit-bot@chromium.org } 34357f4969724a1dd88c8d9ae35a863e6cf621181d5djsollen@google.com } 34482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y += 1; 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += fDevice.rowBytes(); 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha += mask.fRowBytes; 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 350126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 351126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com/////////////////////////////////////////////////////////////////////////////// 352126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 353126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comSkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkBitmap& device, 354126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkPaint& paint) : SkRasterBlitter(device) { 355126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(NULL == paint.getShader()); 356126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(NULL == paint.getXfermode()); 357126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(NULL == paint.getColorFilter()); 358126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 359126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 360126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comvoid SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 361126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const int16_t runs[]) { 362126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com uint8_t* device = fDevice.getAddr8(x, y); 363126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkDEBUGCODE(int totalCount = 0;) 364ab7442c8d733e0642d1cd80af23cdab43d77039eskia.committer@gmail.com 365126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com for (;;) { 366126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com int count = runs[0]; 367126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(count >= 0); 368126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com if (count == 0) { 369126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com return; 370126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 371b95d9f566b08ba400cca027f639e400ef7384b38reed@google.com if (antialias[0]) { 372126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com memset(device, antialias[0], count); 373126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 374126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com runs += count; 375126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com antialias += count; 376126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com device += count; 377126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 378126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkDEBUGCODE(totalCount += count;) 379126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 380126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(fDevice.width() == totalCount); 381126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 382126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 383126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comvoid SkA8_Coverage_Blitter::blitH(int x, int y, int width) { 384126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com memset(fDevice.getAddr8(x, y), 0xFF, width); 385126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 386126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 387126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comvoid SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 388126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com if (0 == alpha) { 389126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com return; 390126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 391b95d9f566b08ba400cca027f639e400ef7384b38reed@google.com 392126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com uint8_t* dst = fDevice.getAddr8(x, y); 393126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const size_t dstRB = fDevice.rowBytes(); 394126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com while (--height >= 0) { 395126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com *dst = alpha; 396126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com dst += dstRB; 397126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 398126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 399126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 400126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comvoid SkA8_Coverage_Blitter::blitRect(int x, int y, int width, int height) { 401126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com uint8_t* dst = fDevice.getAddr8(x, y); 402126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const size_t dstRB = fDevice.rowBytes(); 403126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com while (--height >= 0) { 404126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com memset(dst, 0xFF, width); 405126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com dst += dstRB; 406126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 407126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 408126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 409126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comvoid SkA8_Coverage_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 410126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(SkMask::kA8_Format == mask.fFormat); 411126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 412126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com int x = clip.fLeft; 413126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com int y = clip.fTop; 414126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com int width = clip.width(); 415126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com int height = clip.height(); 416126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 417126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com uint8_t* dst = fDevice.getAddr8(x, y); 418126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const uint8_t* src = mask.getAddr8(x, y); 419126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const size_t srcRB = mask.fRowBytes; 420126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const size_t dstRB = fDevice.rowBytes(); 421ab7442c8d733e0642d1cd80af23cdab43d77039eskia.committer@gmail.com 422126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com while (--height >= 0) { 423126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com memcpy(dst, src, width); 424126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com dst += dstRB; 425126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com src += srcRB; 426126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } 427126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 428126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com 429126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.comconst SkBitmap* SkA8_Coverage_Blitter::justAnOpaqueColor(uint32_t*) { 430126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com return NULL; 431126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com} 432