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