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