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