SkBlitter_RGB16.cpp revision 5119bdb952025a30f115b9c6a187173956e55097
1/* libs/graphics/sgl/SkBlitter_RGB16.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkBlitRow.h"
19#include "SkCoreBlitters.h"
20#include "SkColorPriv.h"
21#include "SkDither.h"
22#include "SkShader.h"
23#include "SkUtils.h"
24#include "SkXfermode.h"
25
26void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
27                        int count) {
28    if (count > 0) {
29        // see if we need to write one short before we can cast to an 4byte ptr
30        // (we do this subtract rather than (unsigned)dst so we don't get warnings
31        //  on 64bit machines)
32        if (((char*)dst - (char*)0) & 2) {
33            *dst++ = value;
34            count -= 1;
35            SkTSwap(value, other);
36        }
37
38        // fast way to set [value,other] pairs
39#ifdef SK_CPU_BENDIAN
40        sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
41#else
42        sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
43#endif
44
45        if (count & 1) {
46            dst[count - 1] = value;
47        }
48    }
49}
50
51///////////////////////////////////////////////////////////////////////////////
52
53SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint)
54    : SkRGB16_Blitter(device, paint) {
55    SkASSERT(paint.getShader() == NULL);
56    SkASSERT(paint.getColorFilter() == NULL);
57    SkASSERT(paint.getXfermode() == NULL);
58    SkASSERT(paint.getColor() == SK_ColorBLACK);
59}
60
61#if 1
62#define black_8_pixels(mask, dst)       \
63    do {                                \
64        if (mask & 0x80) dst[0] = 0;    \
65        if (mask & 0x40) dst[1] = 0;    \
66        if (mask & 0x20) dst[2] = 0;    \
67        if (mask & 0x10) dst[3] = 0;    \
68        if (mask & 0x08) dst[4] = 0;    \
69        if (mask & 0x04) dst[5] = 0;    \
70        if (mask & 0x02) dst[6] = 0;    \
71        if (mask & 0x01) dst[7] = 0;    \
72    } while (0)
73#else
74static inline black_8_pixels(U8CPU mask, uint16_t dst[])
75{
76    if (mask & 0x80) dst[0] = 0;
77    if (mask & 0x40) dst[1] = 0;
78    if (mask & 0x20) dst[2] = 0;
79    if (mask & 0x10) dst[3] = 0;
80    if (mask & 0x08) dst[4] = 0;
81    if (mask & 0x04) dst[5] = 0;
82    if (mask & 0x02) dst[6] = 0;
83    if (mask & 0x01) dst[7] = 0;
84}
85#endif
86
87#define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
88#define SK_BLITBWMASK_ARGS
89#define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
90#define SK_BLITBWMASK_GETADDR               getAddr16
91#define SK_BLITBWMASK_DEVTYPE               uint16_t
92#include "SkBlitBWMaskTemplate.h"
93
94void SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
95                                     const SkIRect& SK_RESTRICT clip)
96                                     SK_RESTRICT {
97    if (mask.fFormat == SkMask::kBW_Format) {
98        SkRGB16_Black_BlitBW(fDevice, mask, clip);
99    } else {
100        uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
101        const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
102        unsigned width = clip.width();
103        unsigned height = clip.height();
104        unsigned deviceRB = fDevice.rowBytes() - (width << 1);
105        unsigned maskRB = mask.fRowBytes - width;
106
107        SkASSERT((int)height > 0);
108        SkASSERT((int)width > 0);
109        SkASSERT((int)deviceRB >= 0);
110        SkASSERT((int)maskRB >= 0);
111
112        do {
113            unsigned w = width;
114            do {
115                unsigned aa = *alpha++;
116                *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
117                device += 1;
118            } while (--w != 0);
119            device = (uint16_t*)((char*)device + deviceRB);
120            alpha += maskRB;
121        } while (--height != 0);
122    }
123}
124
125void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
126                                      const SkAlpha* SK_RESTRICT antialias,
127                                      const int16_t* SK_RESTRICT runs)
128                                      SK_RESTRICT {
129    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
130
131    for (;;) {
132        int count = runs[0];
133        SkASSERT(count >= 0);
134        if (count <= 0) {
135            return;
136        }
137        runs += count;
138
139        unsigned aa = antialias[0];
140        antialias += count;
141        if (aa) {
142            if (aa == 255) {
143                memset(device, 0, count << 1);
144            } else {
145                aa = SkAlpha255To256(255 - aa);
146                do {
147                    *device = SkAlphaMulRGB16(*device, aa);
148                    device += 1;
149                } while (--count != 0);
150                continue;
151            }
152        }
153        device += count;
154    }
155}
156
157//////////////////////////////////////////////////////////////////////////////////////////////////
158//////////////////////////////////////////////////////////////////////////////////////////////////
159
160SkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint)
161    : INHERITED(device) {
162    SkColor color = paint.getColor();
163
164    fSrcColor32 = SkPreMultiplyColor(color);
165    fScale = SkAlpha255To256(SkColorGetA(color));
166
167    int r = SkColorGetR(color);
168    int g = SkColorGetG(color);
169    int b = SkColorGetB(color);
170
171    fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
172    // if we're dithered, use fRawDither16 to hold that.
173    if ((fDoDither = paint.isDither()) != false) {
174        fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
175    }
176
177    fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
178                            SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
179                            SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
180}
181
182const SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
183    if (!fDoDither && 256 == fScale) {
184        *value = fRawColor16;
185        return &fDevice;
186    }
187    return NULL;
188}
189
190void SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
191    SkASSERT(width > 0);
192    SkASSERT(x + width <= fDevice.width());
193
194    if (fScale == 0) {
195        return;
196    }
197
198    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
199    uint16_t srcColor = fColor16;
200
201    if (256 == fScale) {
202        SkASSERT(fRawColor16 == srcColor);
203        if (fDoDither) {
204            uint16_t ditherColor = fRawDither16;
205            if ((x ^ y) & 1) {
206                SkTSwap(ditherColor, srcColor);
207            }
208            sk_dither_memset16(device, srcColor, ditherColor, width);
209        } else {
210            sk_memset16(device, srcColor, width);
211        }
212    } else {
213        // TODO: respect fDoDither
214        SkPMColor src32 = fSrcColor32;
215        do {
216            *device = SkSrcOver32To16(src32, *device);
217            device += 1;
218        } while (--width != 0);
219    }
220}
221
222// return 1 or 0 from a bool
223static int Bool2Int(bool value) {
224    return !!value;
225}
226
227void SkRGB16_Blitter::blitAntiH(int x, int y,
228                                const SkAlpha* SK_RESTRICT antialias,
229                                const int16_t* SK_RESTRICT runs) SK_RESTRICT {
230    if (fScale == 0) {
231        return;
232    }
233
234    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
235    uint16_t    srcColor = fRawColor16;
236    unsigned    scale = fScale;
237    int         ditherInt = Bool2Int(fDoDither);
238
239    if (256 == scale) {
240        uint16_t    ditherColor = fRawDither16;
241        // if we have no dithering, this will always fail
242        if ((x ^ y) & ditherInt) {
243            SkTSwap(ditherColor, srcColor);
244        }
245        for (;;) {
246            int count = runs[0];
247            SkASSERT(count >= 0);
248            if (count <= 0) {
249                return;
250            }
251            runs += count;
252
253            unsigned aa = antialias[0];
254            antialias += count;
255            if (aa) {
256                if (aa == 255) {
257                    if (ditherInt) {
258                        sk_dither_memset16(device, srcColor,
259                                           ditherColor, count);
260                    } else {
261                        sk_memset16(device, srcColor, count);
262                    }
263                } else {
264                    // TODO: respect fDoDither
265                    unsigned scale5 = SkAlpha255To256(aa) >> 3;
266                    uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5;
267                    scale5 = 32 - scale5; // now we can use it on the device
268                    int n = count;
269                    do {
270                        uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
271                        *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
272                    } while (--n != 0);
273                    goto DONE;
274                }
275            }
276            device += count;
277
278            DONE:
279            // if we have no dithering, this will always fail
280            if (count & ditherInt) {
281                SkTSwap(ditherColor, srcColor);
282            }
283        }
284    } else {
285        // TODO: respect fDoDither
286        for (;;) {
287            int count = runs[0];
288            SkASSERT(count >= 0);
289            if (count <= 0) {
290                return;
291            }
292            runs += count;
293
294            unsigned aa = antialias[0];
295            antialias += count;
296            if (aa) {
297                unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
298                uint32_t src32 =  SkExpand_rgb_16(srcColor) * scale5;
299                scale5 = 32 - scale5;
300                do {
301                    uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
302                    *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
303                } while (--count != 0);
304                continue;
305            }
306            device += count;
307        }
308    }
309}
310
311//////////////////////////////////////////////////////////////////////////////////////
312
313#define solid_8_pixels(mask, dst, color)    \
314    do {                                    \
315        if (mask & 0x80) dst[0] = color;    \
316        if (mask & 0x40) dst[1] = color;    \
317        if (mask & 0x20) dst[2] = color;    \
318        if (mask & 0x10) dst[3] = color;    \
319        if (mask & 0x08) dst[4] = color;    \
320        if (mask & 0x04) dst[5] = color;    \
321        if (mask & 0x02) dst[6] = color;    \
322        if (mask & 0x01) dst[7] = color;    \
323    } while (0)
324
325#define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
326#define SK_BLITBWMASK_ARGS                  , uint16_t color
327#define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
328#define SK_BLITBWMASK_GETADDR               getAddr16
329#define SK_BLITBWMASK_DEVTYPE               uint16_t
330#include "SkBlitBWMaskTemplate.h"
331
332static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
333                                  U16CPU srcColor) {
334    if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
335    if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
336    if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
337    if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
338    if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
339    if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
340    if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
341    if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
342}
343
344#define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
345#define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
346#define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
347#define SK_BLITBWMASK_GETADDR               getAddr16
348#define SK_BLITBWMASK_DEVTYPE               uint16_t
349#include "SkBlitBWMaskTemplate.h"
350
351static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
352    return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
353}
354
355void SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask,
356                               const SkIRect& SK_RESTRICT clip) SK_RESTRICT {
357    if (fScale == 0) {
358        return;
359    }
360    if (mask.fFormat == SkMask::kBW_Format) {
361        if (fScale == 256) {
362            SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
363        } else {
364            SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
365        }
366        return;
367    }
368
369    uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop);
370    const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop);
371    int width = clip.width();
372    int height = clip.height();
373    unsigned    deviceRB = fDevice.rowBytes() - (width << 1);
374    unsigned    maskRB = mask.fRowBytes - width;
375    uint32_t    color32 = SkExpand_rgb_16(fRawColor16);
376
377    if (256 == fScale) {
378        do {
379            int w = width;
380            do {
381                *device = blend_compact(color32, SkExpand_rgb_16(*device),
382                                        SkAlpha255To256(*alpha++) >> 3);
383                device += 1;
384            } while (--w != 0);
385            device = (uint16_t*)((char*)device + deviceRB);
386            alpha += maskRB;
387        } while (--height != 0);
388    } else {   // scale < 256
389        unsigned scale256 = fScale;
390        do {
391            int w = width;
392            do {
393                unsigned aa = *alpha++;
394                unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
395                uint32_t src32 = color32 * scale;
396                uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
397                *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
398            } while (--w != 0);
399            device = (uint16_t*)((char*)device + deviceRB);
400            alpha += maskRB;
401        } while (--height != 0);
402    }
403}
404
405void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
406    if (fScale == 0) {
407        return;
408    }
409    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
410    uint16_t    color16 = fRawColor16;
411    unsigned    deviceRB = fDevice.rowBytes();
412
413    if (alpha + fScale == (255 + 256)) {
414        if (fDoDither) {
415            uint16_t ditherColor = fRawDither16;
416            if ((x ^ y) & 1) {
417                SkTSwap(ditherColor, color16);
418            }
419            do {
420                device[0] = color16;
421                device = (uint16_t*)((char*)device + deviceRB);
422                SkTSwap(ditherColor, color16);
423            } while (--height != 0);
424        } else {
425            do {
426                device[0] = color16;
427                device = (uint16_t*)((char*)device + deviceRB);
428            } while (--height != 0);
429        }
430    } else {
431        // TODO: respect fDoDither
432        unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
433        uint32_t src32 =  SkExpand_rgb_16(color16) * scale5;
434        scale5 = 32 - scale5;
435        do {
436            uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
437            *device = SkCompact_rgb_16((src32 + dst32) >> 5);
438            device = (uint16_t*)((char*)device + deviceRB);
439        } while (--height != 0);
440    }
441}
442
443void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
444    SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
445
446    if (fScale == 0) {
447        return;
448    }
449    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
450    unsigned    deviceRB = fDevice.rowBytes();
451    uint16_t    color16 = fColor16;
452
453    if (256 == fScale) {
454        if (fDoDither) {
455            uint16_t ditherColor = fRawDither16;
456            if ((x ^ y) & 1) {
457                SkTSwap(ditherColor, color16);
458            }
459            while (--height >= 0) {
460                sk_dither_memset16(device, color16, ditherColor, width);
461                SkTSwap(ditherColor, color16);
462                device = (uint16_t*)((char*)device + deviceRB);
463            }
464        } else {  // no dither
465            while (--height >= 0) {
466                sk_memset16(device, color16, width);
467                device = (uint16_t*)((char*)device + deviceRB);
468            }
469        }
470    } else {
471        SkPMColor src32 = fSrcColor32;
472        while (--height >= 0) {
473            for (int i = width - 1; i >= 0; --i) {
474                device[i] = SkSrcOver32To16(src32, device[i]);
475            }
476            device = (uint16_t*)((char*)device + deviceRB);
477        }
478    }
479}
480
481///////////////////////////////////////////////////////////////////////////////
482
483SkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device,
484                                                   const SkPaint& paint)
485    : SkRGB16_Shader_Blitter(device, paint) {
486    SkASSERT(SkShader::CanCallShadeSpan16(fShaderFlags));
487}
488
489void SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT {
490    SkASSERT(x + width <= fDevice.width());
491
492    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
493    SkShader*   shader = fShader;
494
495    int alpha = shader->getSpan16Alpha();
496    if (0xFF == alpha) {
497        shader->shadeSpan16(x, y, device, width);
498    } else {
499        uint16_t* span16 = (uint16_t*)fBuffer;
500        shader->shadeSpan16(x, y, span16, width);
501        SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width);
502    }
503}
504
505void SkRGB16_Shader16_Blitter::blitAntiH(int x, int y,
506                                         const SkAlpha* SK_RESTRICT antialias,
507                                         const int16_t* SK_RESTRICT runs)
508                                         SK_RESTRICT {
509    SkShader*   shader = fShader;
510    SkPMColor* SK_RESTRICT span = fBuffer;
511    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
512
513    int alpha = shader->getSpan16Alpha();
514    uint16_t* span16 = (uint16_t*)span;
515
516    if (0xFF == alpha) {
517        for (;;) {
518            int count = *runs;
519            if (count <= 0) {
520                break;
521            }
522            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
523
524            int aa = *antialias;
525            if (aa == 255) {
526                // go direct to the device!
527                shader->shadeSpan16(x, y, device, count);
528            } else if (aa) {
529                shader->shadeSpan16(x, y, span16, count);
530                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
531            }
532            device += count;
533            runs += count;
534            antialias += count;
535            x += count;
536        }
537    } else {  // span alpha is < 255
538        alpha = SkAlpha255To256(alpha);
539        for (;;) {
540            int count = *runs;
541            if (count <= 0) {
542                break;
543            }
544            SkASSERT(count <= fDevice.width()); // don't overrun fBuffer
545
546            int aa = SkAlphaMul(*antialias, alpha);
547            if (aa) {
548                shader->shadeSpan16(x, y, span16, count);
549                SkBlendRGB16(span16, device, SkAlpha255To256(aa), count);
550            }
551
552            device += count;
553            runs += count;
554            antialias += count;
555            x += count;
556        }
557    }
558}
559
560///////////////////////////////////////////////////////////////////////////////
561
562SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device,
563                                               const SkPaint& paint)
564: INHERITED(device, paint) {
565    SkASSERT(paint.getXfermode() == NULL);
566
567    fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
568
569    // compute SkBlitRow::Procs
570    unsigned flags = 0;
571
572    uint32_t shaderFlags = fShaderFlags;
573    // shaders take care of global alpha, so we never set it in SkBlitRow
574    if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
575        flags |= SkBlitRow::kSrcPixelAlpha_Flag;
576        }
577    // don't dither if the shader is really 16bit
578    if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) {
579        flags |= SkBlitRow::kDither_Flag;
580    }
581    // used when we know our global alpha is 0xFF
582    fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config);
583    // used when we know our global alpha is < 0xFF
584    fAlphaProc  = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag,
585                                     SkBitmap::kRGB_565_Config);
586}
587
588SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
589    sk_free(fBuffer);
590}
591
592void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
593    SkASSERT(x + width <= fDevice.width());
594
595    fShader->shadeSpan(x, y, fBuffer, width);
596    // shaders take care of global alpha, so we pass 0xFF (should be ignored)
597    fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y);
598}
599
600void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
601    SkShader*       shader = fShader;
602    SkBlitRow::Proc proc = fOpaqueProc;
603    SkPMColor*      buffer = fBuffer;
604    uint16_t*       dst = fDevice.getAddr16(x, y);
605    size_t          dstRB = fDevice.rowBytes();
606
607    if (fShaderFlags & SkShader::kConstInY_Flag) {
608        shader->shadeSpan(x, y, buffer, width);
609        do {
610            proc(dst, buffer, width, 0xFF, x, y);
611            y += 1;
612            dst = (uint16_t*)((char*)dst + dstRB);
613        } while (--height);
614    } else {
615        do {
616            shader->shadeSpan(x, y, buffer, width);
617            proc(dst, buffer, width, 0xFF, x, y);
618            y += 1;
619            dst = (uint16_t*)((char*)dst + dstRB);
620        } while (--height);
621    }
622}
623
624static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
625    int count = 0;
626    for (;;) {
627        int n = *runs;
628        if (n == 0 || *aa == 0) {
629            break;
630        }
631        runs += n;
632        aa += n;
633        count += n;
634    }
635    return count;
636}
637
638void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
639                                       const SkAlpha* SK_RESTRICT antialias,
640                                       const int16_t* SK_RESTRICT runs)
641                                       SK_RESTRICT {
642    SkShader*   shader = fShader;
643    SkPMColor* SK_RESTRICT span = fBuffer;
644    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
645
646    for (;;) {
647        int count = *runs;
648        if (count <= 0) {
649            break;
650        }
651        int aa = *antialias;
652        if (0 == aa) {
653            device += count;
654            runs += count;
655            antialias += count;
656            x += count;
657            continue;
658        }
659
660        int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
661
662        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
663        shader->shadeSpan(x, y, span, nonZeroCount);
664
665        SkPMColor* localSpan = span;
666        for (;;) {
667            SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
668            proc(device, localSpan, count, aa, x, y);
669
670            x += count;
671            device += count;
672            runs += count;
673            antialias += count;
674            nonZeroCount -= count;
675            if (nonZeroCount == 0) {
676                break;
677            }
678            localSpan += count;
679            SkASSERT(nonZeroCount > 0);
680            count = *runs;
681            SkASSERT(count > 0);
682            aa = *antialias;
683        }
684    }
685}
686
687///////////////////////////////////////////////////////////////////////
688
689SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
690                                const SkBitmap& device, const SkPaint& paint)
691: INHERITED(device, paint) {
692    fXfermode = paint.getXfermode();
693    SkASSERT(fXfermode);
694    fXfermode->ref();
695
696    int width = device.width();
697    fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
698    fAAExpand = (uint8_t*)(fBuffer + width);
699}
700
701SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
702    fXfermode->unref();
703    sk_free(fBuffer);
704}
705
706void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
707    SkASSERT(x + width <= fDevice.width());
708
709    uint16_t*   device = fDevice.getAddr16(x, y);
710    SkPMColor*  span = fBuffer;
711
712    fShader->shadeSpan(x, y, span, width);
713    fXfermode->xfer16(device, span, width, NULL);
714}
715
716void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
717                                const SkAlpha* SK_RESTRICT antialias,
718                                const int16_t* SK_RESTRICT runs) SK_RESTRICT {
719    SkShader*   shader = fShader;
720    SkXfermode* mode = fXfermode;
721    SkPMColor* SK_RESTRICT span = fBuffer;
722    uint8_t* SK_RESTRICT aaExpand = fAAExpand;
723    uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y);
724
725    for (;;) {
726        int count = *runs;
727        if (count <= 0) {
728            break;
729        }
730        int aa = *antialias;
731        if (0 == aa) {
732            device += count;
733            runs += count;
734            antialias += count;
735            x += count;
736            continue;
737        }
738
739        int nonZeroCount = count + count_nonzero_span(runs + count,
740                                                      antialias + count);
741
742        SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
743        shader->shadeSpan(x, y, span, nonZeroCount);
744
745        x += nonZeroCount;
746        SkPMColor* localSpan = span;
747        for (;;) {
748            if (aa == 0xFF) {
749                mode->xfer16(device, localSpan, count, NULL);
750            } else {
751                SkASSERT(aa);
752                memset(aaExpand, aa, count);
753                mode->xfer16(device, localSpan, count, aaExpand);
754            }
755            device += count;
756            runs += count;
757            antialias += count;
758            nonZeroCount -= count;
759            if (nonZeroCount == 0) {
760                break;
761            }
762            localSpan += count;
763            SkASSERT(nonZeroCount > 0);
764            count = *runs;
765            SkASSERT(count > 0);
766            aa = *antialias;
767        }
768    }
769}
770
771////////////////////////
772
773#if 0
774static inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa
775#ifdef DITHER_SHADER
776                                      , int dither
777#endif
778                                      )
779{
780    SkASSERT((unsigned)aa <= 255);
781
782    int src_scale = SkAlpha255To256(aa);
783    int sa = SkGetPackedA32(src);
784    int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale));
785
786#ifdef DITHER_SHADER
787    int sr = SkGetPackedR32(src);
788    int sg = SkGetPackedG32(src);
789    int sb = SkGetPackedB32(src);
790    sr = SkDITHER_R32To16(sr, dither);
791    sg = SkDITHER_G32To16(sg, dither);
792    sb = SkDITHER_B32To16(sb, dither);
793#else
794    int sr = SkPacked32ToR16(src);
795    int sg = SkPacked32ToG16(src);
796    int sb = SkPacked32ToB16(src);
797#endif
798
799    int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8;
800    int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8;
801    int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8;
802
803    return SkPackRGB16(dr, dg, db);
804}
805#endif
806
807