SkBlitMask_D32.cpp revision 83a444602ec580a0040713eed588c245b4ae0ee9
1#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
67///////////////////////////////////////////////////////////////////////////////
68
69static inline int upscale31To32(int value) {
70    SkASSERT((unsigned)value <= 31);
71    return value + (value >> 4);
72}
73
74static inline int blend32(int src, int dst, int scale) {
75    SkASSERT((unsigned)src <= 0xFF);
76    SkASSERT((unsigned)dst <= 0xFF);
77    SkASSERT((unsigned)scale <= 32);
78    return dst + ((src - dst) * scale >> 5);
79}
80
81static void blit_lcd16_row(SkPMColor dst[], const uint16_t src[],
82                           SkColor color, int width, SkPMColor) {
83    int srcA = SkColorGetA(color);
84    int srcR = SkColorGetR(color);
85    int srcG = SkColorGetG(color);
86    int srcB = SkColorGetB(color);
87
88    srcA = SkAlpha255To256(srcA);
89
90    for (int i = 0; i < width; i++) {
91        uint16_t mask = src[i];
92        if (0 == mask) {
93            continue;
94        }
95
96        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        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
102        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
103        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
104
105        // Now upscale them to 0..32, so we can use blend32
106        maskR = upscale31To32(maskR);
107        maskG = upscale31To32(maskG);
108        maskB = upscale31To32(maskB);
109
110        maskR = maskR * srcA >> 8;
111        maskG = maskG * srcA >> 8;
112        maskB = maskB * srcA >> 8;
113
114        int dstR = SkGetPackedR32(d);
115        int dstG = SkGetPackedG32(d);
116        int dstB = SkGetPackedB32(d);
117
118        // LCD blitting is only supported if the dst is known/required
119        // to be opaque
120        dst[i] = SkPackARGB32(0xFF,
121                              blend32(srcR, dstR, maskR),
122                              blend32(srcG, dstG, maskG),
123                              blend32(srcB, dstB, maskB));
124    }
125}
126
127static void blit_lcd16_opaque_row(SkPMColor dst[], const uint16_t src[],
128                                  SkColor color, int width, SkPMColor opaqueDst) {
129    int srcR = SkColorGetR(color);
130    int srcG = SkColorGetG(color);
131    int srcB = SkColorGetB(color);
132
133    for (int i = 0; i < width; i++) {
134        uint16_t mask = src[i];
135        if (0 == mask) {
136            continue;
137        }
138        if (0xFFFF == mask) {
139            dst[i] = opaqueDst;
140            continue;
141        }
142
143        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        int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
149        int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
150        int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
151
152        // Now upscale them to 0..32, so we can use blend32
153        maskR = upscale31To32(maskR);
154        maskG = upscale31To32(maskG);
155        maskB = upscale31To32(maskB);
156
157        int dstR = SkGetPackedR32(d);
158        int dstG = SkGetPackedG32(d);
159        int dstB = SkGetPackedB32(d);
160
161        // LCD blitting is only supported if the dst is known/required
162        // to be opaque
163        dst[i] = SkPackARGB32(0xFF,
164                              blend32(srcR, dstR, maskR),
165                              blend32(srcG, dstG, maskG),
166                              blend32(srcB, dstB, maskB));
167    }
168}
169
170static 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    SkPMColor*		dstRow = (SkPMColor*)dst;
175    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    if (0xFF == SkColorGetA(color)) {
181        proc = blit_lcd16_opaque_row;
182        opaqueDst = SkPreMultiplyColor(color);
183    } else {
184        proc = blit_lcd16_row;
185        opaqueDst = 0;  // ignored
186    }
187
188    do {
189        proc(dstRow, srcRow, color, width, opaqueDst);
190        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
191        srcRow = (const uint16_t*)((const char*)srcRow + maskRB);
192    } while (--height != 0);
193}
194
195///////////////////////////////////////////////////////////////////////////////
196
197static void blit_lcd32_opaque_row(SkPMColor* SK_RESTRICT dst,
198                                  const SkPMColor* SK_RESTRICT src,
199                                  SkColor color, int width) {
200    int srcR = SkColorGetR(color);
201    int srcG = SkColorGetG(color);
202    int srcB = SkColorGetB(color);
203
204    for (int i = 0; i < width; i++) {
205        SkPMColor mask = src[i];
206        if (0 == mask) {
207            continue;
208        }
209
210        SkPMColor d = dst[i];
211
212        int maskR = SkGetPackedR32(mask);
213        int maskG = SkGetPackedG32(mask);
214        int maskB = SkGetPackedB32(mask);
215
216        // Now upscale them to 0..256, so we can use SkAlphaBlend
217        maskR = SkAlpha255To256(maskR);
218        maskG = SkAlpha255To256(maskG);
219        maskB = SkAlpha255To256(maskB);
220
221        int dstR = SkGetPackedR32(d);
222        int dstG = SkGetPackedG32(d);
223        int dstB = SkGetPackedB32(d);
224
225        // LCD blitting is only supported if the dst is known/required
226        // to be opaque
227        dst[i] = SkPackARGB32(0xFF,
228                              SkAlphaBlend(srcR, dstR, maskR),
229                              SkAlphaBlend(srcG, dstG, maskG),
230                              SkAlphaBlend(srcB, dstB, maskB));
231    }
232}
233
234static void blit_lcd32_row(SkPMColor* SK_RESTRICT dst,
235                           const SkPMColor* SK_RESTRICT src,
236                           SkColor color, int width) {
237    int srcA = SkColorGetA(color);
238    int srcR = SkColorGetR(color);
239    int srcG = SkColorGetG(color);
240    int srcB = SkColorGetB(color);
241
242    srcA = SkAlpha255To256(srcA);
243
244    for (int i = 0; i < width; i++) {
245        SkPMColor mask = src[i];
246        if (0 == mask) {
247            continue;
248        }
249
250        SkPMColor d = dst[i];
251
252        int maskR = SkGetPackedR32(mask);
253        int maskG = SkGetPackedG32(mask);
254        int maskB = SkGetPackedB32(mask);
255
256        // Now upscale them to 0..256, so we can use SkAlphaBlend
257        maskR = SkAlpha255To256(maskR);
258        maskG = SkAlpha255To256(maskG);
259        maskB = SkAlpha255To256(maskB);
260
261        maskR = maskR * srcA >> 8;
262        maskG = maskG * srcA >> 8;
263        maskB = maskB * srcA >> 8;
264
265        int dstR = SkGetPackedR32(d);
266        int dstG = SkGetPackedG32(d);
267        int dstB = SkGetPackedB32(d);
268
269        // LCD blitting is only supported if the dst is known/required
270        // to be opaque
271        dst[i] = SkPackARGB32(0xFF,
272                              SkAlphaBlend(srcR, dstR, maskR),
273                              SkAlphaBlend(srcG, dstG, maskG),
274                              SkAlphaBlend(srcB, dstB, maskB));
275    }
276}
277
278static 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    SkASSERT(height > 0);
282    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
283    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
284
285    do {
286        blit_lcd32_row(dstRow, srcRow, color, width);
287        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
288        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
289    } while (--height != 0);
290}
291
292static 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    SkASSERT(height > 0);
296    SkPMColor* SK_RESTRICT dstRow = (SkPMColor*)dst;
297    const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)mask;
298
299    do {
300        blit_lcd32_opaque_row(dstRow, srcRow, color, width);
301        dstRow = (SkPMColor*)((char*)dstRow + dstRB);
302        srcRow = (const SkPMColor*)((const char*)srcRow + maskRB);
303    } while (--height != 0);
304}
305
306///////////////////////////////////////////////////////////////////////////////
307
308static SkBlitMask::Proc D32_A8_Factory(SkColor color) {
309    if (SK_ColorBLACK == color) {
310        return D32_A8_Black;
311    } else if (0xFF == SkColorGetA(color)) {
312        return D32_A8_Opaque;
313    } else {
314        return D32_A8_Color;
315    }
316}
317
318static SkBlitMask::Proc D32_LCD32_Factory(SkColor color) {
319    return (0xFF == SkColorGetA(color)) ? D32_LCD32_Opaque : D32_LCD32_Blend;
320}
321
322SkBlitMask::Proc SkBlitMask::Factory(SkBitmap::Config config,
323                                     SkMask::Format format, SkColor color) {
324    SkBlitMask::Proc proc = PlatformProcs(config, format, color);
325    if (proc) {
326        return proc;
327    }
328
329    switch (config) {
330        case SkBitmap::kARGB_8888_Config:
331            switch (format) {
332                case SkMask::kA8_Format:
333                    return D32_A8_Factory(color);
334                case SkMask::kLCD16_Format:
335                    return D32_LCD16_Proc;
336                case SkMask::kLCD32_Format:
337                    return D32_LCD32_Factory(color);
338                default:
339                    break;
340            }
341            break;
342        default:
343            break;
344    }
345    return NULL;
346}
347
348bool SkBlitMask::BlitColor(const SkBitmap& device, const SkMask& mask,
349                           const SkIRect& clip, SkColor color) {
350    Proc proc = Factory(device.config(), mask.fFormat, color);
351    if (proc) {
352        int x = clip.fLeft;
353        int y = clip.fTop;
354        proc(device.getAddr32(x, y), device.rowBytes(), mask.getAddr(x, y),
355             mask.fRowBytes, color, clip.width(), clip.height());
356        return true;
357    }
358    return false;
359}
360
361
362