SkBlitter_ARGB32.cpp revision 7989186dab6bc2f1c1927daf91bddd32b7fd8d0c
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
1358af9a64701540c7f8083bc22a42d0bae3a5583creed@google.com#include "SkBlitMask.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
15f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com///////////////////////////////////////////////////////////////////////////////
16f88d6765a594cf9fb0825b74779f74394a7ccc7areed@google.com
17f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comstatic void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
18f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com							const SkIRect& clip, SkPMColor srcColor) {
19f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	U8CPU alpha = SkGetPackedA32(srcColor);
20f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	if (alpha != 255) {
22f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com		flags |= SkBlitRow::kGlobalAlpha_Flag32;
23f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	}
24f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
26f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int x = clip.fLeft;
27f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int y = clip.fTop;
28f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int width = clip.width();
29f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    int height = clip.height();
3082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
31f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    SkPMColor*		 dstRow = device.getAddr32(x, y);
327989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com    const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
34f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    do {
35f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com		proc(dstRow, srcRow, width, alpha);
36f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com        srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    } while (--height != 0);
39f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com}
40f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
41f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com//////////////////////////////////////////////////////////////////////////////////////
42f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        : INHERITED(device) {
45ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com    SkColor color = paint.getColor();
46ee467ee79d449ebe6ae7f7946e613cc70a479c69reed@google.com    fColor = color;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcA = SkColorGetA(color);
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned scale = SkAlpha255To256(fSrcA);
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcR = SkAlphaMul(SkColorGetR(color), scale);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcG = SkAlphaMul(SkColorGetG(color), scale);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fSrcB = SkAlphaMul(SkColorGetB(color), scale);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
5529e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    fColor32Proc = SkBlitRow::ColorProcFactory();
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (255 == fSrcA) {
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *value = fPMColor;
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return &fDevice;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push )
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 )
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitH(int x, int y, int width) {
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7429e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    uint32_t*   device = fDevice.getAddr32(x, y);
7529e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org    fColor32Proc(device, device, width, fPMColor);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                 const int16_t runs[]) {
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t    color = fPMColor;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if ((opaqueMask & aa) == 255) {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(device, color, count);
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
99c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
10029e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org                fColor32Proc(device, device, count, sc);
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define solid_8_pixels(mask, dst, color)    \
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                    \
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) dst[0] = color;    \
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) dst[1] = color;    \
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) dst[2] = color;    \
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) dst[3] = color;    \
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) dst[4] = color;    \
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) dst[5] = color;    \
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) dst[6] = color;    \
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) dst[7] = color;    \
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , SkPMColor color
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr32
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define blend_8_pixels(mask, dst, sc, dst_scale)                            \
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    do {                                                                    \
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } while (0)
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR               getAddr32
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h"
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fSrcA != 0xFF);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
157edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
158edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        return;
159edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    }
160edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
163f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    } else if (SkMask::kARGB32_Format == mask.fFormat) {
164f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const SkIRect& clip) {
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
172edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
173edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com        return;
174edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com    }
175edb606cb999887d54629f361bcbf57c5fede1bb0reed@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
178f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com    } else if (SkMask::kARGB32_Format == mask.fFormat) {
179f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
180f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com	}
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (alpha == 0 || fSrcA == 0) {
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t* device = fDevice.getAddr32(x, y);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t  color = fPMColor;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (alpha != 255) {
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned dst_scale = 255 - SkGetPackedA32(color);
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t prevDst = ~device[0];
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t result  SK_INIT_TO_AVOID_WARNING;
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t rowBytes = fDevice.rowBytes();
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (--height >= 0) {
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        uint32_t dst = device[0];
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (dst != prevDst) {
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            result = color + SkAlphaMulQ(dst, dst_scale);
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            prevDst = dst;
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device[0] = result;
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device = (uint32_t*)((char*)device + rowBytes);
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fSrcA == 0) {
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t    color = fPMColor;
222c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    size_t      rowBytes = fDevice.rowBytes();
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
224c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    while (--height >= 0) {
22529e5054dd07c97c2195c5f64bf67aaa6b5afa204senorblanco@chromium.org        fColor32Proc(device, device, width, color);
226c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        device = (uint32_t*)((char*)device + rowBytes);
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop )
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                       const int16_t runs[]) {
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    for (;;) {
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (count <= 0) {
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned aa = antialias[0];
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (aa) {
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa == 255) {
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(device, black, count);
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            } else {
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkPMColor src = aa << SK_A32_SHIFT;
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                unsigned dst_scale = 256 - aa;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                int n = count;
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                do {
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    --n;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    device[n] = src + SkAlphaMulQ(device[n], dst_scale);
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } while (n > 0);
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        antialias += count;
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        device += count;
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
270c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                            const SkPaint& paint) : INHERITED(device, paint) {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
273c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    fXfermode = paint.getXfermode();
274c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    SkSafeRef(fXfermode);
275c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com
276c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    int flags = 0;
277c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
278c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
279c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    }
280c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // we call this on the output from the shader
281c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    fProc32 = SkBlitRow::Factory32(flags);
282c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    // we call this on the output from the shader + alpha from the aa buffer
283c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
28782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    SkSafeUnref(fXfermode);
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sk_free(fBuffer);
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fShader->shadeSpan(x, y, device, width);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else {
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkPMColor*  span = fBuffer;
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fShader->shadeSpan(x, y, span, width);
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (fXfermode) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fXfermode->xfer32(device, span, width, NULL);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        } else {
304c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com            fProc32(device, span, width, 255);
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////////////////
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                        const int16_t runs[]) {
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor*  span = fBuffer;
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*   shader = fShader;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (fXfermode) {
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkXfermode* xfer = fXfermode;
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0)
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                shader->shadeSpan(x, y, span, count);
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (aa == 255) {
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    xfer->xfer32(device, span, count, NULL);
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    // count is almost always 1
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    for (int i = count - 1; i >= 0; --i) {
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        xfer->xfer32(&device[i], &span[i], 1, antialias);
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
34082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
349c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                if (aa == 255) {
350c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    // cool, have the shader draw right into the device
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    shader->shadeSpan(x, y, device, count);
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    shader->shadeSpan(x, y, span, count);
354c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32Blend(device, span, count, aa);
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
36182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
362c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com    } else {    // no xfermode but the shader not opaque
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        for (;;) {
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int count = *runs;
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (count <= 0) {
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                break;
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int aa = *antialias;
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            if (aa) {
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fShader->shadeSpan(x, y, span, count);
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                if (aa == 255) {
372c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32(device, span, count, 255);
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                } else {
374c4cae85752e3e486cf4eac8cd8128f57b6f40563reed@android.com                    fProc32Blend(device, span, count, aa);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            device += count;
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += count;
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            antialias += count;
3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += count;
38182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
384