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