1 /*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef SkColorPriv_DEFINED
18 #define SkColorPriv_DEFINED
19
20 // turn this own for extra debug checking when blending onto 565
21 #ifdef SK_DEBUG
22 #define CHECK_FOR_565_OVERFLOW
23 #endif
24
25 #include "SkColor.h"
26 #include "SkMath.h"
27
28 /** Turn 0..255 into 0..256 by adding 1 at the half-way point. Used to turn a
29 byte into a scale value, so that we can say scale * value >> 8 instead of
30 alpha * value / 255.
31
32 In debugging, asserts that alpha is 0..255
33 */
SkAlpha255To256(U8CPU alpha)34 static inline unsigned SkAlpha255To256(U8CPU alpha) {
35 SkASSERT(SkToU8(alpha) == alpha);
36 #ifndef SK_USE_OLD_255_TO_256
37 // this one assues that blending on top of an opaque dst keeps it that way
38 // even though it is less accurate than a+(a>>7) for non-opaque dsts
39 return alpha + 1;
40 #else
41 return alpha + (alpha >> 7);
42 #endif
43 }
44
45 /** Multiplify value by 0..256, and shift the result down 8
46 (i.e. return (value * alpha256) >> 8)
47 */
48 #define SkAlphaMul(value, alpha256) (SkMulS16(value, alpha256) >> 8)
49
50 // The caller may want negative values, so keep all params signed (int)
51 // so we don't accidentally slip into unsigned math and lose the sign
52 // extension when we shift (in SkAlphaMul)
SkAlphaBlend(int src,int dst,int scale256)53 inline int SkAlphaBlend(int src, int dst, int scale256) {
54 SkASSERT((unsigned)scale256 <= 256);
55 return dst + SkAlphaMul(src - dst, scale256);
56 }
57
58 #define SK_R16_BITS 5
59 #define SK_G16_BITS 6
60 #define SK_B16_BITS 5
61
62 #define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS)
63 #define SK_G16_SHIFT (SK_B16_BITS)
64 #define SK_B16_SHIFT 0
65
66 #define SK_R16_MASK ((1 << SK_R16_BITS) - 1)
67 #define SK_G16_MASK ((1 << SK_G16_BITS) - 1)
68 #define SK_B16_MASK ((1 << SK_B16_BITS) - 1)
69
70 #define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
71 #define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
72 #define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
73
74 #define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK)
75 #define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK)
76 #define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK)
77
SkPackRGB16(unsigned r,unsigned g,unsigned b)78 static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
79 SkASSERT(r <= SK_R16_MASK);
80 SkASSERT(g <= SK_G16_MASK);
81 SkASSERT(b <= SK_B16_MASK);
82
83 return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
84 }
85
86 #define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT)
87 #define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT)
88 #define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT)
89
90 /** Expand the 16bit color into a 32bit value that can be scaled all at once
91 by a value up to 32. Used in conjunction with SkCompact_rgb_16.
92 */
SkExpand_rgb_16(U16CPU c)93 static inline uint32_t SkExpand_rgb_16(U16CPU c) {
94 SkASSERT(c == (uint16_t)c);
95
96 return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
97 }
98
99 /** Compress an expanded value (from SkExpand_rgb_16) back down to a 16bit
100 color value. The computation yields only 16bits of valid data, but we claim
101 to return 32bits, so that the compiler won't generate extra instructions to
102 "clean" the top 16bits. However, the top 16 can contain garbage, so it is
103 up to the caller to safely ignore them.
104 */
SkCompact_rgb_16(uint32_t c)105 static inline U16CPU SkCompact_rgb_16(uint32_t c) {
106 return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
107 }
108
109 /** Scale the 16bit color value by the 0..256 scale parameter.
110 The computation yields only 16bits of valid data, but we claim
111 to return 32bits, so that the compiler won't generate extra instructions to
112 "clean" the top 16bits.
113 */
SkAlphaMulRGB16(U16CPU c,unsigned scale)114 static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
115 return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
116 }
117
118 // this helper explicitly returns a clean 16bit value (but slower)
119 #define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s)
120
121 /** Blend src and dst 16bit colors by the 0..256 scale parameter.
122 The computation yields only 16bits of valid data, but we claim
123 to return 32bits, so that the compiler won't generate extra instructions to
124 "clean" the top 16bits.
125 */
SkBlendRGB16(U16CPU src,U16CPU dst,int srcScale)126 static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
127 SkASSERT((unsigned)srcScale <= 256);
128
129 srcScale >>= 3;
130
131 uint32_t src32 = SkExpand_rgb_16(src);
132 uint32_t dst32 = SkExpand_rgb_16(dst);
133 return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
134 }
135
SkBlendRGB16(const uint16_t src[],uint16_t dst[],int srcScale,int count)136 static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
137 int srcScale, int count) {
138 SkASSERT(count > 0);
139 SkASSERT((unsigned)srcScale <= 256);
140
141 srcScale >>= 3;
142
143 do {
144 uint32_t src32 = SkExpand_rgb_16(*src++);
145 uint32_t dst32 = SkExpand_rgb_16(*dst);
146 *dst++ = SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
147 } while (--count > 0);
148 }
149
150 #ifdef SK_DEBUG
SkRGB16Add(U16CPU a,U16CPU b)151 static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
152 SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
153 SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
154 SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
155
156 return a + b;
157 }
158 #else
159 #define SkRGB16Add(a, b) ((a) + (b))
160 #endif
161
162 /////////////////////////////////////////////////////////////////////////////////////////////
163
164 #define SK_A32_BITS 8
165 #define SK_R32_BITS 8
166 #define SK_G32_BITS 8
167 #define SK_B32_BITS 8
168
169 /* we check to see if the SHIFT value has already been defined (SkUserConfig.h)
170 if not, we define it ourself to some default values. We default to OpenGL
171 order (in memory: r,g,b,a)
172 */
173 #ifndef SK_A32_SHIFT
174 #ifdef SK_CPU_BENDIAN
175 #define SK_R32_SHIFT 24
176 #define SK_G32_SHIFT 16
177 #define SK_B32_SHIFT 8
178 #define SK_A32_SHIFT 0
179 #else
180 #define SK_R32_SHIFT 0
181 #define SK_G32_SHIFT 8
182 #define SK_B32_SHIFT 16
183 #define SK_A32_SHIFT 24
184 #endif
185 #endif
186
187 #define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
188 #define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
189 #define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
190 #define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
191
192 #define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
193 #define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
194 #define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
195 #define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
196
197 #define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
198 #define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
199 #define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
200 #define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
201
202 #ifdef SK_DEBUG
SkPMColorAssert(SkPMColor c)203 inline void SkPMColorAssert(SkPMColor c) {
204 unsigned a = SkGetPackedA32(c);
205 unsigned r = SkGetPackedR32(c);
206 unsigned g = SkGetPackedG32(c);
207 unsigned b = SkGetPackedB32(c);
208
209 SkA32Assert(a);
210 SkASSERT(r <= a);
211 SkASSERT(g <= a);
212 SkASSERT(b <= a);
213 }
214 #else
215 #define SkPMColorAssert(c)
216 #endif
217
SkPackARGB32(U8CPU a,U8CPU r,U8CPU g,U8CPU b)218 inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
219 SkA32Assert(a);
220 SkASSERT(r <= a);
221 SkASSERT(g <= a);
222 SkASSERT(b <= a);
223
224 return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
225 (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
226 }
227
228 extern const uint32_t gMask_00FF00FF;
229
SkAlphaMulQ(uint32_t c,unsigned scale)230 inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
231 uint32_t mask = gMask_00FF00FF;
232 // uint32_t mask = 0xFF00FF;
233
234 uint32_t rb = ((c & mask) * scale) >> 8;
235 uint32_t ag = ((c >> 8) & mask) * scale;
236 return (rb & mask) | (ag & ~mask);
237 }
238
SkPMSrcOver(SkPMColor src,SkPMColor dst)239 inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
240 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
241 }
242
SkBlendARGB32(SkPMColor src,SkPMColor dst,U8CPU aa)243 inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
244 SkASSERT((unsigned)aa <= 255);
245
246 unsigned src_scale = SkAlpha255To256(aa);
247 unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale));
248
249 return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale);
250 }
251
252 ////////////////////////////////////////////////////////////////////////////////////////////
253 // Convert a 32bit pixel to a 16bit pixel (no dither)
254
255 #define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
256 #define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
257 #define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
258
259 #ifdef SK_DEBUG
SkR32ToR16(unsigned r)260 inline unsigned SkR32ToR16(unsigned r)
261 {
262 SkR32Assert(r);
263 return SkR32ToR16_MACRO(r);
264 }
SkG32ToG16(unsigned g)265 inline unsigned SkG32ToG16(unsigned g)
266 {
267 SkG32Assert(g);
268 return SkG32ToG16_MACRO(g);
269 }
SkB32ToB16(unsigned b)270 inline unsigned SkB32ToB16(unsigned b)
271 {
272 SkB32Assert(b);
273 return SkB32ToB16_MACRO(b);
274 }
275 #else
276 #define SkR32ToR16(r) SkR32ToR16_MACRO(r)
277 #define SkG32ToG16(g) SkG32ToG16_MACRO(g)
278 #define SkB32ToB16(b) SkB32ToB16_MACRO(b)
279 #endif
280
281 #define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
282 #define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
283 #define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
284
SkPixel32ToPixel16(SkPMColor c)285 inline U16CPU SkPixel32ToPixel16(SkPMColor c)
286 {
287 unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
288 unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
289 unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
290 return r | g | b;
291 }
292
SkPack888ToRGB16(U8CPU r,U8CPU g,U8CPU b)293 inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
294 {
295 return (SkR32ToR16(r) << SK_R16_SHIFT) |
296 (SkG32ToG16(g) << SK_G16_SHIFT) |
297 (SkB32ToB16(b) << SK_B16_SHIFT);
298 }
299
300 #define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src))
301
302 /////////////////////////////////////////////////////////////////////////////////////////
303 // Fast dither from 32->16
304
305 #define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1)
306
SkDitherPack888ToRGB16(U8CPU r,U8CPU g,U8CPU b)307 inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b)
308 {
309 r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
310 g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
311 b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
312
313 return SkPackRGB16(r, g, b);
314 }
315
SkDitherPixel32ToPixel16(SkPMColor c)316 inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c)
317 {
318 return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
319 }
320
321 /* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
322 It is now suitable for combining with a scaled expanded_rgb_16 color
323 as in SkSrcOver32To16().
324 We must do this 565 high-bit replication, in order for the subsequent add
325 to saturate properly (and not overflow). If we take the 8 bits as is, it is
326 possible to overflow.
327 */
SkPMColorToExpanded16x5(SkPMColor c)328 static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c)
329 {
330 unsigned sr = SkPacked32ToR16(c);
331 unsigned sg = SkPacked32ToG16(c);
332 unsigned sb = SkPacked32ToB16(c);
333
334 sr = (sr << 5) | sr;
335 sg = (sg << 5) | (sg >> 1);
336 sb = (sb << 5) | sb;
337 return (sr << 11) | (sg << 21) | (sb << 0);
338 }
339
340 /* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
341 (with dirt in the high 16bits, so caller beware).
342 */
SkSrcOver32To16(SkPMColor src,uint16_t dst)343 static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
344 unsigned sr = SkGetPackedR32(src);
345 unsigned sg = SkGetPackedG32(src);
346 unsigned sb = SkGetPackedB32(src);
347
348 unsigned dr = SkGetPackedR16(dst);
349 unsigned dg = SkGetPackedG16(dst);
350 unsigned db = SkGetPackedB16(dst);
351
352 unsigned isa = 255 - SkGetPackedA32(src);
353
354 dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
355 dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
356 db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
357
358 return SkPackRGB16(dr, dg, db);
359 }
360
361 ////////////////////////////////////////////////////////////////////////////////////////////
362 // Convert a 16bit pixel to a 32bit pixel
363
SkR16ToR32(unsigned r)364 inline unsigned SkR16ToR32(unsigned r)
365 {
366 return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
367 }
SkG16ToG32(unsigned g)368 inline unsigned SkG16ToG32(unsigned g)
369 {
370 return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
371 }
SkB16ToB32(unsigned b)372 inline unsigned SkB16ToB32(unsigned b)
373 {
374 return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
375 }
376
377 #define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c))
378 #define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c))
379 #define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c))
380
SkPixel16ToPixel32(U16CPU src)381 inline SkPMColor SkPixel16ToPixel32(U16CPU src)
382 {
383 SkASSERT(src == SkToU16(src));
384
385 unsigned r = SkPacked16ToR32(src);
386 unsigned g = SkPacked16ToG32(src);
387 unsigned b = SkPacked16ToB32(src);
388
389 SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
390 SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
391 SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
392
393 return SkPackARGB32(0xFF, r, g, b);
394 }
395
396 // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
SkPixel16ToColor(U16CPU src)397 static inline SkColor SkPixel16ToColor(U16CPU src) {
398 SkASSERT(src == SkToU16(src));
399
400 unsigned r = SkPacked16ToR32(src);
401 unsigned g = SkPacked16ToG32(src);
402 unsigned b = SkPacked16ToB32(src);
403
404 SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
405 SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
406 SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
407
408 return SkColorSetRGB(r, g, b);
409 }
410
411 ///////////////////////////////////////////////////////////////////////////////
412
413 typedef uint16_t SkPMColor16;
414
415 // Put in OpenGL order (r g b a)
416 #define SK_A4444_SHIFT 0
417 #define SK_R4444_SHIFT 12
418 #define SK_G4444_SHIFT 8
419 #define SK_B4444_SHIFT 4
420
421 #define SkA32To4444(a) ((unsigned)(a) >> 4)
422 #define SkR32To4444(r) ((unsigned)(r) >> 4)
423 #define SkG32To4444(g) ((unsigned)(g) >> 4)
424 #define SkB32To4444(b) ((unsigned)(b) >> 4)
425
SkReplicateNibble(unsigned nib)426 static inline U8CPU SkReplicateNibble(unsigned nib)
427 {
428 SkASSERT(nib <= 0xF);
429 return (nib << 4) | nib;
430 }
431
432 #define SkA4444ToA32(a) SkReplicateNibble(a)
433 #define SkR4444ToR32(r) SkReplicateNibble(r)
434 #define SkG4444ToG32(g) SkReplicateNibble(g)
435 #define SkB4444ToB32(b) SkReplicateNibble(b)
436
437 #define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
438 #define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
439 #define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
440 #define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
441
442 #define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c))
443 #define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c))
444 #define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c))
445 #define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c))
446
447 #ifdef SK_DEBUG
SkPMColor16Assert(U16CPU c)448 static inline void SkPMColor16Assert(U16CPU c)
449 {
450 unsigned a = SkGetPackedA4444(c);
451 unsigned r = SkGetPackedR4444(c);
452 unsigned g = SkGetPackedG4444(c);
453 unsigned b = SkGetPackedB4444(c);
454
455 SkASSERT(a <= 0xF);
456 SkASSERT(r <= a);
457 SkASSERT(g <= a);
458 SkASSERT(b <= a);
459 }
460 #else
461 #define SkPMColor16Assert(c)
462 #endif
463
SkAlpha15To16(unsigned a)464 static inline unsigned SkAlpha15To16(unsigned a)
465 {
466 SkASSERT(a <= 0xF);
467 return a + (a >> 3);
468 }
469
470 #ifdef SK_DEBUG
SkAlphaMul4(int value,int scale)471 static inline int SkAlphaMul4(int value, int scale)
472 {
473 SkASSERT((unsigned)scale <= 0x10);
474 return value * scale >> 4;
475 }
476 #else
477 #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4)
478 #endif
479
SkR4444ToR565(unsigned r)480 static inline unsigned SkR4444ToR565(unsigned r)
481 {
482 SkASSERT(r <= 0xF);
483 return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
484 }
485
SkG4444ToG565(unsigned g)486 static inline unsigned SkG4444ToG565(unsigned g)
487 {
488 SkASSERT(g <= 0xF);
489 return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
490 }
491
SkB4444ToB565(unsigned b)492 static inline unsigned SkB4444ToB565(unsigned b)
493 {
494 SkASSERT(b <= 0xF);
495 return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
496 }
497
SkPackARGB4444(unsigned a,unsigned r,unsigned g,unsigned b)498 static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
499 unsigned g, unsigned b)
500 {
501 SkASSERT(a <= 0xF);
502 SkASSERT(r <= a);
503 SkASSERT(g <= a);
504 SkASSERT(b <= a);
505
506 return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
507 (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
508 }
509
510 extern const uint16_t gMask_0F0F;
511
SkAlphaMulQ4(U16CPU c,unsigned scale)512 inline U16CPU SkAlphaMulQ4(U16CPU c, unsigned scale)
513 {
514 SkASSERT(scale <= 16);
515
516 const unsigned mask = 0xF0F; //gMask_0F0F;
517
518 #if 0
519 unsigned rb = ((c & mask) * scale) >> 4;
520 unsigned ag = ((c >> 4) & mask) * scale;
521 return (rb & mask) | (ag & ~mask);
522 #else
523 c = (c & mask) | ((c & (mask << 4)) << 12);
524 c = c * scale >> 4;
525 return (c & mask) | ((c >> 12) & (mask << 4));
526 #endif
527 }
528
529 /** Expand the SkPMColor16 color into a 32bit value that can be scaled all at
530 once by a value up to 16. Used in conjunction with SkCompact_4444.
531 */
SkExpand_4444(U16CPU c)532 inline uint32_t SkExpand_4444(U16CPU c)
533 {
534 SkASSERT(c == (uint16_t)c);
535
536 const unsigned mask = 0xF0F; //gMask_0F0F;
537 return (c & mask) | ((c & ~mask) << 12);
538 }
539
540 /** Compress an expanded value (from SkExpand_4444) back down to a SkPMColor16.
541 NOTE: this explicitly does not clean the top 16 bits (which may be garbage).
542 It does this for speed, since if it is being written directly to 16bits of
543 memory, the top 16bits will be ignored. Casting the result to uint16_t here
544 would add 2 more instructions, slow us down. It is up to the caller to
545 perform the cast if needed.
546 */
SkCompact_4444(uint32_t c)547 static inline U16CPU SkCompact_4444(uint32_t c)
548 {
549 const unsigned mask = 0xF0F; //gMask_0F0F;
550 return (c & mask) | ((c >> 12) & ~mask);
551 }
552
SkSrcOver4444To16(SkPMColor16 s,uint16_t d)553 static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d)
554 {
555 unsigned sa = SkGetPackedA4444(s);
556 unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
557 unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
558 unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
559
560 // To avoid overflow, we have to clear the low bit of the synthetic sg
561 // if the src alpha is <= 7.
562 // to see why, try blending 0x4444 on top of 565-white and watch green
563 // overflow (sum == 64)
564 sg &= ~(~(sa >> 3) & 1);
565
566 unsigned scale = SkAlpha15To16(15 - sa);
567 unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
568 unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
569 unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
570
571 #if 0
572 if (sg + dg > 63) {
573 SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
574 }
575 #endif
576 return SkPackRGB16(sr + dr, sg + dg, sb + db);
577 }
578
SkBlend4444To16(SkPMColor16 src,uint16_t dst,int scale16)579 static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16)
580 {
581 SkASSERT((unsigned)scale16 <= 16);
582
583 return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
584 }
585
SkBlend4444(SkPMColor16 src,SkPMColor16 dst,int scale16)586 static inline uint16_t SkBlend4444(SkPMColor16 src, SkPMColor16 dst, int scale16)
587 {
588 SkASSERT((unsigned)scale16 <= 16);
589
590 uint32_t src32 = SkExpand_4444(src) * scale16;
591 // the scaled srcAlpha is the bottom byte
592 #ifdef SK_DEBUG
593 {
594 unsigned srcA = SkGetPackedA4444(src) * scale16;
595 SkASSERT(srcA == (src32 & 0xFF));
596 }
597 #endif
598 unsigned dstScale = SkAlpha255To256(255 - (src32 & 0xFF)) >> 4;
599 uint32_t dst32 = SkExpand_4444(dst) * dstScale;
600 return SkCompact_4444((src32 + dst32) >> 4);
601 }
602
SkPixel4444ToPixel32(U16CPU c)603 static inline SkPMColor SkPixel4444ToPixel32(U16CPU c)
604 {
605 uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
606 (SkGetPackedR4444(c) << SK_R32_SHIFT) |
607 (SkGetPackedG4444(c) << SK_G32_SHIFT) |
608 (SkGetPackedB4444(c) << SK_B32_SHIFT);
609 return d | (d << 4);
610 }
611
SkPixel32ToPixel4444(SkPMColor c)612 static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c)
613 {
614 return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
615 (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
616 (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
617 (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
618 }
619
620 // cheap 2x2 dither
SkDitherARGB32To4444(U8CPU a,U8CPU r,U8CPU g,U8CPU b)621 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
622 U8CPU g, U8CPU b)
623 {
624 a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
625 r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
626 g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
627 b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
628
629 return SkPackARGB4444(a, r, g, b);
630 }
631
SkDitherPixel32To4444(SkPMColor c)632 static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c)
633 {
634 return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
635 SkGetPackedG32(c), SkGetPackedB32(c));
636 }
637
638 /* Assumes 16bit is in standard RGBA order.
639 Transforms a normal ARGB_8888 into the same byte order as
640 expanded ARGB_4444, but keeps each component 8bits
641 */
SkExpand_8888(SkPMColor c)642 static inline uint32_t SkExpand_8888(SkPMColor c)
643 {
644 return (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
645 (((c >> SK_G32_SHIFT) & 0xFF) << 8) |
646 (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
647 (((c >> SK_A32_SHIFT) & 0xFF) << 0);
648 }
649
650 /* Undo the operation of SkExpand_8888, turning the argument back into
651 a SkPMColor.
652 */
SkCompact_8888(uint32_t c)653 static inline SkPMColor SkCompact_8888(uint32_t c)
654 {
655 return (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
656 (((c >> 8) & 0xFF) << SK_G32_SHIFT) |
657 (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
658 (((c >> 0) & 0xFF) << SK_A32_SHIFT);
659 }
660
661 /* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
662 but this routine just keeps the high 4bits of each component in the low
663 4bits of the result (just like a newly expanded PMColor16).
664 */
SkExpand32_4444(SkPMColor c)665 static inline uint32_t SkExpand32_4444(SkPMColor c)
666 {
667 return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
668 (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) |
669 (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
670 (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0);
671 }
672
673 // takes two values and alternamtes them as part of a memset16
674 // used for cheap 2x2 dithering when the colors are opaque
675 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
676
677 #endif
678
679