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
S32_D4444_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)14 static 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
S32_D4444_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)29 static 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
S32A_D4444_Opaque(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)49 static 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
S32A_D4444_Blend(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int,int)71 static 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
S32_D4444_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)95 static 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
106 unsigned dither = DITHER_VALUE(x);
107 *dst++ = SkDitherARGB32To4444(c, dither);
108 DITHER_INC_X(x);
109 } while (--count != 0);
110 }
111 }
112
S32_D4444_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)113 static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
114 const SkPMColor* SK_RESTRICT src,
115 int count, U8CPU alpha, int x, int y) {
116 SkASSERT(255 > alpha);
117
118 if (count > 0) {
119 int scale16 = SkAlpha255To256(alpha) >> 4;
120 DITHER_4444_SCAN(y);
121 do {
122 SkPMColor c = *src++;
123 SkPMColorAssert(c);
124 SkASSERT(SkGetPackedA32(c) == 255);
125
126 uint32_t src_expand = SkExpand32_4444(c) * scale16;
127 uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16);
128
129 c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor
130 *dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x));
131 DITHER_INC_X(x);
132 } while (--count != 0);
133 }
134 }
135
S32A_D4444_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)136 static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst,
137 const SkPMColor* SK_RESTRICT src,
138 int count, U8CPU alpha, int x, int y) {
139 SkASSERT(255 == alpha);
140
141 if (count > 0) {
142 DITHER_4444_SCAN(y);
143 do {
144 SkPMColor c = *src++;
145 SkPMColorAssert(c);
146 if (c) {
147 unsigned a = SkGetPackedA32(c);
148 int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a));
149
150 unsigned scale16 = SkAlpha255To256(255 - a) >> 4;
151 uint32_t src_expand = SkExpand_8888(c);
152 uint32_t dst_expand = SkExpand_4444(*dst) * scale16;
153 // convert back to SkPMColor
154 c = SkCompact_8888(src_expand + dst_expand);
155 *dst = SkDitherARGB32To4444(c, d);
156 }
157 dst += 1;
158 DITHER_INC_X(x);
159 } while (--count != 0);
160 }
161 }
162
163 // need DitherExpand888To4444(expand, dither)
164
S32A_D4444_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)165 static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst,
166 const SkPMColor* SK_RESTRICT src,
167 int count, U8CPU alpha, int x, int y) {
168 SkASSERT(255 > alpha);
169
170 if (count > 0) {
171 int src_scale = SkAlpha255To256(alpha) >> 4;
172 DITHER_4444_SCAN(y);
173 do {
174 SkPMColor c = *src++;
175 SkPMColorAssert(c);
176 if (c) {
177 unsigned a = SkAlpha255To256(SkGetPackedA32(c));
178 int d = SkAlphaMul(DITHER_VALUE(x), a);
179
180 unsigned dst_scale = 16 - SkAlphaMul(src_scale, a);
181 uint32_t src_expand = SkExpand32_4444(c) * src_scale;
182 uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale;
183 // convert back to SkPMColor
184 c = SkCompact_8888(src_expand + dst_expand);
185 *dst = SkDitherARGB32To4444(c, d);
186 }
187 dst += 1;
188 DITHER_INC_X(x);
189 } while (--count != 0);
190 }
191 }
192
193 ///////////////////////////////////////////////////////////////////////////////
194 ///////////////////////////////////////////////////////////////////////////////
195
196 static const SkBlitRow::Proc gProcs4444[] = {
197 // no dither
198 S32_D4444_Opaque,
199 S32_D4444_Blend,
200
201 S32A_D4444_Opaque,
202 S32A_D4444_Blend,
203
204 // dither
205 S32_D4444_Opaque_Dither,
206 S32_D4444_Blend_Dither,
207
208 S32A_D4444_Opaque_Dither,
209 S32A_D4444_Blend_Dither
210 };
211
212 SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
SkBlitRow_Factory_4444(unsigned flags)213 SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags)
214 {
215 SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444));
216
217 return gProcs4444[flags];
218 }
219