blob: ed2fc0ec9a817762df3650c034b377a9f96e7509 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
24SkARGB32_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
37const 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
50void 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
78void 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_scale)
150#define SK_BLITBWMASK_GETADDR getAddr32
151#define SK_BLITBWMASK_DEVTYPE uint32_t
152#include "SkBlitBWMaskTemplate.h"
153
154void 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 - fSrcA));
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
190void 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
224void 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
252void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
253 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.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
293void 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, SkAlpha255To256(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
326void 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
359SkARGB32_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
367SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() {
368 fXfermode->safeUnref();
369 sk_free(fBuffer);
370}
371
372void 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
401void 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 device
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