1 : #include "SkBlitMask.h"
2 : #include "SkColor.h"
3 : #include "SkColorPriv.h"
4 :
5 0 : static void D32_A8_Color(void* SK_RESTRICT dst, size_t dstRB,
6 : const void* SK_RESTRICT maskPtr, size_t maskRB,
7 : SkColor color, int width, int height) {
8 0 : SkPMColor pmc = SkPreMultiplyColor(color);
9 0 : size_t dstOffset = dstRB - (width << 2);
10 0 : size_t maskOffset = maskRB - width;
11 0 : SkPMColor* SK_RESTRICT device = (SkPMColor *)dst;
12 0 : const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
13 :
14 0 : do {
15 0 : int w = width;
16 0 : do {
17 0 : unsigned aa = *mask++;
18 0 : *device = SkBlendARGB32(pmc, *device, aa);
19 0 : device += 1;
20 : } while (--w != 0);
21 0 : device = (uint32_t*)((char*)device + dstOffset);
22 0 : mask += maskOffset;
23 : } while (--height != 0);
24 0 : }
25 :
26 0 : static void D32_A8_Opaque(void* SK_RESTRICT dst, size_t dstRB,
27 : const void* SK_RESTRICT maskPtr, size_t maskRB,
28 : SkColor color, int width, int height) {
29 0 : SkPMColor pmc = SkPreMultiplyColor(color);
30 0 : SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
31 0 : const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
32 :
33 0 : maskRB -= width;
34 0 : dstRB -= (width << 2);
35 0 : do {
36 0 : int w = width;
37 0 : do {
38 0 : unsigned aa = *mask++;
39 0 : *device = SkAlphaMulQ(pmc, SkAlpha255To256(aa)) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
40 0 : device += 1;
41 : } while (--w != 0);
42 0 : device = (uint32_t*)((char*)device + dstRB);
43 0 : mask += maskRB;
44 : } while (--height != 0);
45 0 : }
46 :
47 0 : static void D32_A8_Black(void* SK_RESTRICT dst, size_t dstRB,
48 : const void* SK_RESTRICT maskPtr, size_t maskRB,
49 : SkColor, int width, int height) {
50 0 : SkPMColor* SK_RESTRICT device = (SkPMColor*)dst;
51 0 : const uint8_t* SK_RESTRICT mask = (const uint8_t*)maskPtr;
52 :
53 0 : maskRB -= width;
54 0 : dstRB -= (width << 2);
55 0 : do {
56 0 : int w = width;
57 0 : do {
58 0 : unsigned aa = *mask++;
59 0 : *device = (aa << SK_A32_SHIFT) + SkAlphaMulQ(*device, SkAlpha255To256(255 - aa));
60 0 : device += 1;
61 : } while (--w != 0);
62 0 : device = (uint32_t*)((char*)device + dstRB);
63 0 : mask += maskRB;
64 : } while (--height != 0);
65 0 : }
66 :
67 : ///////////////////////////////////////////////////////////////////////////////
68 :
69 0 : static inline int upscale31To32(int value) {
70 0 : SkASSERT((unsigned)value <= 31);
71 0 : return value + (value >> 4);
72 : }
73 :
74 0 : static inline int blend32(int src, int dst, int scale) {
75 0 : SkASSERT((unsigned)src <= 0xFF);
76 0 : SkASSERT((unsigned)dst <= 0xFF);
77 0 : SkASSERT((unsigned)scale <= 32);
78 0 : return dst + ((src - dst) * scale >> 5);
79 : }
80 :
81 0 : static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
82 : SkColor color, int width, SkPMColor) {
83 0 : int srcA = SkColorGetA(color);
84 0 : int srcR = SkColorGetR(color);
85 0 : int srcG = SkColorGetG(color);
86 0 : int srcB = SkColorGetB(color);
87 :
88 0 : srcA = SkAlpha255To256(srcA);
89 :
90 0 : for (int i = 0; i < width; i++) {
91 0 : uint16_t mask = src[i];
92 0 : if (0 == mask) {
93 0 : continue;
94 : }
95 :
96 0 : SkPMColor d = dst[i];
97 :
98 : /* We want all of these in 5bits, hence the shifts in case one of them
99 : * (green) is 6bits.
100 : */
101 0 : int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
102 0 : int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
103 0 : int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
104 :
105 : // Now upscale them to 0..32, so we can use blend32
106 0 : maskR = upscale31To32(maskR);
107 0 : maskG = upscale31To32(maskG);
108 0 : maskB = upscale31To32(maskB);
109 :
110 0 : maskR = maskR * srcA >> 8;
111 0 : maskG = maskG * srcA >> 8;
112 0 : maskB = maskB * srcA >> 8;
113 :
114 0 : int dstR = SkGetPackedR32(d);
115 0 : int dstG = SkGetPackedG32(d);
116 0 : int dstB = SkGetPackedB32(d);
117 :
118 : // LCD blitting is only supported if the dst is known/required
119 : // to be opaque
120 0 : dst[i] = SkPackARGB32(0xFF,
121 0 : blend32(srcR, dstR, maskR),
122 0 : blend32(srcG, dstG, maskG),
123 0 : blend32(srcB, dstB, maskB));
124 : }
125 0 : }
126 :
127 0 : static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
128 : SkColor color, int width, SkPMColor opaqueDst) {
129 0 : int srcR = SkColorGetR(color);
130 0 : int srcG = SkColorGetG(color);
131 0 : int srcB = SkColorGetB(color);
132 :
133 0 : for (int i = 0; i < width; i++) {
134 0 : uint16_t mask = src[i];
135 0 : if (0 == mask) {
136 0 : continue;
137 : }
138 0 : if (0xFFFF == mask) {
139 0 : dst[i] = opaqueDst;
140 0 : continue;
141 : }
142 :
143 0 : SkPMColor d = dst[i];
144 :
145 : /* We want all of these in 5bits, hence the shifts in case one of them
146 : * (green) is 6bits.
147 : */
148 0 : int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
149 0 : int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
150 0 : int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
151 :
152 : // Now upscale them to 0..32, so we can use blend32
153 0 : maskR = upscale31To32(maskR);
154 0 : maskG = upscale31To32(maskG);
155 0 : maskB = upscale31To32(maskB);
156 :
157 0 : int dstR = SkGetPackedR32(d);
158 0 : int dstG = SkGetPackedG32(d);
159 0 : int dstB = SkGetPackedB32(d);
160 :
161 : // LCD blitting is only supported if the dst is known/required
162 : // to be opaque
163 0 : dst[i] = SkPackARGB32(0xFF,
164 0 : blend32(srcR, dstR, maskR),
165 0 : blend32(srcG, dstG, maskG),
166 0 : blend32(srcB, dstB, maskB));
167 : }
168 0 : }
169 :
170 0 : static void D32_LCD16_Proc(void* SK_RESTRICT dst, size_t dstRB,
171 : const void* SK_RESTRICT mask, size_t maskRB,
172 : SkColor color, int width, int height) {
173 :
174 0 : SkPMColor* dstRow = (SkPMColor*)dst;
175 0 : const uint16_t* srcRow = (const uint16_t*)mask;
176 : SkPMColor opaqueDst;
177 :
178 : void (*proc)(SkPMColor dst[], const uint16_t src[],
179 : SkColor color, int width, SkPMColor);
180 0 : if (0xFF == SkColorGetA(color)) {
181 0 : proc = blit_lcd16_opaque_row;
182 0 : opaqueDst = SkPreMultiplyColor(color);
183 : } else {
184 0 : proc = blit_lcd16_row;
185 0 : opaqueDst = 0; // ignored
186 : }
187 :
188 0 : do {
189 0 : proc(dstRow, srcRow, color, width, opaqueDst);
190 0 : dstRow = (SkPMColor*)((char*)dstRow + dstRB);
191 0 : srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
192 : } while (--height != 0);
193 0 : }
194 :
195 : ///////////////////////////////////////////////////////////////////////////////
196 :
197 0 : static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
198 : const SkPMColor* SK_RESTRICT src,
199 : SkColor color, int width) {
200 0 : int srcR = SkColorGetR(color);
201 0 : int srcG = SkColorGetG(color);
202 0 : int srcB = SkColorGetB(color);
203 :
204 0 : for (int i = 0; i < width; i++) {
205 0 : SkPMColor mask = src[i];
206 0 : if (0 == mask) {
207 0 : continue;
208 : }
209 :
210 0 : SkPMColor d = dst[i];
211 :
212 0 : int maskR = SkGetPackedR32(mask);
213 0 : int maskG = SkGetPackedG32(mask);
214 0 : int maskB = SkGetPackedB32(mask);
215 :
216 : // Now upscale them to 0..256, so we can use SkAlphaBlend
217 0 : maskR = SkAlpha255To256(maskR);
218 0 : maskG = SkAlpha255To256(maskG);
219 0 : maskB = SkAlpha255To256(maskB);
220 :
221 0 : int dstR = SkGetPackedR32(d);
222 0 : int dstG = SkGetPackedG32(d);
223 0 : int dstB = SkGetPackedB32(d);
224 :
225 : // LCD blitting is only supported if the dst is known/required
226 : // to be opaque
227 0 : dst[i] = SkPackARGB32(0xFF,
228 0 : SkAlphaBlend(srcR, dstR, maskR),
229 0 : SkAlphaBlend(srcG, dstG, maskG),
230 0 : SkAlphaBlend(srcB, dstB, maskB));
231 : }
232 0 : }
233 :
234 0 : static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
235 : const SkPMColor* SK_RESTRICT src,
236 : SkColor color, int width) {
237 0 : int srcA = SkColorGetA(color);
238 0 : int srcR = SkColorGetR(color);
239 0 : int srcG = SkColorGetG(color);
240 0 : int srcB = SkColorGetB(color);
241 :
242 0 : srcA = SkAlpha255To256(srcA);
243 :
244 0 : for (int i = 0; i < width; i++) {
245 0 : SkPMColor mask = src[i];
246 0 : if (0 == mask) {
247 0 : continue;
248 : }
249 :
250 0 : SkPMColor d = dst[i];
251 :
252 0 : int maskR = SkGetPackedR32(mask);
253 0 : int maskG = SkGetPackedG32(mask);
254 0 : int maskB = SkGetPackedB32(mask);
255 :
256 : // Now upscale them to 0..256, so we can use SkAlphaBlend
257 0 : maskR = SkAlpha255To256(maskR);
258 0 : maskG = SkAlpha255To256(maskG);
259 0 : maskB = SkAlpha255To256(maskB);
260 :
261 0 : maskR = maskR * srcA >> 8;
262 0 : maskG = maskG * srcA >> 8;
263 0 : maskB = maskB * srcA >> 8;
264 :
265 0 : int dstR = SkGetPackedR32(d);
266 0 : int dstG = SkGetPackedG32(d);
267 0 : int dstB = SkGetPackedB32(d);
268 :
269 : // LCD blitting is only supported if the dst is known/required
270 : // to be opaque
271 0 : dst[i] = SkPackARGB32(0xFF,
272 0 : SkAlphaBlend(srcR, dstR, maskR),
273 0 : SkAlphaBlend(srcG, dstG, maskG),
274 0 : SkAlphaBlend(srcB, dstB, maskB));
275 : }
276 0 : }
277 :
278 0 : static void D32_LCD32_Blend(void* SK_RESTRICT dst, size_t dstRB,
279 : const void* SK_RESTRICT mask, size_t maskRB,
280 : SkColor color, int width, int height) {
281 0 : SkASSERT(height > 0);
282 0 : SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
283 0 : const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
284 :
285 0 : do {
286 0 : blit_lcd32_row(dstRow, srcRow, color, width);
287 0 : dstRow = (SkPMColor*)((char*)dstRow + dstRB);
288 0 : srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
289 : } while (--height != 0);
290 0 : }
291 :
292 0 : static void D32_LCD32_Opaque(void* SK_RESTRICT dst, size_t dstRB,
293 : const void* SK_RESTRICT mask, size_t maskRB,
294 : SkColor color, int width, int height) {
295 0 : SkASSERT(height > 0);
296 0 : SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
297 0 : const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
298 :
299 0 : do {
300 0 : blit_lcd32_opaque_row(dstRow, srcRow, color, width);
301 0 : dstRow = (SkPMColor*)((char*)dstRow + dstRB);
302 0 : srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
303 : } while (--height != 0);
304 0 : }
305 :
306 : ///////////////////////////////////////////////////////////////////////////////
307 :
308 0 : static SkBlitMask::ColorProc D32_A8_Factory(SkColor color) {
309 0 : if (SK_ColorBLACK == color) {
310 0 : return D32_A8_Black;
311 0 : } else if (0xFF == SkColorGetA(color)) {
312 0 : return D32_A8_Opaque;
313 : } else {
314 0 : return D32_A8_Color;
315 : }
316 : }
317 :
318 0 : static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
319 0 : return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
320 : }
321 :
322 0 : SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
323 : SkMask::Format format,
324 : SkColor color) {
325 0 : ColorProc proc = PlatformColorProcs(config, format, color);
326 0 : if (proc) {
327 0 : return proc;
328 : }
329 :
330 0 : switch (config) {
331 : case SkBitmap::kARGB_8888_Config:
332 0 : switch (format) {
333 : case SkMask::kA8_Format:
334 0 : return D32_A8_Factory(color);
335 : case SkMask::kLCD16_Format:
336 0 : return D32_LCD16_Proc;
337 : case SkMask::kLCD32_Format:
338 0 : return D32_LCD32_Factory(color);
339 : default:
340 : break;
341 : }
342 0 : break;
343 : default:
344 0 : break;
345 : }
346 0 : return NULL;
347 : }
348 :
349 0 : bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
350 : const SkIRect& clip, SkColor color) {
351 0 : ColorProc proc = ColorFactory(device.config(), mask.fFormat, color);
352 0 : if (proc) {
353 0 : int x = clip.fLeft;
354 0 : int y = clip.fTop;
355 0 : proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y),
356 0 : mask.fRowBytes, color, clip.width(), clip.height());
357 0 : return true;
358 : }
359 0 : return false;
360 : }
361 :
362 : ///////////////////////////////////////////////////////////////////////////////
363 : ///////////////////////////////////////////////////////////////////////////////
364 :
365 0 : static void BW_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
366 : const uint8_t* SK_RESTRICT mask,
367 : const SkPMColor* SK_RESTRICT src, int count) {
368 0 : int i, octuple = (count + 7) >> 3;
369 0 : for (i = 0; i < octuple; ++i) {
370 0 : int m = *mask++;
371 0 : if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
372 0 : if (m & 0x40) { dst[1] = SkPMSrcOver(src[1], dst[1]); }
373 0 : if (m & 0x20) { dst[2] = SkPMSrcOver(src[2], dst[2]); }
374 0 : if (m & 0x10) { dst[3] = SkPMSrcOver(src[3], dst[3]); }
375 0 : if (m & 0x08) { dst[4] = SkPMSrcOver(src[4], dst[4]); }
376 0 : if (m & 0x04) { dst[5] = SkPMSrcOver(src[5], dst[5]); }
377 0 : if (m & 0x02) { dst[6] = SkPMSrcOver(src[6], dst[6]); }
378 0 : if (m & 0x01) { dst[7] = SkPMSrcOver(src[7], dst[7]); }
379 0 : src += 8;
380 0 : dst += 8;
381 : }
382 0 : count &= 7;
383 0 : if (count > 0) {
384 0 : int m = *mask;
385 0 : do {
386 0 : if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
387 0 : m <<= 1;
388 0 : src += 1;
389 0 : dst += 1;
390 : } while (--count > 0);
391 : }
392 0 : }
393 :
394 0 : static void BW_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
395 : const uint8_t* SK_RESTRICT mask,
396 : const SkPMColor* SK_RESTRICT src, int count) {
397 0 : int i, octuple = (count + 7) >> 3;
398 0 : for (i = 0; i < octuple; ++i) {
399 0 : int m = *mask++;
400 0 : if (m & 0x80) { dst[0] = src[0]; }
401 0 : if (m & 0x40) { dst[1] = src[1]; }
402 0 : if (m & 0x20) { dst[2] = src[2]; }
403 0 : if (m & 0x10) { dst[3] = src[3]; }
404 0 : if (m & 0x08) { dst[4] = src[4]; }
405 0 : if (m & 0x04) { dst[5] = src[5]; }
406 0 : if (m & 0x02) { dst[6] = src[6]; }
407 0 : if (m & 0x01) { dst[7] = src[7]; }
408 0 : src += 8;
409 0 : dst += 8;
410 : }
411 0 : count &= 7;
412 0 : if (count > 0) {
413 0 : int m = *mask;
414 0 : do {
415 0 : if (m & 0x80) { dst[0] = SkPMSrcOver(src[0], dst[0]); }
416 0 : m <<= 1;
417 0 : src += 1;
418 0 : dst += 1;
419 : } while (--count > 0);
420 : }
421 0 : }
422 :
423 0 : static void A8_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
424 : const uint8_t* SK_RESTRICT mask,
425 : const SkPMColor* SK_RESTRICT src, int count) {
426 0 : for (int i = 0; i < count; ++i) {
427 0 : if (mask[i]) {
428 0 : dst[i] = SkBlendARGB32(src[i], dst[i], mask[i]);
429 : }
430 : }
431 0 : }
432 :
433 : // expand the steps that SkAlphaMulQ performs, but this way we can
434 : // exand.. add.. combine
435 : // instead of
436 : // expand..combine add expand..combine
437 : //
438 : #define EXPAND0(v, m, s) ((v) & (m)) * (s)
439 : #define EXPAND1(v, m, s) (((v) >> 8) & (m)) * (s)
440 : #define COMBINE(e0, e1, m) ((((e0) >> 8) & (m)) | ((e1) & ~(m)))
441 :
442 0 : static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
443 : const uint8_t* SK_RESTRICT mask,
444 : const SkPMColor* SK_RESTRICT src, int count) {
445 0 : const uint32_t rbmask = gMask_00FF00FF;
446 0 : for (int i = 0; i < count; ++i) {
447 0 : int m = mask[i];
448 0 : if (m) {
449 0 : m += (m >> 7);
450 : #if 1
451 : // this is slightly slower than the expand/combine version, but it
452 : // is much closer to the old results, so we use it for now to reduce
453 : // rebaselining.
454 0 : dst[i] = SkAlphaMulQ(src[i], m) + SkAlphaMulQ(dst[i], 256 - m);
455 : #else
456 : uint32_t v = src[i];
457 : uint32_t s0 = EXPAND0(v, rbmask, m);
458 : uint32_t s1 = EXPAND1(v, rbmask, m);
459 : v = dst[i];
460 : uint32_t d0 = EXPAND0(v, rbmask, m);
461 : uint32_t d1 = EXPAND1(v, rbmask, m);
462 : dst[i] = COMBINE(s0 + d0, s1 + d1, rbmask);
463 : #endif
464 : }
465 : }
466 0 : }
467 :
468 0 : static int upscale31To255(int value) {
469 0 : value = (value << 3) | (value >> 2);
470 0 : return value;
471 : }
472 :
473 0 : static int mul(int a, int b) {
474 0 : return a * b >> 8;
475 : }
476 :
477 0 : static int src_alpha_blend(int src, int dst, int srcA, int mask) {
478 :
479 0 : return dst + mul(src - mul(srcA, dst), mask);
480 : }
481 :
482 0 : static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
483 : const uint16_t* SK_RESTRICT mask,
484 : const SkPMColor* SK_RESTRICT src, int count) {
485 0 : for (int i = 0; i < count; ++i) {
486 0 : uint16_t m = mask[i];
487 0 : if (0 == m) {
488 0 : continue;
489 : }
490 :
491 0 : SkPMColor s = src[i];
492 0 : SkPMColor d = dst[i];
493 :
494 0 : int srcA = SkGetPackedA32(s);
495 0 : int srcR = SkGetPackedR32(s);
496 0 : int srcG = SkGetPackedG32(s);
497 0 : int srcB = SkGetPackedB32(s);
498 :
499 0 : srcA += srcA >> 7;
500 :
501 : /* We want all of these in 5bits, hence the shifts in case one of them
502 : * (green) is 6bits.
503 : */
504 0 : int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
505 0 : int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
506 0 : int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
507 :
508 0 : maskR = upscale31To255(maskR);
509 0 : maskG = upscale31To255(maskG);
510 0 : maskB = upscale31To255(maskB);
511 :
512 0 : int dstR = SkGetPackedR32(d);
513 0 : int dstG = SkGetPackedG32(d);
514 0 : int dstB = SkGetPackedB32(d);
515 :
516 : // LCD blitting is only supported if the dst is known/required
517 : // to be opaque
518 0 : dst[i] = SkPackARGB32(0xFF,
519 0 : src_alpha_blend(srcR, dstR, srcA, maskR),
520 0 : src_alpha_blend(srcG, dstG, srcA, maskG),
521 0 : src_alpha_blend(srcB, dstB, srcA, maskB));
522 : }
523 0 : }
524 :
525 0 : static void LCD16_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
526 : const uint16_t* SK_RESTRICT mask,
527 : const SkPMColor* SK_RESTRICT src, int count) {
528 0 : for (int i = 0; i < count; ++i) {
529 0 : uint16_t m = mask[i];
530 0 : if (0 == m) {
531 0 : continue;
532 : }
533 :
534 0 : SkPMColor s = src[i];
535 0 : SkPMColor d = dst[i];
536 :
537 0 : int srcR = SkGetPackedR32(s);
538 0 : int srcG = SkGetPackedG32(s);
539 0 : int srcB = SkGetPackedB32(s);
540 :
541 : /* We want all of these in 5bits, hence the shifts in case one of them
542 : * (green) is 6bits.
543 : */
544 0 : int maskR = SkGetPackedR16(m) >> (SK_R16_BITS - 5);
545 0 : int maskG = SkGetPackedG16(m) >> (SK_G16_BITS - 5);
546 0 : int maskB = SkGetPackedB16(m) >> (SK_B16_BITS - 5);
547 :
548 : // Now upscale them to 0..32, so we can use blend32
549 0 : maskR = upscale31To32(maskR);
550 0 : maskG = upscale31To32(maskG);
551 0 : maskB = upscale31To32(maskB);
552 :
553 0 : int dstR = SkGetPackedR32(d);
554 0 : int dstG = SkGetPackedG32(d);
555 0 : int dstB = SkGetPackedB32(d);
556 :
557 : // LCD blitting is only supported if the dst is known/required
558 : // to be opaque
559 0 : dst[i] = SkPackARGB32(0xFF,
560 0 : blend32(srcR, dstR, maskR),
561 0 : blend32(srcG, dstG, maskG),
562 0 : blend32(srcB, dstB, maskB));
563 : }
564 0 : }
565 :
566 0 : static void LCD32_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
567 : const SkPMColor* SK_RESTRICT mask,
568 : const SkPMColor* SK_RESTRICT src, int count) {
569 0 : for (int i = 0; i < count; ++i) {
570 0 : SkPMColor m = mask[i];
571 0 : if (0 == m) {
572 0 : continue;
573 : }
574 :
575 0 : SkPMColor s = src[i];
576 0 : int srcA = SkGetPackedA32(s);
577 0 : int srcR = SkGetPackedR32(s);
578 0 : int srcG = SkGetPackedG32(s);
579 0 : int srcB = SkGetPackedB32(s);
580 :
581 0 : srcA = SkAlpha255To256(srcA);
582 :
583 0 : SkPMColor d = dst[i];
584 :
585 0 : int maskR = SkGetPackedR32(m);
586 0 : int maskG = SkGetPackedG32(m);
587 0 : int maskB = SkGetPackedB32(m);
588 :
589 : // Now upscale them to 0..256
590 0 : maskR = SkAlpha255To256(maskR);
591 0 : maskG = SkAlpha255To256(maskG);
592 0 : maskB = SkAlpha255To256(maskB);
593 :
594 0 : int dstR = SkGetPackedR32(d);
595 0 : int dstG = SkGetPackedG32(d);
596 0 : int dstB = SkGetPackedB32(d);
597 :
598 : // LCD blitting is only supported if the dst is known/required
599 : // to be opaque
600 0 : dst[i] = SkPackARGB32(0xFF,
601 0 : src_alpha_blend(srcR, dstR, srcA, maskR),
602 0 : src_alpha_blend(srcG, dstG, srcA, maskG),
603 0 : src_alpha_blend(srcB, dstB, srcA, maskB));
604 : }
605 0 : }
606 :
607 0 : static void LCD32_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
608 : const SkPMColor* SK_RESTRICT mask,
609 : const SkPMColor* SK_RESTRICT src, int count) {
610 0 : for (int i = 0; i < count; ++i) {
611 0 : SkPMColor m = mask[i];
612 0 : if (0 == m) {
613 0 : continue;
614 : }
615 :
616 0 : SkPMColor s = src[i];
617 0 : SkPMColor d = dst[i];
618 :
619 0 : int maskR = SkGetPackedR32(m);
620 0 : int maskG = SkGetPackedG32(m);
621 0 : int maskB = SkGetPackedB32(m);
622 :
623 0 : int srcR = SkGetPackedR32(s);
624 0 : int srcG = SkGetPackedG32(s);
625 0 : int srcB = SkGetPackedB32(s);
626 :
627 0 : int dstR = SkGetPackedR32(d);
628 0 : int dstG = SkGetPackedG32(d);
629 0 : int dstB = SkGetPackedB32(d);
630 :
631 : // Now upscale them to 0..256, so we can use SkAlphaBlend
632 0 : maskR = SkAlpha255To256(maskR);
633 0 : maskG = SkAlpha255To256(maskG);
634 0 : maskB = SkAlpha255To256(maskB);
635 :
636 : // LCD blitting is only supported if the dst is known/required
637 : // to be opaque
638 0 : dst[i] = SkPackARGB32(0xFF,
639 0 : SkAlphaBlend(srcR, dstR, maskR),
640 0 : SkAlphaBlend(srcG, dstG, maskG),
641 0 : SkAlphaBlend(srcB, dstB, maskB));
642 : }
643 0 : }
644 :
645 0 : SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
646 : SkMask::Format format,
647 : RowFlags flags) {
648 : // make this opt-in until chrome can rebaseline
649 0 : RowProc proc = PlatformRowProcs(config, format, flags);
650 0 : if (proc) {
651 0 : return proc;
652 : }
653 :
654 : static const RowProc gProcs[] = {
655 : // need X coordinate to handle BW
656 : NULL, NULL, //(RowProc)BW_RowProc_Blend, (RowProc)BW_RowProc_Opaque,
657 : (RowProc)A8_RowProc_Blend, (RowProc)A8_RowProc_Opaque,
658 : (RowProc)LCD16_RowProc_Blend, (RowProc)LCD16_RowProc_Opaque,
659 : (RowProc)LCD32_RowProc_Blend, (RowProc)LCD32_RowProc_Opaque,
660 : };
661 :
662 : int index;
663 0 : switch (config) {
664 : case SkBitmap::kARGB_8888_Config:
665 0 : switch (format) {
666 0 : case SkMask::kBW_Format: index = 0; break;
667 0 : case SkMask::kA8_Format: index = 2; break;
668 0 : case SkMask::kLCD16_Format: index = 4; break;
669 0 : case SkMask::kLCD32_Format: index = 6; break;
670 : default:
671 0 : return NULL;
672 : }
673 0 : if (flags & kSrcIsOpaque_RowFlag) {
674 0 : index |= 1;
675 : }
676 0 : SkASSERT((size_t)index < SK_ARRAY_COUNT(gProcs));
677 0 : return gProcs[index];
678 : default:
679 : break;
680 : }
681 0 : return NULL;
682 : }
683 :
|