• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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