blob: 1f16d775b51e2845a6ac5b08b272bd19c761bfeb [file] [log] [blame]
reed@google.comedb606c2011-10-18 13:56:50 +00001#include "SkBlitMask.h"
2#include "SkColor.h"
3#include "SkColorPriv.h"
4
5static 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
26static 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
47static 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
tomhudson@google.comd6770e62012-02-14 16:01:15 +000067SkBlitMask::BlitLCD16RowProc SkBlitMask::BlitLCD16RowFactory(bool isOpaque) {
68 BlitLCD16RowProc proc = PlatformBlitRowProcs16(isOpaque);
69 if (proc) {
70 return proc;
reed@google.comedb606c2011-10-18 13:56:50 +000071 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000072
tomhudson@google.comd6770e62012-02-14 16:01:15 +000073 if (isOpaque) {
74 return SkBlitLCD16OpaqueRow;
75 } else {
76 return SkBlitLCD16Row;
reed@google.comedb606c2011-10-18 13:56:50 +000077 }
78}
79
80static 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) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +000083
84 SkPMColor* dstRow = (SkPMColor*)dst;
reed@google.comedb606c2011-10-18 13:56:50 +000085 const uint16_t* srcRow = (const uint16_t*)mask;
86 SkPMColor opaqueDst;
rmistry@google.comfbfcd562012-08-23 18:09:54 +000087
tomhudson@google.comd6770e62012-02-14 16:01:15 +000088 SkBlitMask::BlitLCD16RowProc proc = NULL;
89 bool isOpaque = (0xFF == SkColorGetA(color));
90 proc = SkBlitMask::BlitLCD16RowFactory(isOpaque);
91 SkASSERT(proc != NULL);
92
93 if (isOpaque) {
reed@google.comedb606c2011-10-18 13:56:50 +000094 opaqueDst = SkPreMultiplyColor(color);
95 } else {
reed@google.comedb606c2011-10-18 13:56:50 +000096 opaqueDst = 0; // ignored
97 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +000098
reed@google.comedb606c2011-10-18 13:56:50 +000099 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
108static 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);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000114
reed@google.comedb606c2011-10-18 13:56:50 +0000115 for (int i = 0; i < width; i++) {
116 SkPMColor mask = src[i];
117 if (0 == mask) {
118 continue;
119 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000120
reed@google.comedb606c2011-10-18 13:56:50 +0000121 SkPMColor d = dst[i];
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000122
reed@google.comedb606c2011-10-18 13:56:50 +0000123 int maskR = SkGetPackedR32(mask);
124 int maskG = SkGetPackedG32(mask);
125 int maskB = SkGetPackedB32(mask);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000126
reed@google.comedb606c2011-10-18 13:56:50 +0000127 // Now upscale them to 0..256, so we can use SkAlphaBlend
128 maskR = SkAlpha255To256(maskR);
129 maskG = SkAlpha255To256(maskG);
130 maskB = SkAlpha255To256(maskB);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000131
reed@google.comedb606c2011-10-18 13:56:50 +0000132 int dstR = SkGetPackedR32(d);
133 int dstG = SkGetPackedG32(d);
134 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000135
reed@google.comedb606c2011-10-18 13:56:50 +0000136 // 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
145static 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);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000152
reed@google.comedb606c2011-10-18 13:56:50 +0000153 srcA = SkAlpha255To256(srcA);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000154
reed@google.comedb606c2011-10-18 13:56:50 +0000155 for (int i = 0; i < width; i++) {
156 SkPMColor mask = src[i];
157 if (0 == mask) {
158 continue;
159 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000160
reed@google.comedb606c2011-10-18 13:56:50 +0000161 SkPMColor d = dst[i];
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000162
reed@google.comedb606c2011-10-18 13:56:50 +0000163 int maskR = SkGetPackedR32(mask);
164 int maskG = SkGetPackedG32(mask);
165 int maskB = SkGetPackedB32(mask);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000166
reed@google.comedb606c2011-10-18 13:56:50 +0000167 // Now upscale them to 0..256, so we can use SkAlphaBlend
168 maskR = SkAlpha255To256(maskR);
169 maskG = SkAlpha255To256(maskG);
170 maskB = SkAlpha255To256(maskB);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000171
reed@google.comedb606c2011-10-18 13:56:50 +0000172 maskR = maskR * srcA >> 8;
173 maskG = maskG * srcA >> 8;
174 maskB = maskB * srcA >> 8;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000175
reed@google.comedb606c2011-10-18 13:56:50 +0000176 int dstR = SkGetPackedR32(d);
177 int dstG = SkGetPackedG32(d);
178 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000179
reed@google.comedb606c2011-10-18 13:56:50 +0000180 // 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
189static 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;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000195
reed@google.comedb606c2011-10-18 13:56:50 +0000196 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
203static 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;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000209
reed@google.comedb606c2011-10-18 13:56:50 +0000210 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
reed@google.come901b4c2011-11-14 21:56:45 +0000219static SkBlitMask::ColorProc D32_A8_Factory(SkColor color) {
reed@google.comedb606c2011-10-18 13:56:50 +0000220 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
reed@google.come901b4c2011-11-14 21:56:45 +0000229static SkBlitMask::ColorProc D32_LCD32_Factory(SkColor color) {
reed@google.comedb606c2011-10-18 13:56:50 +0000230 return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
231}
232
reed@google.come901b4c2011-11-14 21:56:45 +0000233SkBlitMask::ColorProc SkBlitMask::ColorFactory(SkBitmap::Config config,
234 SkMask::Format format,
235 SkColor color) {
236 ColorProc proc = PlatformColorProcs(config, format, color);
reed@google.comedb606c2011-10-18 13:56:50 +0000237 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);
reed@google.com5344a1a2011-10-18 14:03:23 +0000250 default:
251 break;
reed@google.comedb606c2011-10-18 13:56:50 +0000252 }
253 break;
254 default:
255 break;
256 }
257 return NULL;
258}
259
reed@google.comedb606c2011-10-18 13:56:50 +0000260bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
261 const SkIRect& clip, SkColor color) {
reed@google.come901b4c2011-11-14 21:56:45 +0000262 ColorProc proc = ColorFactory(device.config(), mask.fFormat, color);
reed@google.comedb606c2011-10-18 13:56:50 +0000263 if (proc) {
264 int x = clip.fLeft;
265 int y = clip.fTop;
reed@google.comf52e5552011-10-18 17:29:44 +0000266 proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y),
reed@google.comedb606c2011-10-18 13:56:50 +0000267 mask.fRowBytes, color, clip.width(), clip.height());
268 return true;
269 }
270 return false;
271}
272
reed@google.com1750bf12011-11-15 19:51:02 +0000273///////////////////////////////////////////////////////////////////////////////
274///////////////////////////////////////////////////////////////////////////////
275
276static 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
305static 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
334static 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
353static void A8_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
354 const uint8_t* SK_RESTRICT mask,
355 const SkPMColor* SK_RESTRICT src, int count) {
caryclark@google.com803eceb2012-06-06 12:09:34 +0000356#if 0 // suppress warning
reed@google.com1750bf12011-11-15 19:51:02 +0000357 const uint32_t rbmask = gMask_00FF00FF;
caryclark@google.com803eceb2012-06-06 12:09:34 +0000358#endif
reed@google.com1750bf12011-11-15 19:51:02 +0000359 for (int i = 0; i < count; ++i) {
360 int m = mask[i];
361 if (m) {
362 m += (m >> 7);
reed@google.com22048622011-11-18 18:36:07 +0000363#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.
reed@google.com1750bf12011-11-15 19:51:02 +0000367 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
reed@google.com181f4b32011-11-30 14:49:24 +0000381static int upscale31To255(int value) {
382 value = (value << 3) | (value >> 2);
383 return value;
384}
385
reed@google.com181f4b32011-11-30 14:49:24 +0000386static int src_alpha_blend(int src, int dst, int srcA, int mask) {
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000387
commit-bot@chromium.org12e0cda2013-07-15 12:40:54 +0000388 return dst + SkAlphaMul(src - SkAlphaMul(srcA, dst), mask);
reed@google.com181f4b32011-11-30 14:49:24 +0000389}
390
reed@google.com1750bf12011-11-15 19:51:02 +0000391static void LCD16_RowProc_Blend(SkPMColor* SK_RESTRICT dst,
reed@google.com5e127702011-11-28 16:32:01 +0000392 const uint16_t* SK_RESTRICT mask,
reed@google.com1750bf12011-11-15 19:51:02 +0000393 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 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000399
reed@google.com1750bf12011-11-15 19:51:02 +0000400 SkPMColor s = src[i];
401 SkPMColor d = dst[i];
402
403 int srcA = SkGetPackedA32(s);
404 int srcR = SkGetPackedR32(s);
reed@google.com181f4b32011-11-30 14:49:24 +0000405 int srcG = SkGetPackedG32(s);
reed@google.com1750bf12011-11-15 19:51:02 +0000406 int srcB = SkGetPackedB32(s);
reed@google.com181f4b32011-11-30 14:49:24 +0000407
408 srcA += srcA >> 7;
409
reed@google.com1750bf12011-11-15 19:51:02 +0000410 /* 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);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000416
reed@google.com181f4b32011-11-30 14:49:24 +0000417 maskR = upscale31To255(maskR);
418 maskG = upscale31To255(maskG);
419 maskB = upscale31To255(maskB);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000420
reed@google.com1750bf12011-11-15 19:51:02 +0000421 int dstR = SkGetPackedR32(d);
422 int dstG = SkGetPackedG32(d);
423 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000424
reed@google.com1750bf12011-11-15 19:51:02 +0000425 // LCD blitting is only supported if the dst is known/required
426 // to be opaque
427 dst[i] = SkPackARGB32(0xFF,
reed@google.com181f4b32011-11-30 14:49:24 +0000428 src_alpha_blend(srcR, dstR, srcA, maskR),
429 src_alpha_blend(srcG, dstG, srcA, maskG),
430 src_alpha_blend(srcB, dstB, srcA, maskB));
reed@google.com1750bf12011-11-15 19:51:02 +0000431 }
432}
433
434static void LCD16_RowProc_Opaque(SkPMColor* SK_RESTRICT dst,
reed@google.com5e127702011-11-28 16:32:01 +0000435 const uint16_t* SK_RESTRICT mask,
reed@google.com1750bf12011-11-15 19:51:02 +0000436 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 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000442
reed@google.com1750bf12011-11-15 19:51:02 +0000443 SkPMColor s = src[i];
444 SkPMColor d = dst[i];
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000445
reed@google.com1750bf12011-11-15 19:51:02 +0000446 int srcR = SkGetPackedR32(s);
reed@google.com181f4b32011-11-30 14:49:24 +0000447 int srcG = SkGetPackedG32(s);
reed@google.com1750bf12011-11-15 19:51:02 +0000448 int srcB = SkGetPackedB32(s);
reed@google.com181f4b32011-11-30 14:49:24 +0000449
reed@google.com1750bf12011-11-15 19:51:02 +0000450 /* 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);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000456
reed@google.com1750bf12011-11-15 19:51:02 +0000457 // Now upscale them to 0..32, so we can use blend32
tomhudson@google.comd6770e62012-02-14 16:01:15 +0000458 maskR = SkUpscale31To32(maskR);
459 maskG = SkUpscale31To32(maskG);
460 maskB = SkUpscale31To32(maskB);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000461
reed@google.com1750bf12011-11-15 19:51:02 +0000462 int dstR = SkGetPackedR32(d);
463 int dstG = SkGetPackedG32(d);
464 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000465
reed@google.com1750bf12011-11-15 19:51:02 +0000466 // LCD blitting is only supported if the dst is known/required
467 // to be opaque
468 dst[i] = SkPackARGB32(0xFF,
tomhudson@google.comd6770e62012-02-14 16:01:15 +0000469 SkBlend32(srcR, dstR, maskR),
470 SkBlend32(srcG, dstG, maskG),
471 SkBlend32(srcB, dstB, maskB));
reed@google.com1750bf12011-11-15 19:51:02 +0000472 }
473}
474
475static 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);
reed@google.comfb823002011-11-30 14:29:55 +0000487 int srcG = SkGetPackedG32(s);
reed@google.com1750bf12011-11-15 19:51:02 +0000488 int srcB = SkGetPackedB32(s);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000489
reed@google.com1750bf12011-11-15 19:51:02 +0000490 srcA = SkAlpha255To256(srcA);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000491
reed@google.com1750bf12011-11-15 19:51:02 +0000492 SkPMColor d = dst[i];
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000493
reed@google.com1750bf12011-11-15 19:51:02 +0000494 int maskR = SkGetPackedR32(m);
495 int maskG = SkGetPackedG32(m);
496 int maskB = SkGetPackedB32(m);
497
reed@google.comfb823002011-11-30 14:29:55 +0000498 // Now upscale them to 0..256
reed@google.com1750bf12011-11-15 19:51:02 +0000499 maskR = SkAlpha255To256(maskR);
500 maskG = SkAlpha255To256(maskG);
501 maskB = SkAlpha255To256(maskB);
reed@google.comfb823002011-11-30 14:29:55 +0000502
reed@google.com1750bf12011-11-15 19:51:02 +0000503 int dstR = SkGetPackedR32(d);
504 int dstG = SkGetPackedG32(d);
505 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000506
reed@google.com1750bf12011-11-15 19:51:02 +0000507 // LCD blitting is only supported if the dst is known/required
508 // to be opaque
509 dst[i] = SkPackARGB32(0xFF,
reed@google.comfb823002011-11-30 14:29:55 +0000510 src_alpha_blend(srcR, dstR, srcA, maskR),
511 src_alpha_blend(srcG, dstG, srcA, maskG),
512 src_alpha_blend(srcB, dstB, srcA, maskB));
reed@google.com1750bf12011-11-15 19:51:02 +0000513 }
514}
515
516static 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 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000524
reed@google.com1750bf12011-11-15 19:51:02 +0000525 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);
reed@google.comfb823002011-11-30 14:29:55 +0000531
reed@google.com1750bf12011-11-15 19:51:02 +0000532 int srcR = SkGetPackedR32(s);
reed@google.comfb823002011-11-30 14:29:55 +0000533 int srcG = SkGetPackedG32(s);
534 int srcB = SkGetPackedB32(s);
535
reed@google.com1750bf12011-11-15 19:51:02 +0000536 int dstR = SkGetPackedR32(d);
537 int dstG = SkGetPackedG32(d);
538 int dstB = SkGetPackedB32(d);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000539
reed@google.com1750bf12011-11-15 19:51:02 +0000540 // 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
554SkBlitMask::RowProc SkBlitMask::RowFactory(SkBitmap::Config config,
555 SkMask::Format format,
556 RowFlags flags) {
reed@google.comd4780e22011-11-15 20:49:52 +0000557// make this opt-in until chrome can rebaseline
reed@google.com1750bf12011-11-15 19:51:02 +0000558 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
caryclark@google.com803eceb2012-06-06 12:09:34 +0000565 false ? (RowProc)BW_RowProc_Blend : NULL, // suppress unused warning
566 false ? (RowProc)BW_RowProc_Opaque : NULL, // suppress unused warning
reed@google.com1750bf12011-11-15 19:51:02 +0000567 (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}