11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkCoreBlitters.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkXfermode.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint) 1687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger : INHERITED(device) { 1787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger fSrcA = paint.getAlpha(); 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerconst SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) { 2140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (255 == fSrcA) { 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *value = 255; 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return &fDevice; 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return NULL; 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Blitter::blitH(int x, int y, int width) { 2940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(x >= 0 && y >= 0 && 3040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (unsigned)(x + width) <= (unsigned)fDevice.width()); 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0) { 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 3440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 255) { 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(device, 0xFF, width); 4040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = 256 - SkAlpha255To256(fSrcA); 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = fSrcA; 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = 0; i < width; i++) { 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 5140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const int16_t runs[]) { 5240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0) { 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 5440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = fSrcA; 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (;;) { 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = runs[0]; 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(count >= 0); 6240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (count == 0) { 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 6440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned aa = antialias[0]; 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (aa == 255 && srcA == 255) { 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(device, 0xFF, count); 6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = 256 - sa; 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = 0; i < count; i++) { 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project runs += count; 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project antialias += count; 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += count; 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////////// 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define solid_8_pixels(mask, dst) \ 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { \ 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x80) dst[0] = 0xFF; \ 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x40) dst[1] = 0xFF; \ 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x20) dst[2] = 0xFF; \ 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x10) dst[3] = 0xFF; \ 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x08) dst[4] = 0xFF; \ 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x04) dst[5] = 0xFF; \ 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x02) dst[6] = 0xFF; \ 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mask & 0x01) dst[7] = 0xFF; \ 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (0) 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_NAME SkA8_BlitBW 9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#define SK_BLITBWMASK_ARGS 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst) 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_GETADDR getAddr8 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_DEVTYPE uint8_t 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitBWMaskTemplate.h" 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa, 10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger unsigned dst_scale) { 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale)); 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale)); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale)); 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale)); 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale)); 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale)); 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale)); 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale)); 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_NAME SkA8_BlendBW 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_ARGS , U8CPU sa, unsigned dst_scale 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sa, dst_scale) 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_GETADDR getAddr8 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SK_BLITBWMASK_DEVTYPE uint8_t 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitBWMaskTemplate.h" 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0) { 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (mask.fFormat == SkMask::kBW_Format) { 12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0xFF) { 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkA8_BlitBW(fDevice, mask, clip); 13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkA8_BlendBW(fDevice, mask, clip, fSrcA, 13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkAlpha255To256(255 - fSrcA)); 13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int x = clip.fLeft; 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int y = clip.fTop; 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width = clip.width(); 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int height = clip.height(); 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 1431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* alpha = mask.getAddr8(x, y); 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = fSrcA; 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (--height >= 0) { 14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = width - 1; i >= 0; --i) { 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sa; 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // scale our src by the alpha value 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int aa = alpha[i]; 15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (aa == 0) { 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project continue; 15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (aa == 255) { 15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (srcA == 255) { 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = 0xFF; 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project continue; 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sa = srcA; 16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sa = SkAlphaMul(srcA, SkAlpha255To256(aa)); 16340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scale = 256 - SkAlpha255To256(sa); 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = SkToU8(sa + SkAlphaMul(device[i], scale)); 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += fDevice.rowBytes(); 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project alpha += mask.fRowBytes; 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 17740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0) { 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 17940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha)); 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int rowBytes = fDevice.rowBytes(); 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (sa == 0xFF) { 18640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = 0; i < height; i++) { 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *device = SkToU8(sa); 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += rowBytes; 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = 256 - SkAlpha255To256(sa); 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = 0; i < height; i++) { 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *device = SkToU8(sa + SkAlphaMul(*device, scale)); 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += rowBytes; 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Blitter::blitRect(int x, int y, int width, int height) { 20140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(x >= 0 && y >= 0 && 20240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (unsigned)(x + width) <= (unsigned)fDevice.width() && 20340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (unsigned)(y + height) <= (unsigned)fDevice.height()); 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fSrcA == 0) { 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 20740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = fSrcA; 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (srcA == 255) { 21340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (--height >= 0) { 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(device, 0xFF, width); 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += fDevice.rowBytes(); 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = 256 - SkAlpha255To256(srcA); 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (--height >= 0) { 22140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = 0; i < width; i++) { 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += fDevice.rowBytes(); 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////// 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint) 23240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger : INHERITED(device, paint) { 23340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if ((fXfermode = paint.getXfermode()) != NULL) { 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fXfermode->ref(); 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fShader); 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width = device.width(); 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2))); 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fAAExpand = (uint8_t*)(fBuffer + width); 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkA8_Shader_Blitter::~SkA8_Shader_Blitter() { 24440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fXfermode) SkSafeUnref(fXfermode); 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_free(fBuffer); 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Shader_Blitter::blitH(int x, int y, int width) { 24940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(x >= 0 && y >= 0 && 25040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (unsigned)(x + width) <= (unsigned)fDevice.width()); 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if ((fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) { 2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(device, 0xFF, width); 25640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPMColor* span = fBuffer; 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fShader->shadeSpan(x, y, span, width); 26040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fXfermode) { 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fXfermode->xferA8(device, span, width, NULL); 26240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 26340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = width - 1; i >= 0; --i) { 2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned srcA = SkGetPackedA32(span[i]); 2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned scale = 256 - SkAlpha255To256(srcA); 2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale)); 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 27340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) { 2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)aa <= 255); 2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int src_scale = SkAlpha255To256(aa); 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int sa = SkGetPackedA32(src); 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int dst_scale = 256 - SkAlphaMul(sa, src_scale); 2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkToU8((sa * src_scale + da * dst_scale) >> 8); 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 28340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], 28440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const int16_t runs[]) { 2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkShader* shader = fShader; 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkXfermode* mode = fXfermode; 2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* aaExpand = fAAExpand; 2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPMColor* span = fBuffer; 2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int opaque = fShader->getFlags() & SkShader::kOpaqueAlpha_Flag; 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 29240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (;;) { 2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = *runs; 29440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (count == 0) { 2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 29640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int aa = *antialias; 29840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (aa) { 29940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (opaque && aa == 255 && mode == NULL) { 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(device, 0xFF, count); 30140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader->shadeSpan(x, y, span, count); 30340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (mode) { 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(aaExpand, aa, count); 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mode->xferA8(device, span, count, aaExpand); 30640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 30740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger for (int i = count - 1; i >= 0; --i) { 3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device[i] = aa_blend8(span[i], device[i], aa); 30940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += count; 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project runs += count; 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project antialias += count; 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x += count; 31740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 32040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergervoid SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { 32140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (mask.fFormat == SkMask::kBW_Format) { 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->INHERITED::blitMask(mask, clip); 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 32540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int x = clip.fLeft; 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int y = clip.fTop; 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width = clip.width(); 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int height = clip.height(); 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* device = fDevice.getAddr8(x, y); 3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* alpha = mask.getAddr8(x, y); 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPMColor* span = fBuffer; 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 33540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger while (--height >= 0) { 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fShader->shadeSpan(x, y, span, width); 33725c9ae8253171f35b9a14dd2adc5775929330e7bRomain Guy if (fXfermode) { 33825c9ae8253171f35b9a14dd2adc5775929330e7bRomain Guy fXfermode->xferA8(device, span, width, alpha); 33925c9ae8253171f35b9a14dd2adc5775929330e7bRomain Guy } 34040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project y += 1; 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device += fDevice.rowBytes(); 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project alpha += mask.fRowBytes; 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 347