1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCoreBlitters.h"
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorPriv.h"
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkShader.h"
11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkUtils.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXfermode.h"
139fccaf03218080b80f8da85f5b422aca469f2b1breed@google.com#include "SkBlitMask.h"
14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
15c8ee9920ac53db56da7e53e591057f359f03693dreed@google.com///////////////////////////////////////////////////////////////////////////////
16c8ee9920ac53db56da7e53e591057f359f03693dreed@google.com
17e216b62841acd5db9d91b63960805568259a2e0ereed@android.comstatic void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
18935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com                            const SkIRect& clip, SkPMColor srcColor) {
19935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    U8CPU alpha = SkGetPackedA32(srcColor);
20935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
21935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    if (alpha != 255) {
22935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        flags |= SkBlitRow::kGlobalAlpha_Flag32;
23935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    }
24935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
25e216b62841acd5db9d91b63960805568259a2e0ereed@android.com
26e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    int x = clip.fLeft;
27e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    int y = clip.fTop;
28e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    int width = clip.width();
29e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    int height = clip.height();
30919114813d58933c9d9433b141e0222c34b700b1reed@google.com
31935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    SkPMColor*         dstRow = device.getAddr32(x, y);
32e2961f787751b880e535e893ca068af71218ba32reed@google.com    const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr8(x, y));
33e216b62841acd5db9d91b63960805568259a2e0ereed@android.com
34e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    do {
35935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        proc(dstRow, srcRow, width, alpha);
36e216b62841acd5db9d91b63960805568259a2e0ereed@android.com        dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
37e216b62841acd5db9d91b63960805568259a2e0ereed@android.com        srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
38e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    } while (--height != 0);
39e216b62841acd5db9d91b63960805568259a2e0ereed@android.com}
40e216b62841acd5db9d91b63960805568259a2e0ereed@android.com
41e216b62841acd5db9d91b63960805568259a2e0ereed@android.com//////////////////////////////////////////////////////////////////////////////////////
42e216b62841acd5db9d91b63960805568259a2e0ereed@android.com
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        : INHERITED(device) {
45def3e927ac43495ad443f186a1717cdfd15d1630reed@google.com    SkColor color = paint.getColor();
46def3e927ac43495ad443f186a1717cdfd15d1630reed@google.com    fColor = color;
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSrcA = SkColorGetA(color);
49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned scale = SkAlpha255To256(fSrcA);
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSrcR = SkAlphaMul(SkColorGetR(color), scale);
51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSrcG = SkAlphaMul(SkColorGetG(color), scale);
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fSrcB = SkAlphaMul(SkColorGetB(color), scale);
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB);
553c376b1cb0de6fe8e496a756742d117562c3f26dsenorblanco@chromium.org    fColor32Proc = SkBlitRow::ColorProcFactory();
56c0a3e317e6385742b150a2164adeda99c176b6ddtomhudson@google.com    fColorRect32Proc = SkBlitRow::ColorRectProcFactory();
57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) {
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (255 == fSrcA) {
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        *value = fPMColor;
62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return &fDevice;
63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return NULL;
65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300  // disable warning : local variable used without having been initialized
68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( push )
69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( disable : 4701 )
70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Blitter::blitH(int x, int y, int width) {
73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
753c376b1cb0de6fe8e496a756742d117562c3f26dsenorblanco@chromium.org    uint32_t*   device = fDevice.getAddr32(x, y);
763c376b1cb0de6fe8e496a756742d117562c3f26dsenorblanco@chromium.org    fColor32Proc(device, device, width, fPMColor);
77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                 const int16_t runs[]) {
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fSrcA == 0) {
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t    color = fPMColor;
86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case
88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (;;) {
90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int count = runs[0];
91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(count >= 0);
92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (count <= 0) {
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return;
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        unsigned aa = antialias[0];
96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (aa) {
97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if ((opaqueMask & aa) == 255) {
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                sk_memset32(device, color, count);
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            } else {
100cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
1013c376b1cb0de6fe8e496a756742d117562c3f26dsenorblanco@chromium.org                fColor32Proc(device, device, count, sc);
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs += count;
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        antialias += count;
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        device += count;
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//////////////////////////////////////////////////////////////////////////////////////
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define solid_8_pixels(mask, dst, color)    \
113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    do {                                    \
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x80) dst[0] = color;    \
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x40) dst[1] = color;    \
116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x20) dst[2] = color;    \
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x10) dst[3] = color;    \
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x08) dst[4] = color;    \
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x04) dst[5] = color;    \
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x02) dst[6] = color;    \
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x01) dst[7] = color;    \
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } while (0)
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlitBW
125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_ARGS                  , SkPMColor color
126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_GETADDR               getAddr32
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitBWMaskTemplate.h"
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define blend_8_pixels(mask, dst, sc, dst_scale)                            \
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    do {                                                                    \
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); }  \
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); }  \
135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); }  \
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); }  \
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); }  \
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); }  \
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); }  \
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); }  \
141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } while (0)
142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_NAME                  SkARGB32_BlendBW
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_ARGS                  , uint32_t sc, unsigned dst_scale
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sc, dst_scale)
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_GETADDR               getAddr32
147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SK_BLITBWMASK_DEVTYPE               uint32_t
148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitBWMaskTemplate.h"
149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(mask.fBounds.contains(clip));
152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(fSrcA != 0xFF);
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fSrcA == 0) {
155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1589bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
1599bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com        return;
1609bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com    }
1619bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com
162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
164e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    } else if (SkMask::kARGB32_Format == mask.fFormat) {
165935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask,
170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                       const SkIRect& clip) {
171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(mask.fBounds.contains(clip));
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1739bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com    if (SkBlitMask::BlitColor(fDevice, mask, clip, fColor)) {
1749bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com        return;
1759bed9d7780715fe1c6aae1df1ceee692a8c365a2reed@google.com    }
176935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (mask.fFormat == SkMask::kBW_Format) {
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
179e216b62841acd5db9d91b63960805568259a2e0ereed@android.com    } else if (SkMask::kARGB32_Format == mask.fFormat) {
180935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
181935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    }
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1845048d4852ca019b359ebdaffaec0e28fc8dcd689reed@google.com///////////////////////////////////////////////////////////////////////////////
185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (alpha == 0 || fSrcA == 0) {
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t* device = fDevice.getAddr32(x, y);
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t  color = fPMColor;
193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (alpha != 255) {
195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        color = SkAlphaMulQ(color, SkAlpha255To256(alpha));
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    unsigned dst_scale = 255 - SkGetPackedA32(color);
1992dcc8513452824388c1f2bb47cb4095cfd7abbfescroggo@google.com    size_t rowBytes = fDevice.rowBytes();
200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (--height >= 0) {
2015048d4852ca019b359ebdaffaec0e28fc8dcd689reed@google.com        device[0] = color + SkAlphaMulQ(device[0], dst_scale);
202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        device = (uint32_t*)((char*)device + rowBytes);
203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());
208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (fSrcA == 0) {
210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t    color = fPMColor;
215cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    size_t      rowBytes = fDevice.rowBytes();
216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
21754547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com    if (255 == SkGetPackedA32(color)) {
218c0a3e317e6385742b150a2164adeda99c176b6ddtomhudson@google.com        fColorRect32Proc(device, width, height, rowBytes, color);
21954547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com    } else {
22054547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com        while (--height >= 0) {
22154547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com            fColor32Proc(device, device, width, color);
22254547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com            device = (uint32_t*)((char*)device + rowBytes);
22354547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com        }
22454547aa4eb530859a7dd934aef008012dea19228tomhudson@google.com    }
225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#if defined _WIN32 && _MSC_VER >= 1300
228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#pragma warning ( pop )
229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif
230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////
232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                       const int16_t runs[]) {
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    for (;;) {
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int count = runs[0];
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(count >= 0);
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (count <= 0) {
242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return;
243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        unsigned aa = antialias[0];
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (aa) {
246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (aa == 255) {
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                sk_memset32(device, black, count);
248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            } else {
249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkPMColor src = aa << SK_A32_SHIFT;
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                unsigned dst_scale = 256 - aa;
251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                int n = count;
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                do {
253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    --n;
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    device[n] = src + SkAlphaMulQ(device[n], dst_scale);
255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                } while (n > 0);
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs += count;
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        antialias += count;
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        device += count;
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
26426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com///////////////////////////////////////////////////////////////////////////////
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
266e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com// Special version of SkBlitRow::Factory32 that knows we're in kSrc_Mode,
267e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com// instead of kSrcOver_Mode
268e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.comstatic void blend_srcmode(SkPMColor* SK_RESTRICT device,
269e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                          const SkPMColor* SK_RESTRICT span,
270e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                          int count, U8CPU aa) {
271e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    int aa256 = SkAlpha255To256(aa);
272e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    for (int i = 0; i < count; ++i) {
273e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        device[i] = SkFourByteInterp256(span[i], device[i], aa256);
274e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
275e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com}
276e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device,
278cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                            const SkPaint& paint) : INHERITED(device, paint) {
279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor)));
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
281cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    fXfermode = paint.getXfermode();
282cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    SkSafeRef(fXfermode);
283cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com
284cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    int flags = 0;
285cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    if (!(fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
286cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com        flags |= SkBlitRow::kSrcPixelAlpha_Flag32;
287cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    }
288cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    // we call this on the output from the shader
289cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    fProc32 = SkBlitRow::Factory32(flags);
290cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    // we call this on the output from the shader + alpha from the aa buffer
291cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com    fProc32Blend = SkBlitRow::Factory32(flags | SkBlitRow::kGlobalAlpha_Flag32);
292e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
293e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    fShadeDirectlyIntoDevice = false;
294e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fXfermode == NULL) {
295e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
296e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            fShadeDirectlyIntoDevice = true;
297e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
298e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    } else {
299e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkXfermode::Mode mode;
300e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (fXfermode->asMode(&mode)) {
301e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (SkXfermode::kSrc_Mode == mode) {
302e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                fShadeDirectlyIntoDevice = true;
303e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                fProc32Blend = blend_srcmode;
304e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
305e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
306e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
307e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
308e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    fConstInY = SkToBool(fShader->getFlags() & SkShader::kConstInY32_Flag);
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
312919114813d58933c9d9433b141e0222c34b700b1reed@google.com    SkSafeUnref(fXfermode);
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    sk_free(fBuffer);
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Shader_Blitter::blitH(int x, int y, int width) {
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
321e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fShadeDirectlyIntoDevice) {
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fShader->shadeSpan(x, y, device, width);
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    } else {
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkPMColor*  span = fBuffer;
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fShader->shadeSpan(x, y, span, width);
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (fXfermode) {
327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fXfermode->xfer32(device, span, width, NULL);
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        } else {
329cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com            fProc32(device, span, width, 255);
330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
334f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.comvoid SkARGB32_Shader_Blitter::blitRect(int x, int y, int width, int height) {
335f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    SkASSERT(x >= 0 && y >= 0 &&
336f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com             x + width <= fDevice.width() && y + height <= fDevice.height());
337d16b9898e212b0b141b8849ce89e08dc23dadd39skia.committer@gmail.com
338f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    uint32_t*   device = fDevice.getAddr32(x, y);
339f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    size_t      deviceRB = fDevice.rowBytes();
340f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    SkShader*   shader = fShader;
341e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    SkPMColor*  span = fBuffer;
342e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
343e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fConstInY) {
344e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (fShadeDirectlyIntoDevice) {
345e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            // shade the first row directly into the device
346e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            fShader->shadeSpan(x, y, device, width);
347e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            span = device;
348e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            while (--height > 0) {
349e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
350e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                memcpy(device, span, width << 2);
351e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
352e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        } else {
353e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            fShader->shadeSpan(x, y, span, width);
354e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            SkXfermode* xfer = fXfermode;
355e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (xfer) {
356e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
357e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    xfer->xfer32(device, span, width, NULL);
358e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
359e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
360e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
361e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } else {
362e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                SkBlitRow::Proc32 proc = fProc32;
363e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
364e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    proc(device, span, width, 255);
365e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
366e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
367e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
368e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
369e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
370e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        return;
371e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
372f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com
373e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fShadeDirectlyIntoDevice) {
374f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        void* ctx;
375f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
376f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        if (shadeProc) {
377f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            do {
378f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                shadeProc(ctx, x, y, device, width);
379f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                y += 1;
380f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
381f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            } while (--height > 0);
382f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        } else {
383f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            do {
384f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                shader->shadeSpan(x, y, device, width);
385f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                y += 1;
386f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
387f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            } while (--height > 0);
388f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        }
389f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    } else {
390f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        SkXfermode* xfer = fXfermode;
391f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        if (xfer) {
392f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            do {
393f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                shader->shadeSpan(x, y, span, width);
394f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                xfer->xfer32(device, span, width, NULL);
395f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                y += 1;
396f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
397f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            } while (--height > 0);
398f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        } else {
399f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            SkBlitRow::Proc32 proc = fProc32;
400f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            do {
401f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                shader->shadeSpan(x, y, span, width);
402f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                proc(device, span, width, 255);
403f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                y += 1;
404f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
405f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com            } while (--height > 0);
406f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com        }
407f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com    }
408f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com}
409f1bbd533e266687c5c2b6b406e06ae28bc500920reed@google.com
410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                                        const int16_t runs[]) {
412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPMColor*  span = fBuffer;
413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    uint32_t*   device = fDevice.getAddr32(x, y);
414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkShader*   shader = fShader;
415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
416e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fXfermode && !fShadeDirectlyIntoDevice) {
417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        for (;;) {
418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkXfermode* xfer = fXfermode;
419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int count = *runs;
421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (count <= 0)
422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                break;
423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int aa = *antialias;
424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (aa) {
425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                shader->shadeSpan(x, y, span, count);
426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                if (aa == 255) {
427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    xfer->xfer32(device, span, count, NULL);
428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                } else {
429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    // count is almost always 1
430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    for (int i = count - 1; i >= 0; --i) {
431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        xfer->xfer32(&device[i], &span[i], 1, antialias);
432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    }
433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            device += count;
436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            runs += count;
437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            antialias += count;
438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += count;
439919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
440e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    } else if (fShadeDirectlyIntoDevice ||
441e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com               (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        for (;;) {
443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int count = *runs;
444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (count <= 0) {
445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                break;
446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int aa = *antialias;
448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (aa) {
449cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                if (aa == 255) {
450cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                    // cool, have the shader draw right into the device
451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    shader->shadeSpan(x, y, device, count);
452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                } else {
453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    shader->shadeSpan(x, y, span, count);
454cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                    fProc32Blend(device, span, count, aa);
455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            device += count;
458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            runs += count;
459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            antialias += count;
460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += count;
461919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
462e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    } else {
463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        for (;;) {
464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int count = *runs;
465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (count <= 0) {
466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                break;
467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int aa = *antialias;
469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            if (aa) {
470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fShader->shadeSpan(x, y, span, count);
471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                if (aa == 255) {
472cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                    fProc32(device, span, count, 255);
473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                } else {
474cdbc582d7a596ad26571dc8c7e857f74d3a8ae7creed@android.com                    fProc32Blend(device, span, count, aa);
475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            device += count;
478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            runs += count;
479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            antialias += count;
480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += count;
481919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
48426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
48526cb94b362c50333cde0ed993dae6aa747b307dareed@google.comvoid SkARGB32_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
48626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    // we only handle kA8 with an xfermode
48726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    if (fXfermode && (SkMask::kA8_Format != mask.fFormat)) {
48826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        this->INHERITED::blitMask(mask, clip);
48926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        return;
49026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    }
49126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
49226cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    SkASSERT(mask.fBounds.contains(clip));
49326cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
49426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    SkBlitMask::RowProc proc = NULL;
49526cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    if (!fXfermode) {
49626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        unsigned flags = 0;
49726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) {
49826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            flags |= SkBlitMask::kSrcIsOpaque_RowFlag;
49926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        }
50026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        proc = SkBlitMask::RowFactory(SkBitmap::kARGB_8888_Config, mask.fFormat,
50126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com                                      (SkBlitMask::RowFlags)flags);
50226cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        if (NULL == proc) {
50326cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            this->INHERITED::blitMask(mask, clip);
50426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            return;
50526cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        }
50626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    }
50726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
50826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    const int x = clip.fLeft;
50926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    const int width = clip.width();
51026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    int y = clip.fTop;
51126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    int height = clip.height();
51226cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
51326cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    char* dstRow = (char*)fDevice.getAddr32(x, y);
51426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    const size_t dstRB = fDevice.rowBytes();
51526cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
51626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    const size_t maskRB = mask.fRowBytes;
51726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
51826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    SkShader* shader = fShader;
51926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    SkPMColor* span = fBuffer;
52026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
52126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    if (fXfermode) {
52226cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        SkASSERT(SkMask::kA8_Format == mask.fFormat);
52326cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        SkXfermode* xfer = fXfermode;
52426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        do {
52526cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            shader->shadeSpan(x, y, span, width);
52626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            xfer->xfer32((SkPMColor*)dstRow, span, width, maskRow);
52726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            dstRow += dstRB;
52826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            maskRow += maskRB;
52926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            y += 1;
53026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        } while (--height > 0);
53126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    } else {
53226cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        do {
53326cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            shader->shadeSpan(x, y, span, width);
53426cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            proc(dstRow, maskRow, span, width);
53526cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            dstRow += dstRB;
53626cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            maskRow += maskRB;
53726cb94b362c50333cde0ed993dae6aa747b307dareed@google.com            y += 1;
53826cb94b362c50333cde0ed993dae6aa747b307dareed@google.com        } while (--height > 0);
53926cb94b362c50333cde0ed993dae6aa747b307dareed@google.com    }
54026cb94b362c50333cde0ed993dae6aa747b307dareed@google.com}
54126cb94b362c50333cde0ed993dae6aa747b307dareed@google.com
542e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.comvoid SkARGB32_Shader_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
543e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
544713a335d7ed43207cb059d437c4dde44cc0f86a4skia.committer@gmail.com
545e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    uint32_t*   device = fDevice.getAddr32(x, y);
546e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    size_t      deviceRB = fDevice.rowBytes();
547e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    SkShader*   shader = fShader;
548713a335d7ed43207cb059d437c4dde44cc0f86a4skia.committer@gmail.com
549e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fConstInY) {
550e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkPMColor c;
551e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        fShader->shadeSpan(x, y, &c, 1);
552e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
553e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (fShadeDirectlyIntoDevice) {
554e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (255 == alpha) {
555e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
556e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    *device = c;
557e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
558e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
559e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } else {
560e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
561e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    *device = SkFourByteInterp(c, *device, alpha);
562e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
563e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
564e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
565e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        } else {
566e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            SkXfermode* xfer = fXfermode;
567e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (xfer) {
568e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
569e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    xfer->xfer32(device, &c, 1, &alpha);
570e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
571e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
572e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } else {
5737a154279d801eb51ccec5f1f8bffec73c7998ae9reed@google.com                SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
574e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
575e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    proc(device, &c, 1, alpha);
576e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
577e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
578e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
579e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
580e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        return;
581e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
582e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
583e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (fShadeDirectlyIntoDevice) {
584e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        void* ctx;
585e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkShader::ShadeProc shadeProc = fShader->asAShadeProc(&ctx);
586e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (255 == alpha) {
587e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (shadeProc) {
588e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
589e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    shadeProc(ctx, x, y, device, 1);
590e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
591e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
592e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
593e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } else {
594e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
595e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    shader->shadeSpan(x, y, device, 1);
596e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
597e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
598e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
599e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
600e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        } else {    // alpha < 255
601e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            SkPMColor c;
602e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            if (shadeProc) {
603e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
604e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    shadeProc(ctx, x, y, &c, 1);
605e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    *device = SkFourByteInterp(c, *device, alpha);
606e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
607e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
608e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
609e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } else {
610e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                do {
611e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    shader->shadeSpan(x, y, &c, 1);
612e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    *device = SkFourByteInterp(c, *device, alpha);
613e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    y += 1;
614e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                    device = (uint32_t*)((char*)device + deviceRB);
615e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                } while (--height > 0);
616e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            }
617e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
618e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    } else {
619e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkPMColor* span = fBuffer;
620e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkXfermode* xfer = fXfermode;
621e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        if (xfer) {
622e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            do {
623e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                shader->shadeSpan(x, y, span, 1);
624e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                xfer->xfer32(device, span, 1, &alpha);
625e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                y += 1;
626e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
627e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } while (--height > 0);
628e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        } else {
6296f8396a6040707a706b87658817c225d373ee859reed@google.com            SkBlitRow::Proc32 proc = (255 == alpha) ? fProc32 : fProc32Blend;
630e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            do {
631e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                shader->shadeSpan(x, y, span, 1);
6326f8396a6040707a706b87658817c225d373ee859reed@google.com                proc(device, span, 1, alpha);
633e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                y += 1;
634e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com                device = (uint32_t*)((char*)device + deviceRB);
635e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com            } while (--height > 0);
636e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        }
637e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
638e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com}
639