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