SkSpriteBlitter_ARGB32.cpp revision c240e719b2bebd3711ade4e6fe056921aa7b0521
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 "SkSpriteBlitter.h"
11#include "SkBlitRow.h"
12#include "SkColorFilter.h"
13#include "SkColorPriv.h"
14#include "SkTemplates.h"
15#include "SkUtils.h"
16#include "SkXfermode.h"
17
18///////////////////////////////////////////////////////////////////////////////
19
20class Sprite_D32_S32 : public SkSpriteBlitter {
21public:
22    Sprite_D32_S32(const SkPixmap& src, U8CPU alpha)  : INHERITED(src) {
23        SkASSERT(src.colorType() == kN32_SkColorType);
24
25        unsigned flags32 = 0;
26        if (255 != alpha) {
27            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
28        }
29        if (!src.isOpaque()) {
30            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
31        }
32
33        fProc32 = SkBlitRow::Factory32(flags32);
34        fAlpha = alpha;
35    }
36
37    void blitRect(int x, int y, int width, int height) override {
38        SkASSERT(width > 0 && height > 0);
39        uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
40        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
41        size_t dstRB = fDevice->rowBytes();
42        size_t srcRB = fSource.rowBytes();
43        SkBlitRow::Proc32 proc = fProc32;
44        U8CPU             alpha = fAlpha;
45
46        do {
47            proc(dst, src, width, alpha);
48            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
49            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
50        } while (--height != 0);
51    }
52
53private:
54    SkBlitRow::Proc32   fProc32;
55    U8CPU               fAlpha;
56
57    typedef SkSpriteBlitter INHERITED;
58};
59
60///////////////////////////////////////////////////////////////////////////////
61
62class Sprite_D32_XferFilter : public SkSpriteBlitter {
63public:
64    Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) {
65        fColorFilter = paint.getColorFilter();
66        SkSafeRef(fColorFilter);
67
68        fXfermode = paint.getXfermode();
69        SkSafeRef(fXfermode);
70
71        fBufferSize = 0;
72        fBuffer = NULL;
73
74        unsigned flags32 = 0;
75        if (255 != paint.getAlpha()) {
76            flags32 |= SkBlitRow::kGlobalAlpha_Flag32;
77        }
78        if (!source.isOpaque()) {
79            flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32;
80        }
81
82        fProc32 = SkBlitRow::Factory32(flags32);
83        fAlpha = paint.getAlpha();
84    }
85
86    virtual ~Sprite_D32_XferFilter() {
87        delete[] fBuffer;
88        SkSafeUnref(fXfermode);
89        SkSafeUnref(fColorFilter);
90    }
91
92    void setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override {
93        this->INHERITED::setup(device, left, top, paint);
94
95        int width = device.width();
96        if (width > fBufferSize) {
97            fBufferSize = width;
98            delete[] fBuffer;
99            fBuffer = new SkPMColor[width];
100        }
101    }
102
103protected:
104    SkColorFilter*      fColorFilter;
105    SkXfermode*         fXfermode;
106    int                 fBufferSize;
107    SkPMColor*          fBuffer;
108    SkBlitRow::Proc32   fProc32;
109    U8CPU               fAlpha;
110
111private:
112    typedef SkSpriteBlitter INHERITED;
113};
114
115///////////////////////////////////////////////////////////////////////////////
116
117class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter {
118public:
119    Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint)
120        : Sprite_D32_XferFilter(source, paint) {}
121
122    void blitRect(int x, int y, int width, int height) override {
123        SkASSERT(width > 0 && height > 0);
124        uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y);
125        const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop);
126        size_t dstRB = fDevice->rowBytes();
127        size_t srcRB = fSource.rowBytes();
128        SkColorFilter* colorFilter = fColorFilter;
129        SkXfermode* xfermode = fXfermode;
130
131        do {
132            const SkPMColor* tmp = src;
133
134            if (colorFilter) {
135                colorFilter->filterSpan(src, width, fBuffer);
136                tmp = fBuffer;
137            }
138
139            if (xfermode) {
140                xfermode->xfer32(dst, tmp, width, NULL);
141            } else {
142                fProc32(dst, tmp, width, fAlpha);
143            }
144
145            dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
146            src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB);
147        } while (--height != 0);
148    }
149
150private:
151    typedef Sprite_D32_XferFilter INHERITED;
152};
153
154static void fillbuffer(SkPMColor* SK_RESTRICT dst,
155                       const SkPMColor16* SK_RESTRICT src, int count) {
156    SkASSERT(count > 0);
157
158    do {
159        *dst++ = SkPixel4444ToPixel32(*src++);
160    } while (--count != 0);
161}
162
163class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter {
164public:
165    Sprite_D32_S4444_XferFilter(const SkPixmap& source, const SkPaint& paint)
166        : Sprite_D32_XferFilter(source, paint) {}
167
168    void blitRect(int x, int y, int width, int height) override {
169        SkASSERT(width > 0 && height > 0);
170        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
171        const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
172        size_t dstRB = fDevice->rowBytes();
173        size_t srcRB = fSource.rowBytes();
174        SkPMColor* SK_RESTRICT buffer = fBuffer;
175        SkColorFilter* colorFilter = fColorFilter;
176        SkXfermode* xfermode = fXfermode;
177
178        do {
179            fillbuffer(buffer, src, width);
180
181            if (colorFilter) {
182                colorFilter->filterSpan(buffer, width, buffer);
183            }
184            if (xfermode) {
185                xfermode->xfer32(dst, buffer, width, NULL);
186            } else {
187                fProc32(dst, buffer, width, fAlpha);
188            }
189
190            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
191            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
192        } while (--height != 0);
193    }
194
195private:
196    typedef Sprite_D32_XferFilter INHERITED;
197};
198
199///////////////////////////////////////////////////////////////////////////////
200
201static void src_row(SkPMColor* SK_RESTRICT dst,
202                    const SkPMColor16* SK_RESTRICT src, int count) {
203    do {
204        *dst = SkPixel4444ToPixel32(*src);
205        src += 1;
206        dst += 1;
207    } while (--count != 0);
208}
209
210class Sprite_D32_S4444_Opaque : public SkSpriteBlitter {
211public:
212    Sprite_D32_S4444_Opaque(const SkPixmap& source) : SkSpriteBlitter(source) {}
213
214    void blitRect(int x, int y, int width, int height) override {
215        SkASSERT(width > 0 && height > 0);
216        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
217        const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
218        size_t dstRB = fDevice->rowBytes();
219        size_t srcRB = fSource.rowBytes();
220
221        do {
222            src_row(dst, src, width);
223            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
224            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
225        } while (--height != 0);
226    }
227};
228
229static void srcover_row(SkPMColor* SK_RESTRICT dst,
230                        const SkPMColor16* SK_RESTRICT src, int count) {
231    do {
232        *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst);
233        src += 1;
234        dst += 1;
235    } while (--count != 0);
236}
237
238class Sprite_D32_S4444 : public SkSpriteBlitter {
239public:
240    Sprite_D32_S4444(const SkPixmap& source) : SkSpriteBlitter(source) {}
241
242    void blitRect(int x, int y, int width, int height) override {
243        SkASSERT(width > 0 && height > 0);
244        SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y);
245        const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop);
246        size_t dstRB = fDevice->rowBytes();
247        size_t srcRB = fSource.rowBytes();
248
249        do {
250            srcover_row(dst, src, width);
251            dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB);
252            src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB);
253        } while (--height != 0);
254    }
255};
256
257///////////////////////////////////////////////////////////////////////////////
258
259SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkPixmap& source, const SkPaint& paint,
260        SkTBlitterAllocator* allocator) {
261    SkASSERT(allocator != NULL);
262
263    if (paint.getMaskFilter() != NULL) {
264        return NULL;
265    }
266
267    U8CPU       alpha = paint.getAlpha();
268    SkXfermode* xfermode = paint.getXfermode();
269    SkColorFilter* filter = paint.getColorFilter();
270    SkSpriteBlitter* blitter = NULL;
271
272    switch (source.colorType()) {
273        case kARGB_4444_SkColorType:
274            if (alpha != 0xFF) {
275                return NULL;    // we only have opaque sprites
276            }
277            if (xfermode || filter) {
278                blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint);
279            } else if (source.isOpaque()) {
280                blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source);
281            } else {
282                blitter = allocator->createT<Sprite_D32_S4444>(source);
283            }
284            break;
285        case kN32_SkColorType:
286            if (xfermode || filter) {
287                if (255 == alpha) {
288                    // this can handle xfermode or filter, but not alpha
289                    blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint);
290                }
291            } else {
292                // this can handle alpha, but not xfermode or filter
293                blitter = allocator->createT<Sprite_D32_S32>(source, alpha);
294            }
295            break;
296        default:
297            break;
298    }
299    return blitter;
300}
301