1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkCoreBlitters.h"
11#include "SkColorPriv.h"
12#include "SkShader.h"
13#include "SkXfermode.h"
14
15SkA8_Blitter::SkA8_Blitter(const SkBitmap& device, const SkPaint& paint)
16        : INHERITED(device) {
17    fSrcA = paint.getAlpha();
18}
19
20const SkBitmap* SkA8_Blitter::justAnOpaqueColor(uint32_t* value) {
21    if (255 == fSrcA) {
22        *value = 255;
23        return &fDevice;
24    }
25    return NULL;
26}
27
28void SkA8_Blitter::blitH(int x, int y, int width) {
29    SkASSERT(x >= 0 && y >= 0 &&
30             (unsigned)(x + width) <= (unsigned)fDevice.width());
31
32    if (fSrcA == 0) {
33        return;
34    }
35
36    uint8_t* device = fDevice.getAddr8(x, y);
37
38    if (fSrcA == 255) {
39        memset(device, 0xFF, width);
40    } else {
41        unsigned scale = 256 - SkAlpha255To256(fSrcA);
42        unsigned srcA = fSrcA;
43
44        for (int i = 0; i < width; i++) {
45            device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
46        }
47    }
48}
49
50void SkA8_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
51                             const int16_t runs[]) {
52    if (fSrcA == 0) {
53        return;
54    }
55
56    uint8_t*    device = fDevice.getAddr8(x, y);
57    unsigned    srcA = fSrcA;
58
59    for (;;) {
60        int count = runs[0];
61        SkASSERT(count >= 0);
62        if (count == 0) {
63            return;
64        }
65        unsigned aa = antialias[0];
66
67        if (aa == 255 && srcA == 255) {
68            memset(device, 0xFF, count);
69        } else {
70            unsigned sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
71            unsigned scale = 256 - sa;
72
73            for (int i = 0; i < count; i++) {
74                device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
75            }
76        }
77        runs += count;
78        antialias += count;
79        device += count;
80    }
81}
82
83/////////////////////////////////////////////////////////////////////////////////////
84
85#define solid_8_pixels(mask, dst)           \
86    do {                                    \
87        if (mask & 0x80) dst[0] = 0xFF;     \
88        if (mask & 0x40) dst[1] = 0xFF;     \
89        if (mask & 0x20) dst[2] = 0xFF;     \
90        if (mask & 0x10) dst[3] = 0xFF;     \
91        if (mask & 0x08) dst[4] = 0xFF;     \
92        if (mask & 0x04) dst[5] = 0xFF;     \
93        if (mask & 0x02) dst[6] = 0xFF;     \
94        if (mask & 0x01) dst[7] = 0xFF;     \
95    } while (0)
96
97#define SK_BLITBWMASK_NAME                  SkA8_BlitBW
98#define SK_BLITBWMASK_ARGS
99#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst)
100#define SK_BLITBWMASK_GETADDR               getAddr8
101#define SK_BLITBWMASK_DEVTYPE               uint8_t
102#include "SkBlitBWMaskTemplate.h"
103
104static inline void blend_8_pixels(U8CPU bw, uint8_t dst[], U8CPU sa,
105                                  unsigned dst_scale) {
106    if (bw & 0x80) dst[0] = SkToU8(sa + SkAlphaMul(dst[0], dst_scale));
107    if (bw & 0x40) dst[1] = SkToU8(sa + SkAlphaMul(dst[1], dst_scale));
108    if (bw & 0x20) dst[2] = SkToU8(sa + SkAlphaMul(dst[2], dst_scale));
109    if (bw & 0x10) dst[3] = SkToU8(sa + SkAlphaMul(dst[3], dst_scale));
110    if (bw & 0x08) dst[4] = SkToU8(sa + SkAlphaMul(dst[4], dst_scale));
111    if (bw & 0x04) dst[5] = SkToU8(sa + SkAlphaMul(dst[5], dst_scale));
112    if (bw & 0x02) dst[6] = SkToU8(sa + SkAlphaMul(dst[6], dst_scale));
113    if (bw & 0x01) dst[7] = SkToU8(sa + SkAlphaMul(dst[7], dst_scale));
114}
115
116#define SK_BLITBWMASK_NAME                  SkA8_BlendBW
117#define SK_BLITBWMASK_ARGS                  , U8CPU sa, unsigned dst_scale
118#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, sa, dst_scale)
119#define SK_BLITBWMASK_GETADDR               getAddr8
120#define SK_BLITBWMASK_DEVTYPE               uint8_t
121#include "SkBlitBWMaskTemplate.h"
122
123void SkA8_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
124    if (fSrcA == 0) {
125        return;
126    }
127
128    if (mask.fFormat == SkMask::kBW_Format) {
129        if (fSrcA == 0xFF) {
130            SkA8_BlitBW(fDevice, mask, clip);
131        } else {
132            SkA8_BlendBW(fDevice, mask, clip, fSrcA,
133                         SkAlpha255To256(255 - fSrcA));
134        }
135        return;
136    }
137
138    int x = clip.fLeft;
139    int y = clip.fTop;
140    int width = clip.width();
141    int height = clip.height();
142    uint8_t* device = fDevice.getAddr8(x, y);
143    const uint8_t* alpha = mask.getAddr8(x, y);
144    unsigned    srcA = fSrcA;
145
146    while (--height >= 0) {
147        for (int i = width - 1; i >= 0; --i) {
148            unsigned sa;
149            // scale our src by the alpha value
150            {
151                int aa = alpha[i];
152                if (aa == 0) {
153                    continue;
154                }
155                if (aa == 255) {
156                    if (srcA == 255) {
157                        device[i] = 0xFF;
158                        continue;
159                    }
160                    sa = srcA;
161                } else {
162                    sa = SkAlphaMul(srcA, SkAlpha255To256(aa));
163                }
164            }
165
166            int scale = 256 - SkAlpha255To256(sa);
167            device[i] = SkToU8(sa + SkAlphaMul(device[i], scale));
168        }
169        device += fDevice.rowBytes();
170        alpha += mask.fRowBytes;
171    }
172}
173
174///////////////////////////////////////////////////////////////////////////////
175
176void SkA8_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
177    if (fSrcA == 0) {
178        return;
179    }
180
181    unsigned sa = SkAlphaMul(fSrcA, SkAlpha255To256(alpha));
182    uint8_t* device = fDevice.getAddr8(x, y);
183    size_t   rowBytes = fDevice.rowBytes();
184
185    if (sa == 0xFF) {
186        for (int i = 0; i < height; i++) {
187            *device = SkToU8(sa);
188            device += rowBytes;
189        }
190    } else {
191        unsigned scale = 256 - SkAlpha255To256(sa);
192
193        for (int i = 0; i < height; i++) {
194            *device = SkToU8(sa + SkAlphaMul(*device, scale));
195            device += rowBytes;
196        }
197    }
198}
199
200void SkA8_Blitter::blitRect(int x, int y, int width, int height) {
201    SkASSERT(x >= 0 && y >= 0 &&
202             (unsigned)(x + width) <= (unsigned)fDevice.width() &&
203             (unsigned)(y + height) <= (unsigned)fDevice.height());
204
205    if (fSrcA == 0) {
206        return;
207    }
208
209    uint8_t*    device = fDevice.getAddr8(x, y);
210    unsigned    srcA = fSrcA;
211
212    if (srcA == 255) {
213        while (--height >= 0) {
214            memset(device, 0xFF, width);
215            device += fDevice.rowBytes();
216        }
217    } else {
218        unsigned scale = 256 - SkAlpha255To256(srcA);
219
220        while (--height >= 0) {
221            for (int i = 0; i < width; i++) {
222                device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
223            }
224            device += fDevice.rowBytes();
225        }
226    }
227}
228
229///////////////////////////////////////////////////////////////////////
230
231SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkBitmap& device, const SkPaint& paint,
232                                         SkShader::Context* shaderContext)
233    : INHERITED(device, paint, shaderContext) {
234    if ((fXfermode = paint.getXfermode()) != NULL) {
235        fXfermode->ref();
236        SkASSERT(fShaderContext);
237    }
238
239    int width = device.width();
240    fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2)));
241    fAAExpand = (uint8_t*)(fBuffer + width);
242}
243
244SkA8_Shader_Blitter::~SkA8_Shader_Blitter() {
245    if (fXfermode) SkSafeUnref(fXfermode);
246    sk_free(fBuffer);
247}
248
249void SkA8_Shader_Blitter::blitH(int x, int y, int width) {
250    SkASSERT(x >= 0 && y >= 0 &&
251             (unsigned)(x + width) <= (unsigned)fDevice.width());
252
253    uint8_t* device = fDevice.getAddr8(x, y);
254    SkShader::Context* shaderContext = fShaderContext;
255
256    if ((shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag) && !fXfermode) {
257        memset(device, 0xFF, width);
258    } else {
259        SkPMColor*  span = fBuffer;
260
261        shaderContext->shadeSpan(x, y, span, width);
262        if (fXfermode) {
263            fXfermode->xferA8(device, span, width, NULL);
264        } else {
265            for (int i = width - 1; i >= 0; --i) {
266                unsigned    srcA = SkGetPackedA32(span[i]);
267                unsigned    scale = 256 - SkAlpha255To256(srcA);
268
269                device[i] = SkToU8(srcA + SkAlphaMul(device[i], scale));
270            }
271        }
272    }
273}
274
275static inline uint8_t aa_blend8(SkPMColor src, U8CPU da, int aa) {
276    SkASSERT((unsigned)aa <= 255);
277
278    int src_scale = SkAlpha255To256(aa);
279    int sa = SkGetPackedA32(src);
280    int dst_scale = 256 - SkAlphaMul(sa, src_scale);
281
282    return SkToU8((sa * src_scale + da * dst_scale) >> 8);
283}
284
285void SkA8_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
286                                    const int16_t runs[]) {
287    SkShader::Context* shaderContext = fShaderContext;
288    SkXfermode*        mode = fXfermode;
289    uint8_t*           aaExpand = fAAExpand;
290    SkPMColor*         span = fBuffer;
291    uint8_t*           device = fDevice.getAddr8(x, y);
292    int                opaque = shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag;
293
294    for (;;) {
295        int count = *runs;
296        if (count == 0) {
297            break;
298        }
299        int aa = *antialias;
300        if (aa) {
301            if (opaque && aa == 255 && mode == NULL) {
302                memset(device, 0xFF, count);
303            } else {
304                shaderContext->shadeSpan(x, y, span, count);
305                if (mode) {
306                    memset(aaExpand, aa, count);
307                    mode->xferA8(device, span, count, aaExpand);
308                } else {
309                    for (int i = count - 1; i >= 0; --i) {
310                        device[i] = aa_blend8(span[i], device[i], aa);
311                    }
312                }
313            }
314        }
315        device += count;
316        runs += count;
317        antialias += count;
318        x += count;
319    }
320}
321
322void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
323    if (mask.fFormat == SkMask::kBW_Format) {
324        this->INHERITED::blitMask(mask, clip);
325        return;
326    }
327
328    int x = clip.fLeft;
329    int y = clip.fTop;
330    int width = clip.width();
331    int height = clip.height();
332    uint8_t* device = fDevice.getAddr8(x, y);
333    const uint8_t* alpha = mask.getAddr8(x, y);
334    SkShader::Context* shaderContext = fShaderContext;
335
336    SkPMColor*  span = fBuffer;
337
338    while (--height >= 0) {
339        shaderContext->shadeSpan(x, y, span, width);
340        if (fXfermode) {
341            fXfermode->xferA8(device, span, width, alpha);
342        } else {
343            for (int i = width - 1; i >= 0; --i) {
344                device[i] = aa_blend8(span[i], device[i], alpha[i]);
345            }
346        }
347
348        y += 1;
349        device += fDevice.rowBytes();
350        alpha += mask.fRowBytes;
351    }
352}
353
354///////////////////////////////////////////////////////////////////////////////
355
356SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkBitmap& device,
357                             const SkPaint& paint) : SkRasterBlitter(device) {
358    SkASSERT(NULL == paint.getShader());
359    SkASSERT(NULL == paint.getXfermode());
360    SkASSERT(NULL == paint.getColorFilter());
361}
362
363void SkA8_Coverage_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
364                                      const int16_t runs[]) {
365    uint8_t* device = fDevice.getAddr8(x, y);
366    SkDEBUGCODE(int totalCount = 0;)
367
368    for (;;) {
369        int count = runs[0];
370        SkASSERT(count >= 0);
371        if (count == 0) {
372            return;
373        }
374        if (antialias[0]) {
375            memset(device, antialias[0], count);
376        }
377        runs += count;
378        antialias += count;
379        device += count;
380
381        SkDEBUGCODE(totalCount += count;)
382    }
383    SkASSERT(fDevice.width() == totalCount);
384}
385
386void SkA8_Coverage_Blitter::blitH(int x, int y, int width) {
387    memset(fDevice.getAddr8(x, y), 0xFF, width);
388}
389
390void SkA8_Coverage_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
391    if (0 == alpha) {
392        return;
393    }
394
395    uint8_t* dst = fDevice.getAddr8(x, y);
396    const size_t dstRB = fDevice.rowBytes();
397    while (--height >= 0) {
398        *dst = alpha;
399        dst += dstRB;
400    }
401}
402
403void SkA8_Coverage_Blitter::blitRect(int x, int y, int width, int height) {
404    uint8_t* dst = fDevice.getAddr8(x, y);
405    const size_t dstRB = fDevice.rowBytes();
406    while (--height >= 0) {
407        memset(dst, 0xFF, width);
408        dst += dstRB;
409    }
410}
411
412void SkA8_Coverage_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
413    SkASSERT(SkMask::kA8_Format == mask.fFormat);
414
415    int x = clip.fLeft;
416    int y = clip.fTop;
417    int width = clip.width();
418    int height = clip.height();
419
420    uint8_t* dst = fDevice.getAddr8(x, y);
421    const uint8_t* src = mask.getAddr8(x, y);
422    const size_t srcRB = mask.fRowBytes;
423    const size_t dstRB = fDevice.rowBytes();
424
425    while (--height >= 0) {
426        memcpy(dst, src, width);
427        dst += dstRB;
428        src += srcRB;
429    }
430}
431
432const SkBitmap* SkA8_Coverage_Blitter::justAnOpaqueColor(uint32_t*) {
433    return NULL;
434}
435