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