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 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
S32_D4444_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)114 static 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
S32A_D4444_Opaque_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)137 static 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
S32A_D4444_Blend_Dither(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,U8CPU alpha,int x,int y)166 static 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
197 static 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
213 SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags);
SkBlitRow_Factory_4444(unsigned flags)214 SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags)
215 {
216 SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444));
217
218 return gProcs4444[flags];
219 }
220
221
222