|
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: |
|
22 Sprite_D32_S32(const SkBitmap& src, U8CPU alpha) : INHERITED(src) { |
|
23 SkASSERT(src.colorType() == kPMColor_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 virtual void blitRect(int x, int y, int width, int height) { |
|
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: |
|
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 |
|
88 virtual ~Sprite_D32_XferFilter() { |
|
89 delete[] fBuffer; |
|
90 SkSafeUnref(fXfermode); |
|
91 SkSafeUnref(fColorFilter); |
|
92 } |
|
93 |
|
94 virtual void setup(const SkBitmap& device, int left, int top, |
|
95 const SkPaint& paint) { |
|
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: |
|
122 Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint) |
|
123 : Sprite_D32_XferFilter(source, paint) {} |
|
124 |
|
125 virtual void blitRect(int x, int y, int width, int height) { |
|
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 (NULL != colorFilter) { |
|
139 colorFilter->filterSpan(src, width, fBuffer); |
|
140 tmp = fBuffer; |
|
141 } |
|
142 |
|
143 if (NULL != 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 |
|
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: |
|
169 Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint) |
|
170 : Sprite_D32_XferFilter(source, paint) {} |
|
171 |
|
172 virtual void blitRect(int x, int y, int width, int height) { |
|
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 (NULL != colorFilter) { |
|
187 colorFilter->filterSpan(buffer, width, buffer); |
|
188 } |
|
189 if (NULL != 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 |
|
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: |
|
217 Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} |
|
218 |
|
219 virtual void blitRect(int x, int y, int width, int height) { |
|
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 |
|
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: |
|
246 Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {} |
|
247 |
|
248 virtual void blitRect(int x, int y, int width, int height) { |
|
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 |
|
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 kPMColor_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 } |