OLD | NEW |
| (Empty) |
1 /* libs/graphics/sgl/SkBlitter_ARGB32.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkCoreBlitters.h" | |
19 #include "SkColorPriv.h" | |
20 #include "SkShader.h" | |
21 #include "SkUtils.h" | |
22 #include "SkXfermode.h" | |
23 | |
24 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint) | |
25 : INHERITED(device) { | |
26 uint32_t color = paint.getColor(); | |
27 | |
28 fSrcA = SkColorGetA(color); | |
29 unsigned scale = SkAlpha255To256(fSrcA); | |
30 fSrcR = SkAlphaMul(SkColorGetR(color), scale); | |
31 fSrcG = SkAlphaMul(SkColorGetG(color), scale); | |
32 fSrcB = SkAlphaMul(SkColorGetB(color), scale); | |
33 | |
34 fPMColor = SkPackARGB32(fSrcA, fSrcR, fSrcG, fSrcB); | |
35 } | |
36 | |
37 const SkBitmap* SkARGB32_Blitter::justAnOpaqueColor(uint32_t* value) { | |
38 if (255 == fSrcA) { | |
39 *value = fPMColor; | |
40 return &fDevice; | |
41 } | |
42 return NULL; | |
43 } | |
44 | |
45 #if defined _WIN32 && _MSC_VER >= 1300 // disable warning : local variable used
without having been initialized | |
46 #pragma warning ( push ) | |
47 #pragma warning ( disable : 4701 ) | |
48 #endif | |
49 | |
50 void SkARGB32_Blitter::blitH(int x, int y, int width) { | |
51 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
52 | |
53 if (fSrcA == 0) { | |
54 return; | |
55 } | |
56 | |
57 uint32_t* device = fDevice.getAddr32(x, y); | |
58 | |
59 if (fSrcA == 255) { | |
60 sk_memset32(device, fPMColor, width); | |
61 } else { | |
62 uint32_t color = fPMColor; | |
63 unsigned dst_scale = SkAlpha255To256(255 - fSrcA); | |
64 uint32_t prevDst = ~device[0]; // so we always fail the test the first
time | |
65 uint32_t result SK_INIT_TO_AVOID_WARNING; | |
66 | |
67 for (int i = 0; i < width; i++) { | |
68 uint32_t currDst = device[i]; | |
69 if (currDst != prevDst) { | |
70 result = color + SkAlphaMulQ(currDst, dst_scale); | |
71 prevDst = currDst; | |
72 } | |
73 device[i] = result; | |
74 } | |
75 } | |
76 } | |
77 | |
78 void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], | |
79 const int16_t runs[]) { | |
80 if (fSrcA == 0) { | |
81 return; | |
82 } | |
83 | |
84 uint32_t color = fPMColor; | |
85 uint32_t* device = fDevice.getAddr32(x, y); | |
86 unsigned opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the
fast opaque case | |
87 | |
88 for (;;) { | |
89 int count = runs[0]; | |
90 SkASSERT(count >= 0); | |
91 if (count <= 0) { | |
92 return; | |
93 } | |
94 unsigned aa = antialias[0]; | |
95 if (aa) { | |
96 if ((opaqueMask & aa) == 255) { | |
97 sk_memset32(device, color, count); | |
98 } else { | |
99 uint32_t sc = SkAlphaMulQ(color, aa); | |
100 unsigned dst_scale = 255 - SkGetPackedA32(sc); | |
101 int n = count; | |
102 do { | |
103 --n; | |
104 device[n] = sc + SkAlphaMulQ(device[n], dst_scale); | |
105 } while (n > 0); | |
106 } | |
107 } | |
108 runs += count; | |
109 antialias += count; | |
110 device += count; | |
111 } | |
112 } | |
113 | |
114 ////////////////////////////////////////////////////////////////////////////////
////// | |
115 | |
116 #define solid_8_pixels(mask, dst, color) \ | |
117 do { \ | |
118 if (mask & 0x80) dst[0] = color; \ | |
119 if (mask & 0x40) dst[1] = color; \ | |
120 if (mask & 0x20) dst[2] = color; \ | |
121 if (mask & 0x10) dst[3] = color; \ | |
122 if (mask & 0x08) dst[4] = color; \ | |
123 if (mask & 0x04) dst[5] = color; \ | |
124 if (mask & 0x02) dst[6] = color; \ | |
125 if (mask & 0x01) dst[7] = color; \ | |
126 } while (0) | |
127 | |
128 #define SK_BLITBWMASK_NAME SkARGB32_BlitBW | |
129 #define SK_BLITBWMASK_ARGS , SkPMColor color | |
130 #define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) | |
131 #define SK_BLITBWMASK_GETADDR getAddr32 | |
132 #define SK_BLITBWMASK_DEVTYPE uint32_t | |
133 #include "SkBlitBWMaskTemplate.h" | |
134 | |
135 #define blend_8_pixels(mask, dst, sc, dst_scale) \ | |
136 do { \ | |
137 if (mask & 0x80) { dst[0] = sc + SkAlphaMulQ(dst[0], dst_scale); } \ | |
138 if (mask & 0x40) { dst[1] = sc + SkAlphaMulQ(dst[1], dst_scale); } \ | |
139 if (mask & 0x20) { dst[2] = sc + SkAlphaMulQ(dst[2], dst_scale); } \ | |
140 if (mask & 0x10) { dst[3] = sc + SkAlphaMulQ(dst[3], dst_scale); } \ | |
141 if (mask & 0x08) { dst[4] = sc + SkAlphaMulQ(dst[4], dst_scale); } \ | |
142 if (mask & 0x04) { dst[5] = sc + SkAlphaMulQ(dst[5], dst_scale); } \ | |
143 if (mask & 0x02) { dst[6] = sc + SkAlphaMulQ(dst[6], dst_scale); } \ | |
144 if (mask & 0x01) { dst[7] = sc + SkAlphaMulQ(dst[7], dst_scale); } \ | |
145 } while (0) | |
146 | |
147 #define SK_BLITBWMASK_NAME SkARGB32_BlendBW | |
148 #define SK_BLITBWMASK_ARGS , uint32_t sc, unsigned dst_scale | |
149 #define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, sc, dst_sc
ale) | |
150 #define SK_BLITBWMASK_GETADDR getAddr32 | |
151 #define SK_BLITBWMASK_DEVTYPE uint32_t | |
152 #include "SkBlitBWMaskTemplate.h" | |
153 | |
154 void SkARGB32_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { | |
155 SkASSERT(mask.fBounds.contains(clip)); | |
156 SkASSERT(fSrcA != 0xFF); | |
157 | |
158 if (fSrcA == 0) { | |
159 return; | |
160 } | |
161 | |
162 if (mask.fFormat == SkMask::kBW_Format) { | |
163 SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fS
rcA)); | |
164 return; | |
165 } | |
166 | |
167 int x = clip.fLeft; | |
168 int y = clip.fTop; | |
169 int width = clip.width(); | |
170 int height = clip.height(); | |
171 | |
172 uint32_t* device = fDevice.getAddr32(x, y); | |
173 const uint8_t* alpha = mask.getAddr(x, y); | |
174 uint32_t srcColor = fPMColor; | |
175 unsigned devRB = fDevice.rowBytes() - (width << 2); | |
176 unsigned maskRB = mask.fRowBytes - width; | |
177 | |
178 do { | |
179 int w = width; | |
180 do { | |
181 unsigned aa = *alpha++; | |
182 *device = SkBlendARGB32(srcColor, *device, aa); | |
183 device += 1; | |
184 } while (--w != 0); | |
185 device = (uint32_t*)((char*)device + devRB); | |
186 alpha += maskRB; | |
187 } while (--height != 0); | |
188 } | |
189 | |
190 void SkARGB32_Opaque_Blitter::blitMask(const SkMask& mask, | |
191 const SkIRect& clip) { | |
192 SkASSERT(mask.fBounds.contains(clip)); | |
193 | |
194 if (mask.fFormat == SkMask::kBW_Format) { | |
195 SkARGB32_BlitBW(fDevice, mask, clip, fPMColor); | |
196 return; | |
197 } | |
198 | |
199 int x = clip.fLeft; | |
200 int y = clip.fTop; | |
201 int width = clip.width(); | |
202 int height = clip.height(); | |
203 | |
204 uint32_t* device = fDevice.getAddr32(x, y); | |
205 const uint8_t* alpha = mask.getAddr(x, y); | |
206 uint32_t srcColor = fPMColor; | |
207 unsigned devRB = fDevice.rowBytes() - (width << 2); | |
208 unsigned maskRB = mask.fRowBytes - width; | |
209 | |
210 do { | |
211 int w = width; | |
212 do { | |
213 unsigned aa = *alpha++; | |
214 *device = SkAlphaMulQ(srcColor, SkAlpha255To256(aa)) + SkAlphaMulQ(*
device, SkAlpha255To256(255 - aa)); | |
215 device += 1; | |
216 } while (--w != 0); | |
217 device = (uint32_t*)((char*)device + devRB); | |
218 alpha += maskRB; | |
219 } while (--height != 0); | |
220 } | |
221 | |
222 ////////////////////////////////////////////////////////////////////////////////
////// | |
223 | |
224 void SkARGB32_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { | |
225 if (alpha == 0 || fSrcA == 0) { | |
226 return; | |
227 } | |
228 | |
229 uint32_t* device = fDevice.getAddr32(x, y); | |
230 uint32_t color = fPMColor; | |
231 | |
232 if (alpha != 255) { | |
233 color = SkAlphaMulQ(color, SkAlpha255To256(alpha)); | |
234 } | |
235 | |
236 unsigned dst_scale = 255 - SkGetPackedA32(color); | |
237 uint32_t prevDst = ~device[0]; | |
238 uint32_t result SK_INIT_TO_AVOID_WARNING; | |
239 uint32_t rowBytes = fDevice.rowBytes(); | |
240 | |
241 while (--height >= 0) { | |
242 uint32_t dst = device[0]; | |
243 if (dst != prevDst) { | |
244 result = color + SkAlphaMulQ(dst, dst_scale); | |
245 prevDst = dst; | |
246 } | |
247 device[0] = result; | |
248 device = (uint32_t*)((char*)device + rowBytes); | |
249 } | |
250 } | |
251 | |
252 void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) { | |
253 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= f
Device.height()); | |
254 | |
255 if (fSrcA == 0) { | |
256 return; | |
257 } | |
258 | |
259 uint32_t* device = fDevice.getAddr32(x, y); | |
260 uint32_t color = fPMColor; | |
261 | |
262 if (fSrcA == 255) { | |
263 while (--height >= 0) { | |
264 sk_memset32(device, color, width); | |
265 device = (uint32_t*)((char*)device + fDevice.rowBytes()); | |
266 } | |
267 } else { | |
268 unsigned dst_scale = SkAlpha255To256(255 - fSrcA); | |
269 | |
270 while (--height >= 0) { | |
271 uint32_t prevDst = ~device[0]; | |
272 uint32_t result SK_INIT_TO_AVOID_WARNING; | |
273 | |
274 for (int i = 0; i < width; i++) { | |
275 uint32_t dst = device[i]; | |
276 if (dst != prevDst) { | |
277 result = color + SkAlphaMulQ(dst, dst_scale); | |
278 prevDst = dst; | |
279 } | |
280 device[i] = result; | |
281 } | |
282 device = (uint32_t*)((char*)device + fDevice.rowBytes()); | |
283 } | |
284 } | |
285 } | |
286 | |
287 #if defined _WIN32 && _MSC_VER >= 1300 | |
288 #pragma warning ( pop ) | |
289 #endif | |
290 | |
291 /////////////////////////////////////////////////////////////////////// | |
292 | |
293 void SkARGB32_Black_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { | |
294 SkASSERT(mask.fBounds.contains(clip)); | |
295 | |
296 if (mask.fFormat == SkMask::kBW_Format) { | |
297 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); | |
298 | |
299 SkARGB32_BlitBW(fDevice, mask, clip, black); | |
300 } else { | |
301 uint32_t* device = fDevice.getAddr32(clip.fLeft, clip.fTop); | |
302 const uint8_t* alpha = mask.getAddr(clip.fLeft, clip.fTop); | |
303 unsigned width = clip.width(); | |
304 unsigned height = clip.height(); | |
305 unsigned deviceRB = fDevice.rowBytes() - (width << 2); | |
306 unsigned maskRB = mask.fRowBytes - width; | |
307 | |
308 SkASSERT((int)height > 0); | |
309 SkASSERT((int)width > 0); | |
310 SkASSERT((int)deviceRB >= 0); | |
311 SkASSERT((int)maskRB >= 0); | |
312 | |
313 do { | |
314 unsigned w = width; | |
315 do { | |
316 unsigned aa = *alpha++; | |
317 *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255
To256(255 - aa)); | |
318 device += 1; | |
319 } while (--w != 0); | |
320 device = (uint32_t*)((char*)device + deviceRB); | |
321 alpha += maskRB; | |
322 } while (--height != 0); | |
323 } | |
324 } | |
325 | |
326 void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], | |
327 const int16_t runs[]) { | |
328 uint32_t* device = fDevice.getAddr32(x, y); | |
329 SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT); | |
330 | |
331 for (;;) { | |
332 int count = runs[0]; | |
333 SkASSERT(count >= 0); | |
334 if (count <= 0) { | |
335 return; | |
336 } | |
337 unsigned aa = antialias[0]; | |
338 if (aa) { | |
339 if (aa == 255) { | |
340 sk_memset32(device, black, count); | |
341 } else { | |
342 SkPMColor src = aa << SK_A32_SHIFT; | |
343 unsigned dst_scale = 256 - aa; | |
344 int n = count; | |
345 do { | |
346 --n; | |
347 device[n] = src + SkAlphaMulQ(device[n], dst_scale); | |
348 } while (n > 0); | |
349 } | |
350 } | |
351 runs += count; | |
352 antialias += count; | |
353 device += count; | |
354 } | |
355 } | |
356 | |
357 ////////////////////////////////////////////////////////////////////////////////
////////// | |
358 | |
359 SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkBitmap& device, | |
360 const SkPaint& paint) | |
361 : INHERITED(device, paint) { | |
362 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); | |
363 | |
364 (fXfermode = paint.getXfermode())->safeRef(); | |
365 } | |
366 | |
367 SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { | |
368 fXfermode->safeUnref(); | |
369 sk_free(fBuffer); | |
370 } | |
371 | |
372 void SkARGB32_Shader_Blitter::blitH(int x, int y, int width) { | |
373 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
374 | |
375 uint32_t* device = fDevice.getAddr32(x, y); | |
376 | |
377 if (fXfermode == NULL && (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag)
) { | |
378 fShader->shadeSpan(x, y, device, width); | |
379 } else { | |
380 SkPMColor* span = fBuffer; | |
381 fShader->shadeSpan(x, y, span, width); | |
382 if (fXfermode) { | |
383 fXfermode->xfer32(device, span, width, NULL); | |
384 } else { | |
385 for (int i = 0; i < width; i++) { | |
386 uint32_t src = span[i]; | |
387 if (src) { | |
388 unsigned srcA = SkGetPackedA32(src); | |
389 if (srcA != 0xFF) { | |
390 src += SkAlphaMulQ(device[i], SkAlpha255To256(255 - srcA
)); | |
391 } | |
392 device[i] = src; | |
393 } | |
394 } | |
395 } | |
396 } | |
397 } | |
398 | |
399 ////////////////////////////////////////////////////////////////////////////////
/////////////// | |
400 | |
401 void SkARGB32_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[], | |
402 const int16_t runs[]) { | |
403 SkPMColor* span = fBuffer; | |
404 uint32_t* device = fDevice.getAddr32(x, y); | |
405 SkShader* shader = fShader; | |
406 | |
407 if (fXfermode) { | |
408 for (;;) { | |
409 SkXfermode* xfer = fXfermode; | |
410 | |
411 int count = *runs; | |
412 if (count <= 0) | |
413 break; | |
414 int aa = *antialias; | |
415 if (aa) { | |
416 shader->shadeSpan(x, y, span, count); | |
417 if (aa == 255) { | |
418 xfer->xfer32(device, span, count, NULL); | |
419 } else { | |
420 // count is almost always 1 | |
421 for (int i = count - 1; i >= 0; --i) { | |
422 xfer->xfer32(&device[i], &span[i], 1, antialias); | |
423 } | |
424 } | |
425 } | |
426 device += count; | |
427 runs += count; | |
428 antialias += count; | |
429 x += count; | |
430 } | |
431 } else if (fShader->getFlags() & SkShader::kOpaqueAlpha_Flag) { | |
432 for (;;) { | |
433 int count = *runs; | |
434 if (count <= 0) { | |
435 break; | |
436 } | |
437 int aa = *antialias; | |
438 if (aa) { | |
439 if (aa == 255) { // cool, have the shader draw right into the d
evice | |
440 shader->shadeSpan(x, y, device, count); | |
441 } else { | |
442 shader->shadeSpan(x, y, span, count); | |
443 for (int i = count - 1; i >= 0; --i) { | |
444 if (span[i]) { | |
445 device[i] = SkBlendARGB32(span[i], device[i], aa); | |
446 } | |
447 } | |
448 } | |
449 } | |
450 device += count; | |
451 runs += count; | |
452 antialias += count; | |
453 x += count; | |
454 } | |
455 } else { // no xfermode but we are not opaque | |
456 for (;;) { | |
457 int count = *runs; | |
458 if (count <= 0) { | |
459 break; | |
460 } | |
461 int aa = *antialias; | |
462 if (aa) { | |
463 fShader->shadeSpan(x, y, span, count); | |
464 if (aa == 255) { | |
465 for (int i = count - 1; i >= 0; --i) { | |
466 if (span[i]) { | |
467 device[i] = SkPMSrcOver(span[i], device[i]); | |
468 } | |
469 } | |
470 } else { | |
471 for (int i = count - 1; i >= 0; --i) { | |
472 if (span[i]) { | |
473 device[i] = SkBlendARGB32(span[i], device[i], aa); | |
474 } | |
475 } | |
476 } | |
477 } | |
478 device += count; | |
479 runs += count; | |
480 antialias += count; | |
481 x += count; | |
482 } | |
483 } | |
484 } | |
485 | |
OLD | NEW |