1/*
2 * Copyright 2011 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 "SkBlitRow.h"
9#include "SkColorPriv.h"
10#include "SkDither.h"
11
12///////////////////////////////////////////////////////////////////////////////
13
14static void S32_D4444_Opaque(uint16_t* SK_RESTRICT dst,
15                             const SkPMColor* SK_RESTRICT src, int count,
16                             U8CPU alpha, int /*x*/, int /*y*/) {
17    SkASSERT(255 == alpha);
18
19    if (count > 0) {
20        do {
21            SkPMColor c = *src++;
22            SkPMColorAssert(c);
23            SkASSERT(SkGetPackedA32(c) == 255);
24            *dst++ = SkPixel32ToPixel4444(c);
25        } while (--count != 0);
26    }
27}
28
29static void S32_D4444_Blend(uint16_t* SK_RESTRICT dst,
30                            const SkPMColor* SK_RESTRICT src, int count,
31                            U8CPU alpha, int /*x*/, int /*y*/) {
32    SkASSERT(255 > alpha);
33
34    if (count > 0) {
35        unsigned scale16 = SkAlpha255To256(alpha) >> 4;
36        do {
37            SkPMColor c = *src++;
38            SkPMColorAssert(c);
39            SkASSERT(SkGetPackedA32(c) == 255);
40
41            uint32_t src_expand = SkExpand32_4444(c);
42            uint32_t dst_expand = SkExpand_4444(*dst);
43            dst_expand += (src_expand - dst_expand) * scale16 >> 4;
44            *dst++ = SkCompact_4444(dst_expand);
45        } while (--count != 0);
46    }
47}
48
49static void S32A_D4444_Opaque(uint16_t* SK_RESTRICT dst,
50                              const SkPMColor* SK_RESTRICT src, int count,
51                              U8CPU alpha, int /*x*/, int /*y*/) {
52    SkASSERT(255 == alpha);
53
54    if (count > 0) {
55        do {
56            SkPMColor c = *src++;
57            SkPMColorAssert(c);
58//            if (__builtin_expect(c!=0, 1))
59            if (c)
60            {
61                unsigned scale16 = SkAlpha255To256(255 - SkGetPackedA32(c)) >> 4;
62                uint32_t src_expand = SkExpand_8888(c);
63                uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
64                *dst = SkCompact_4444((src_expand + dst_expand) >> 4);
65            }
66            dst += 1;
67        } while (--count != 0);
68    }
69}
70
71static void S32A_D4444_Blend(uint16_t* SK_RESTRICT dst,
72                             const SkPMColor* SK_RESTRICT src, int count,
73                             U8CPU alpha, int /*x*/, int /*y*/) {
74    SkASSERT(255 > alpha);
75
76    if (count > 0) {
77        int src_scale = SkAlpha255To256(alpha) >> 4;
78        do {
79            SkPMColor sc = *src++;
80            SkPMColorAssert(sc);
81
82            if (sc) {
83                unsigned dst_scale = 16 - (SkGetPackedA32(sc) * src_scale >> 8);
84                uint32_t src_expand = SkExpand32_4444(sc) * src_scale;
85                uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
86                *dst = SkCompact_4444((src_expand + dst_expand) >> 4);
87            }
88            dst += 1;
89        } while (--count != 0);
90    }
91}
92
93/////////////////////////////////////////////////////////////////////////////
94
95static void S32_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
96                                    const SkPMColor* SK_RESTRICT src,
97                                    int count, U8CPU alpha, int x, int y) {
98    SkASSERT(255 == alpha);
99
100    if (count > 0) {
101        DITHER_4444_SCAN(y);
102        do {
103            SkPMColor c = *src++;
104            SkPMColorAssert(c);
105            SkASSERT(SkGetPackedA32(c) == 255);
106
107            unsigned dither = DITHER_VALUE(x);
108            *dst++ = SkDitherARGB32To4444(c, dither);
109            DITHER_INC_X(x);
110        } while (--count != 0);
111    }
112}
113
114static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
115                                   const SkPMColor* SK_RESTRICT src,
116                                   int count, U8CPU alpha, int x, int y) {
117    SkASSERT(255 > alpha);
118
119    if (count > 0) {
120        int scale16 = SkAlpha255To256(alpha) >> 4;
121        DITHER_4444_SCAN(y);
122        do {
123            SkPMColor c = *src++;
124            SkPMColorAssert(c);
125            SkASSERT(SkGetPackedA32(c) == 255);
126
127            uint32_t src_expand = SkExpand32_4444(c) * scale16;
128            uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16);
129
130            c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor
131            *dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
132            DITHER_INC_X(x);
133        } while (--count != 0);
134    }
135}
136
137static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
138                                     const SkPMColor* SK_RESTRICT src,
139                                     int count, U8CPU alpha, int x, int y) {
140    SkASSERT(255 == alpha);
141
142    if (count > 0) {
143        DITHER_4444_SCAN(y);
144        do {
145            SkPMColor c = *src++;
146            SkPMColorAssert(c);
147            if (c) {
148                unsigned a = SkGetPackedA32(c);
149                int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
150
151                unsigned scale16 = SkAlpha255To256(255 - a) >> 4;
152                uint32_t src_expand = SkExpand_8888(c);
153                uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
154                // convert back to SkPMColor
155                c = SkCompact_8888(src_expand + dst_expand);
156                *dst = SkDitherARGB32To4444(c, d);
157            }
158            dst += 1;
159            DITHER_INC_X(x);
160        } while (--count != 0);
161    }
162}
163
164// need DitherExpand888To4444(expand, dither)
165
166static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
167                                    const SkPMColor* SK_RESTRICT src,
168                                    int count, U8CPU alpha, int x, int y) {
169    SkASSERT(255 > alpha);
170
171    if (count > 0) {
172        int src_scale = SkAlpha255To256(alpha) >> 4;
173        DITHER_4444_SCAN(y);
174        do {
175            SkPMColor c = *src++;
176            SkPMColorAssert(c);
177            if (c) {
178                unsigned a = SkAlpha255To256(SkGetPackedA32(c));
179                int d = SkAlphaMul(DITHER_VALUE(x), a);
180
181                unsigned dst_scale = 16 - SkAlphaMul(src_scale, a);
182                uint32_t src_expand = SkExpand32_4444(c) * src_scale;
183                uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
184                // convert back to SkPMColor
185                c = SkCompact_8888(src_expand + dst_expand);
186                *dst = SkDitherARGB32To4444(c, d);
187            }
188            dst += 1;
189            DITHER_INC_X(x);
190        } while (--count != 0);
191    }
192}
193
194///////////////////////////////////////////////////////////////////////////////
195///////////////////////////////////////////////////////////////////////////////
196
197static const SkBlitRow::Proc gProcs4444[] = {
198    // no dither
199    S32_D4444_Opaque,
200    S32_D4444_Blend,
201
202    S32A_D4444_Opaque,
203    S32A_D4444_Blend,
204
205    // dither
206    S32_D4444_Opaque_Dither,
207    S32_D4444_Blend_Dither,
208
209    S32A_D4444_Opaque_Dither,
210    S32A_D4444_Blend_Dither
211};
212
213SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
214SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags)
215{
216    SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444));
217
218    return gProcs4444[flags];
219}
220
221
222