Skia
2DGraphicsLibrary
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SkColorPriv.h
1 /*
2  * Copyright 2006 The Android Open Source Project
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 #ifndef SkColorPriv_DEFINED
9 #define SkColorPriv_DEFINED
10 
11 // turn this own for extra debug checking when blending onto 565
12 #ifdef SK_DEBUG
13  #define CHECK_FOR_565_OVERFLOW
14 #endif
15 
16 #include "SkColor.h"
17 #include "SkMath.h"
18 
20 
21 #define SkASSERT_IS_BYTE(x) SkASSERT(0 == ((x) & ~0xFF))
22 
23 /*
24  * Skia's 32bit backend only supports 1 sizzle order at a time (compile-time).
25  * This is specified by 4 defines SK_A32_SHIFT, SK_R32_SHIFT, ... for G and B.
26  *
27  * For easier compatibility with Skia's GPU backend, we further restrict these
28  * to either (in memory-byte-order) RGBA or BGRA. Note that this "order" does
29  * not directly correspond to the same shift-order, since we have to take endianess
30  * into account.
31  *
32  * Here we enforce this constraint.
33  */
34 
35 #ifdef SK_CPU_BENDIAN
36  #define SK_RGBA_R32_SHIFT 24
37  #define SK_RGBA_G32_SHIFT 16
38  #define SK_RGBA_B32_SHIFT 8
39  #define SK_RGBA_A32_SHIFT 0
40 
41  #define SK_BGRA_B32_SHIFT 24
42  #define SK_BGRA_G32_SHIFT 16
43  #define SK_BGRA_R32_SHIFT 8
44  #define SK_BGRA_A32_SHIFT 0
45 #else
46  #define SK_RGBA_R32_SHIFT 0
47  #define SK_RGBA_G32_SHIFT 8
48  #define SK_RGBA_B32_SHIFT 16
49  #define SK_RGBA_A32_SHIFT 24
50 
51  #define SK_BGRA_B32_SHIFT 0
52  #define SK_BGRA_G32_SHIFT 8
53  #define SK_BGRA_R32_SHIFT 16
54  #define SK_BGRA_A32_SHIFT 24
55 #endif
56 
57 #if defined(SK_PMCOLOR_IS_RGBA) && defined(SK_PMCOLOR_IS_BGRA)
58  #error "can't define PMCOLOR to be RGBA and BGRA"
59 #endif
60 
61 #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA \
62  (SK_A32_SHIFT == SK_RGBA_A32_SHIFT && \
63  SK_R32_SHIFT == SK_RGBA_R32_SHIFT && \
64  SK_G32_SHIFT == SK_RGBA_G32_SHIFT && \
65  SK_B32_SHIFT == SK_RGBA_B32_SHIFT)
66 
67 #define LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA \
68  (SK_A32_SHIFT == SK_BGRA_A32_SHIFT && \
69  SK_R32_SHIFT == SK_BGRA_R32_SHIFT && \
70  SK_G32_SHIFT == SK_BGRA_G32_SHIFT && \
71  SK_B32_SHIFT == SK_BGRA_B32_SHIFT)
72 
73 
74 #define SK_A_INDEX (SK_A32_SHIFT/8)
75 #define SK_R_INDEX (SK_R32_SHIFT/8)
76 #define SK_G_INDEX (SK_G32_SHIFT/8)
77 #define SK_B_INDEX (SK_B32_SHIFT/8)
78 
79 #if defined(SK_PMCOLOR_IS_RGBA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
80  #error "SK_PMCOLOR_IS_RGBA does not match SK_*32_SHIFT values"
81 #endif
82 
83 #if defined(SK_PMCOLOR_IS_BGRA) && !LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
84  #error "SK_PMCOLOR_IS_BGRA does not match SK_*32_SHIFT values"
85 #endif
86 
87 #if !defined(SK_PMCOLOR_IS_RGBA) && !defined(SK_PMCOLOR_IS_BGRA)
88  // deduce which to define from the _SHIFT defines
89 
90  #if LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
91  #define SK_PMCOLOR_IS_RGBA
92  #elif LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
93  #define SK_PMCOLOR_IS_BGRA
94  #else
95  #error "need 32bit packing to be either RGBA or BGRA"
96  #endif
97 #endif
98 
99 // hide these now that we're done
100 #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_RGBA
101 #undef LOCAL_PMCOLOR_SHIFTS_EQUIVALENT_TO_BGRA
102 
104 
105 // Reverse the bytes coorsponding to RED and BLUE in a packed pixels. Note the
106 // pair of them are in the same 2 slots in both RGBA and BGRA, thus there is
107 // no need to pass in the colortype to this function.
108 static inline uint32_t SkSwizzle_RB(uint32_t c) {
109  static const uint32_t kRBMask = (0xFF << SK_R32_SHIFT) | (0xFF << SK_B32_SHIFT);
110 
111  unsigned c0 = (c >> SK_R32_SHIFT) & 0xFF;
112  unsigned c1 = (c >> SK_B32_SHIFT) & 0xFF;
113  return (c & ~kRBMask) | (c0 << SK_B32_SHIFT) | (c1 << SK_R32_SHIFT);
114 }
115 
116 static inline uint32_t SkPackARGB_as_RGBA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
117  SkASSERT_IS_BYTE(a);
118  SkASSERT_IS_BYTE(r);
119  SkASSERT_IS_BYTE(g);
120  SkASSERT_IS_BYTE(b);
121  return (a << SK_RGBA_A32_SHIFT) | (r << SK_RGBA_R32_SHIFT) |
122  (g << SK_RGBA_G32_SHIFT) | (b << SK_RGBA_B32_SHIFT);
123 }
124 
125 static inline uint32_t SkPackARGB_as_BGRA(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
126  SkASSERT_IS_BYTE(a);
127  SkASSERT_IS_BYTE(r);
128  SkASSERT_IS_BYTE(g);
129  SkASSERT_IS_BYTE(b);
130  return (a << SK_BGRA_A32_SHIFT) | (r << SK_BGRA_R32_SHIFT) |
131  (g << SK_BGRA_G32_SHIFT) | (b << SK_BGRA_B32_SHIFT);
132 }
133 
134 static inline SkPMColor SkSwizzle_RGBA_to_PMColor(uint32_t c) {
135 #ifdef SK_PMCOLOR_IS_RGBA
136  return c;
137 #else
138  return SkSwizzle_RB(c);
139 #endif
140 }
141 
142 static inline SkPMColor SkSwizzle_BGRA_to_PMColor(uint32_t c) {
143 #ifdef SK_PMCOLOR_IS_BGRA
144  return c;
145 #else
146  return SkSwizzle_RB(c);
147 #endif
148 }
149 
151 
153 
154 #define SK_ITU_BT709_LUM_COEFF_R (0.2126f)
155 #define SK_ITU_BT709_LUM_COEFF_G (0.7152f)
156 #define SK_ITU_BT709_LUM_COEFF_B (0.0722f)
157 
160 
161 #define SK_LUM_COEFF_R SK_ITU_BT709_LUM_COEFF_R
162 #define SK_LUM_COEFF_G SK_ITU_BT709_LUM_COEFF_G
163 #define SK_LUM_COEFF_B SK_ITU_BT709_LUM_COEFF_B
164 
169 static inline U8CPU SkComputeLuminance(U8CPU r, U8CPU g, U8CPU b) {
170  //The following is
171  //r * SK_LUM_COEFF_R + g * SK_LUM_COEFF_G + b * SK_LUM_COEFF_B
172  //with SK_LUM_COEFF_X in 1.8 fixed point (rounding adjusted to sum to 256).
173  return (r * 54 + g * 183 + b * 19) >> 8;
174 }
175 
182 static inline unsigned SkAlpha255To256(U8CPU alpha) {
183  SkASSERT(SkToU8(alpha) == alpha);
184  // this one assues that blending on top of an opaque dst keeps it that way
185  // even though it is less accurate than a+(a>>7) for non-opaque dsts
186  return alpha + 1;
187 }
188 
193 static inline unsigned Sk255To256(U8CPU value) {
194  SkASSERT(SkToU8(value) == value);
195  return value + (value >> 7);
196 }
197 
201 #define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8)
202 
206 static inline U16CPU SkAlphaMulInv256(U16CPU value, U16CPU alpha256) {
207  unsigned prod = 0xFFFF - value * alpha256;
208  return (prod + (prod >> 8)) >> 8;
209 }
210 
211 // The caller may want negative values, so keep all params signed (int)
212 // so we don't accidentally slip into unsigned math and lose the sign
213 // extension when we shift (in SkAlphaMul)
214 static inline int SkAlphaBlend(int src, int dst, int scale256) {
215  SkASSERT((unsigned)scale256 <= 256);
216  return dst + SkAlphaMul(src - dst, scale256);
217 }
218 
224 static inline int SkAlphaBlend255(S16CPU src, S16CPU dst, U8CPU alpha) {
225  SkASSERT((int16_t)src == src);
226  SkASSERT((int16_t)dst == dst);
227  SkASSERT((uint8_t)alpha == alpha);
228 
229  int prod = (src - dst) * alpha + 128;
230  prod = (prod + (prod >> 8)) >> 8;
231  return dst + prod;
232 }
233 
234 static inline U8CPU SkUnitScalarClampToByte(SkScalar x) {
235  return static_cast<U8CPU>(SkScalarPin(x, 0, 1) * 255 + 0.5);
236 }
237 
238 #define SK_R16_BITS 5
239 #define SK_G16_BITS 6
240 #define SK_B16_BITS 5
241 
242 #define SK_R16_SHIFT (SK_B16_BITS + SK_G16_BITS)
243 #define SK_G16_SHIFT (SK_B16_BITS)
244 #define SK_B16_SHIFT 0
245 
246 #define SK_R16_MASK ((1 << SK_R16_BITS) - 1)
247 #define SK_G16_MASK ((1 << SK_G16_BITS) - 1)
248 #define SK_B16_MASK ((1 << SK_B16_BITS) - 1)
249 
250 #define SkGetPackedR16(color) (((unsigned)(color) >> SK_R16_SHIFT) & SK_R16_MASK)
251 #define SkGetPackedG16(color) (((unsigned)(color) >> SK_G16_SHIFT) & SK_G16_MASK)
252 #define SkGetPackedB16(color) (((unsigned)(color) >> SK_B16_SHIFT) & SK_B16_MASK)
253 
254 #define SkR16Assert(r) SkASSERT((unsigned)(r) <= SK_R16_MASK)
255 #define SkG16Assert(g) SkASSERT((unsigned)(g) <= SK_G16_MASK)
256 #define SkB16Assert(b) SkASSERT((unsigned)(b) <= SK_B16_MASK)
257 
258 static inline uint16_t SkPackRGB16(unsigned r, unsigned g, unsigned b) {
259  SkASSERT(r <= SK_R16_MASK);
260  SkASSERT(g <= SK_G16_MASK);
261  SkASSERT(b <= SK_B16_MASK);
262 
263  return SkToU16((r << SK_R16_SHIFT) | (g << SK_G16_SHIFT) | (b << SK_B16_SHIFT));
264 }
265 
266 #define SK_R16_MASK_IN_PLACE (SK_R16_MASK << SK_R16_SHIFT)
267 #define SK_G16_MASK_IN_PLACE (SK_G16_MASK << SK_G16_SHIFT)
268 #define SK_B16_MASK_IN_PLACE (SK_B16_MASK << SK_B16_SHIFT)
269 
273 static inline uint32_t SkExpand_rgb_16(U16CPU c) {
274  SkASSERT(c == (uint16_t)c);
275 
276  return ((c & SK_G16_MASK_IN_PLACE) << 16) | (c & ~SK_G16_MASK_IN_PLACE);
277 }
278 
285 static inline U16CPU SkCompact_rgb_16(uint32_t c) {
286  return ((c >> 16) & SK_G16_MASK_IN_PLACE) | (c & ~SK_G16_MASK_IN_PLACE);
287 }
288 
294 static inline U16CPU SkAlphaMulRGB16(U16CPU c, unsigned scale) {
295  return SkCompact_rgb_16(SkExpand_rgb_16(c) * (scale >> 3) >> 5);
296 }
297 
298 // this helper explicitly returns a clean 16bit value (but slower)
299 #define SkAlphaMulRGB16_ToU16(c, s) (uint16_t)SkAlphaMulRGB16(c, s)
300 
306 static inline U16CPU SkBlend32_RGB16(uint32_t src_expand, uint16_t dst, unsigned scale) {
307  uint32_t dst_expand = SkExpand_rgb_16(dst) * scale;
308  return SkCompact_rgb_16((src_expand + dst_expand) >> 5);
309 }
310 
316 static inline U16CPU SkBlendRGB16(U16CPU src, U16CPU dst, int srcScale) {
317  SkASSERT((unsigned)srcScale <= 256);
318 
319  srcScale >>= 3;
320 
321  uint32_t src32 = SkExpand_rgb_16(src);
322  uint32_t dst32 = SkExpand_rgb_16(dst);
323  return SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5));
324 }
325 
326 static inline void SkBlendRGB16(const uint16_t src[], uint16_t dst[],
327  int srcScale, int count) {
328  SkASSERT(count > 0);
329  SkASSERT((unsigned)srcScale <= 256);
330 
331  srcScale >>= 3;
332 
333  do {
334  uint32_t src32 = SkExpand_rgb_16(*src++);
335  uint32_t dst32 = SkExpand_rgb_16(*dst);
336  *dst++ = static_cast<uint16_t>(
337  SkCompact_rgb_16(dst32 + ((src32 - dst32) * srcScale >> 5)));
338  } while (--count > 0);
339 }
340 
341 #ifdef SK_DEBUG
342  static inline U16CPU SkRGB16Add(U16CPU a, U16CPU b) {
343  SkASSERT(SkGetPackedR16(a) + SkGetPackedR16(b) <= SK_R16_MASK);
344  SkASSERT(SkGetPackedG16(a) + SkGetPackedG16(b) <= SK_G16_MASK);
345  SkASSERT(SkGetPackedB16(a) + SkGetPackedB16(b) <= SK_B16_MASK);
346 
347  return a + b;
348  }
349 #else
350  #define SkRGB16Add(a, b) ((a) + (b))
351 #endif
352 
354 
355 #define SK_A32_BITS 8
356 #define SK_R32_BITS 8
357 #define SK_G32_BITS 8
358 #define SK_B32_BITS 8
359 
360 #define SK_A32_MASK ((1 << SK_A32_BITS) - 1)
361 #define SK_R32_MASK ((1 << SK_R32_BITS) - 1)
362 #define SK_G32_MASK ((1 << SK_G32_BITS) - 1)
363 #define SK_B32_MASK ((1 << SK_B32_BITS) - 1)
364 
365 #define SkGetPackedA32(packed) ((uint32_t)((packed) << (24 - SK_A32_SHIFT)) >> 24)
366 #define SkGetPackedR32(packed) ((uint32_t)((packed) << (24 - SK_R32_SHIFT)) >> 24)
367 #define SkGetPackedG32(packed) ((uint32_t)((packed) << (24 - SK_G32_SHIFT)) >> 24)
368 #define SkGetPackedB32(packed) ((uint32_t)((packed) << (24 - SK_B32_SHIFT)) >> 24)
369 
370 #define SkA32Assert(a) SkASSERT((unsigned)(a) <= SK_A32_MASK)
371 #define SkR32Assert(r) SkASSERT((unsigned)(r) <= SK_R32_MASK)
372 #define SkG32Assert(g) SkASSERT((unsigned)(g) <= SK_G32_MASK)
373 #define SkB32Assert(b) SkASSERT((unsigned)(b) <= SK_B32_MASK)
374 
375 #ifdef SK_DEBUG
376  #define SkPMColorAssert(color_value) \
377  do { \
378  SkPMColor pm_color_value = (color_value); \
379  uint32_t alpha_color_value = SkGetPackedA32(pm_color_value); \
380  SkA32Assert(alpha_color_value); \
381  SkASSERT(SkGetPackedR32(pm_color_value) <= alpha_color_value); \
382  SkASSERT(SkGetPackedG32(pm_color_value) <= alpha_color_value); \
383  SkASSERT(SkGetPackedB32(pm_color_value) <= alpha_color_value); \
384  } while (false)
385 #else
386  #define SkPMColorAssert(c)
387 #endif
388 
389 static inline bool SkPMColorValid(SkPMColor c) {
390  auto a = SkGetPackedA32(c);
391  bool valid = a <= SK_A32_MASK
392  && SkGetPackedR32(c) <= a
393  && SkGetPackedG32(c) <= a
394  && SkGetPackedB32(c) <= a;
395  if (valid) {
396  SkPMColorAssert(c); // Make sure we're consistent when it counts.
397  }
398  return valid;
399 }
400 
405 static inline SkPMColor SkPackARGB32(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
406  SkA32Assert(a);
407  SkASSERT(r <= a);
408  SkASSERT(g <= a);
409  SkASSERT(b <= a);
410 
411  return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
412  (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
413 }
414 
415 static inline uint32_t SkPackPMColor_as_RGBA(SkPMColor c) {
416  return SkPackARGB_as_RGBA(SkGetPackedA32(c), SkGetPackedR32(c),
417  SkGetPackedG32(c), SkGetPackedB32(c));
418 }
419 
420 static inline uint32_t SkPackPMColor_as_BGRA(SkPMColor c) {
421  return SkPackARGB_as_BGRA(SkGetPackedA32(c), SkGetPackedR32(c),
422  SkGetPackedG32(c), SkGetPackedB32(c));
423 }
424 
432 static inline SkPMColor SkFourByteInterp256(SkPMColor src, SkPMColor dst,
433  unsigned scale) {
434  unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale);
435  unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale);
436  unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale);
437  unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale);
438 
439  return SkPackARGB32(a, r, g, b);
440 }
441 
448 static inline SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst,
449  U8CPU srcWeight) {
450  unsigned scale = SkAlpha255To256(srcWeight);
451  return SkFourByteInterp256(src, dst, scale);
452 }
453 
457 static inline void SkSplay(uint32_t color, uint32_t* ag, uint32_t* rb) {
458  const uint32_t mask = 0x00FF00FF;
459  *ag = (color >> 8) & mask;
460  *rb = color & mask;
461 }
462 
467 static inline uint64_t SkSplay(uint32_t color) {
468  const uint32_t mask = 0x00FF00FF;
469  uint64_t agrb = (color >> 8) & mask; // 0x0000000000AA00GG
470  agrb <<= 32; // 0x00AA00GG00000000
471  agrb |= color & mask; // 0x00AA00GG00RR00BB
472  return agrb;
473 }
474 
478 static inline uint32_t SkUnsplay(uint32_t ag, uint32_t rb) {
479  const uint32_t mask = 0xFF00FF00;
480  return (ag & mask) | ((rb & mask) >> 8);
481 }
482 
487 static inline uint32_t SkUnsplay(uint64_t agrb) {
488  const uint32_t mask = 0xFF00FF00;
489  return SkPMColor(
490  ((agrb & mask) >> 8) | // 0x00RR00BB
491  ((agrb >> 32) & mask)); // 0xAARRGGBB
492 }
493 
494 static inline SkPMColor SkFastFourByteInterp256_32(SkPMColor src, SkPMColor dst, unsigned scale) {
495  SkASSERT(scale <= 256);
496 
497  // Two 8-bit blends per two 32-bit registers, with space to make sure the math doesn't collide.
498  uint32_t src_ag, src_rb, dst_ag, dst_rb;
499  SkSplay(src, &src_ag, &src_rb);
500  SkSplay(dst, &dst_ag, &dst_rb);
501 
502  const uint32_t ret_ag = src_ag * scale + (256 - scale) * dst_ag;
503  const uint32_t ret_rb = src_rb * scale + (256 - scale) * dst_rb;
504 
505  return SkUnsplay(ret_ag, ret_rb);
506 }
507 
508 static inline SkPMColor SkFastFourByteInterp256_64(SkPMColor src, SkPMColor dst, unsigned scale) {
509  SkASSERT(scale <= 256);
510  // Four 8-bit blends in one 64-bit register, with space to make sure the math doesn't collide.
511  return SkUnsplay(SkSplay(src) * scale + (256-scale) * SkSplay(dst));
512 }
513 
514 // TODO(mtklein): Replace slow versions with fast versions, using scale + (scale>>7) everywhere.
515 
519 static inline SkPMColor SkFastFourByteInterp256(SkPMColor src, SkPMColor dst, unsigned scale) {
520  // On a 64-bit machine, _64 is about 10% faster than _32, but ~40% slower on a 32-bit machine.
521  if (sizeof(void*) == 4) {
522  return SkFastFourByteInterp256_32(src, dst, scale);
523  } else {
524  return SkFastFourByteInterp256_64(src, dst, scale);
525  }
526 }
527 
532 static inline SkPMColor SkFastFourByteInterp(SkPMColor src,
533  SkPMColor dst,
534  U8CPU srcWeight) {
535  SkASSERT(srcWeight <= 255);
536  // scale = srcWeight + (srcWeight >> 7) is more accurate than
537  // scale = srcWeight + 1, but 7% slower
538  return SkFastFourByteInterp256(src, dst, srcWeight + (srcWeight >> 7));
539 }
540 
545 static inline SkPMColor SkPackARGB32NoCheck(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
546  return (a << SK_A32_SHIFT) | (r << SK_R32_SHIFT) |
547  (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
548 }
549 
550 static inline
551 SkPMColor SkPremultiplyARGBInline(U8CPU a, U8CPU r, U8CPU g, U8CPU b) {
552  SkA32Assert(a);
553  SkR32Assert(r);
554  SkG32Assert(g);
555  SkB32Assert(b);
556 
557  if (a != 255) {
558  r = SkMulDiv255Round(r, a);
559  g = SkMulDiv255Round(g, a);
560  b = SkMulDiv255Round(b, a);
561  }
562  return SkPackARGB32(a, r, g, b);
563 }
564 
565 // When Android is compiled optimizing for size, SkAlphaMulQ doesn't get
566 // inlined; forcing inlining significantly improves performance.
567 static SK_ALWAYS_INLINE uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
568  uint32_t mask = 0xFF00FF;
569 
570  uint32_t rb = ((c & mask) * scale) >> 8;
571  uint32_t ag = ((c >> 8) & mask) * scale;
572  return (rb & mask) | (ag & ~mask);
573 }
574 
575 static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) {
576  return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
577 }
578 
582 static inline SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale) {
583  return SkFastFourByteInterp256(src, dst, scale);
584 }
585 
586 static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) {
587  SkASSERT((unsigned)aa <= 255);
588 
589  unsigned src_scale = SkAlpha255To256(aa);
590  unsigned dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), src_scale);
591 
592  const uint32_t mask = 0xFF00FF;
593 
594  uint32_t src_rb = (src & mask) * src_scale;
595  uint32_t src_ag = ((src >> 8) & mask) * src_scale;
596 
597  uint32_t dst_rb = (dst & mask) * dst_scale;
598  uint32_t dst_ag = ((dst >> 8) & mask) * dst_scale;
599 
600  return (((src_rb + dst_rb) >> 8) & mask) | ((src_ag + dst_ag) & ~mask);
601 }
602 
604 // Convert a 32bit pixel to a 16bit pixel (no dither)
605 
606 #define SkR32ToR16_MACRO(r) ((unsigned)(r) >> (SK_R32_BITS - SK_R16_BITS))
607 #define SkG32ToG16_MACRO(g) ((unsigned)(g) >> (SK_G32_BITS - SK_G16_BITS))
608 #define SkB32ToB16_MACRO(b) ((unsigned)(b) >> (SK_B32_BITS - SK_B16_BITS))
609 
610 #ifdef SK_DEBUG
611  static inline unsigned SkR32ToR16(unsigned r) {
612  SkR32Assert(r);
613  return SkR32ToR16_MACRO(r);
614  }
615  static inline unsigned SkG32ToG16(unsigned g) {
616  SkG32Assert(g);
617  return SkG32ToG16_MACRO(g);
618  }
619  static inline unsigned SkB32ToB16(unsigned b) {
620  SkB32Assert(b);
621  return SkB32ToB16_MACRO(b);
622  }
623 #else
624  #define SkR32ToR16(r) SkR32ToR16_MACRO(r)
625  #define SkG32ToG16(g) SkG32ToG16_MACRO(g)
626  #define SkB32ToB16(b) SkB32ToB16_MACRO(b)
627 #endif
628 
629 #define SkPacked32ToR16(c) (((unsigned)(c) >> (SK_R32_SHIFT + SK_R32_BITS - SK_R16_BITS)) & SK_R16_MASK)
630 #define SkPacked32ToG16(c) (((unsigned)(c) >> (SK_G32_SHIFT + SK_G32_BITS - SK_G16_BITS)) & SK_G16_MASK)
631 #define SkPacked32ToB16(c) (((unsigned)(c) >> (SK_B32_SHIFT + SK_B32_BITS - SK_B16_BITS)) & SK_B16_MASK)
632 
633 static inline U16CPU SkPixel32ToPixel16(SkPMColor c) {
634  unsigned r = ((c >> (SK_R32_SHIFT + (8 - SK_R16_BITS))) & SK_R16_MASK) << SK_R16_SHIFT;
635  unsigned g = ((c >> (SK_G32_SHIFT + (8 - SK_G16_BITS))) & SK_G16_MASK) << SK_G16_SHIFT;
636  unsigned b = ((c >> (SK_B32_SHIFT + (8 - SK_B16_BITS))) & SK_B16_MASK) << SK_B16_SHIFT;
637  return r | g | b;
638 }
639 
640 static inline U16CPU SkPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
641  return (SkR32ToR16(r) << SK_R16_SHIFT) |
642  (SkG32ToG16(g) << SK_G16_SHIFT) |
643  (SkB32ToB16(b) << SK_B16_SHIFT);
644 }
645 
646 #define SkPixel32ToPixel16_ToU16(src) SkToU16(SkPixel32ToPixel16(src))
647 
649 // Fast dither from 32->16
650 
651 #define SkShouldDitherXY(x, y) (((x) ^ (y)) & 1)
652 
653 static inline uint16_t SkDitherPack888ToRGB16(U8CPU r, U8CPU g, U8CPU b) {
654  r = ((r << 1) - ((r >> (8 - SK_R16_BITS) << (8 - SK_R16_BITS)) | (r >> SK_R16_BITS))) >> (8 - SK_R16_BITS);
655  g = ((g << 1) - ((g >> (8 - SK_G16_BITS) << (8 - SK_G16_BITS)) | (g >> SK_G16_BITS))) >> (8 - SK_G16_BITS);
656  b = ((b << 1) - ((b >> (8 - SK_B16_BITS) << (8 - SK_B16_BITS)) | (b >> SK_B16_BITS))) >> (8 - SK_B16_BITS);
657 
658  return SkPackRGB16(r, g, b);
659 }
660 
661 static inline uint16_t SkDitherPixel32ToPixel16(SkPMColor c) {
662  return SkDitherPack888ToRGB16(SkGetPackedR32(c), SkGetPackedG32(c), SkGetPackedB32(c));
663 }
664 
665 /* Return c in expanded_rgb_16 format, but also scaled up by 32 (5 bits)
666  It is now suitable for combining with a scaled expanded_rgb_16 color
667  as in SkSrcOver32To16().
668  We must do this 565 high-bit replication, in order for the subsequent add
669  to saturate properly (and not overflow). If we take the 8 bits as is, it is
670  possible to overflow.
671 */
672 static inline uint32_t SkPMColorToExpanded16x5(SkPMColor c) {
673  unsigned sr = SkPacked32ToR16(c);
674  unsigned sg = SkPacked32ToG16(c);
675  unsigned sb = SkPacked32ToB16(c);
676 
677  sr = (sr << 5) | sr;
678  sg = (sg << 5) | (sg >> 1);
679  sb = (sb << 5) | sb;
680  return (sr << 11) | (sg << 21) | (sb << 0);
681 }
682 
683 /* SrcOver the 32bit src color with the 16bit dst, returning a 16bit value
684  (with dirt in the high 16bits, so caller beware).
685 */
686 static inline U16CPU SkSrcOver32To16(SkPMColor src, uint16_t dst) {
687  unsigned sr = SkGetPackedR32(src);
688  unsigned sg = SkGetPackedG32(src);
689  unsigned sb = SkGetPackedB32(src);
690 
691  unsigned dr = SkGetPackedR16(dst);
692  unsigned dg = SkGetPackedG16(dst);
693  unsigned db = SkGetPackedB16(dst);
694 
695  unsigned isa = 255 - SkGetPackedA32(src);
696 
697  dr = (sr + SkMul16ShiftRound(dr, isa, SK_R16_BITS)) >> (8 - SK_R16_BITS);
698  dg = (sg + SkMul16ShiftRound(dg, isa, SK_G16_BITS)) >> (8 - SK_G16_BITS);
699  db = (sb + SkMul16ShiftRound(db, isa, SK_B16_BITS)) >> (8 - SK_B16_BITS);
700 
701  return SkPackRGB16(dr, dg, db);
702 }
703 
705 // Convert a 16bit pixel to a 32bit pixel
706 
707 static inline unsigned SkR16ToR32(unsigned r) {
708  return (r << (8 - SK_R16_BITS)) | (r >> (2 * SK_R16_BITS - 8));
709 }
710 
711 static inline unsigned SkG16ToG32(unsigned g) {
712  return (g << (8 - SK_G16_BITS)) | (g >> (2 * SK_G16_BITS - 8));
713 }
714 
715 static inline unsigned SkB16ToB32(unsigned b) {
716  return (b << (8 - SK_B16_BITS)) | (b >> (2 * SK_B16_BITS - 8));
717 }
718 
719 #define SkPacked16ToR32(c) SkR16ToR32(SkGetPackedR16(c))
720 #define SkPacked16ToG32(c) SkG16ToG32(SkGetPackedG16(c))
721 #define SkPacked16ToB32(c) SkB16ToB32(SkGetPackedB16(c))
722 
723 static inline SkPMColor SkPixel16ToPixel32(U16CPU src) {
724  SkASSERT(src == SkToU16(src));
725 
726  unsigned r = SkPacked16ToR32(src);
727  unsigned g = SkPacked16ToG32(src);
728  unsigned b = SkPacked16ToB32(src);
729 
730  SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
731  SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
732  SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
733 
734  return SkPackARGB32(0xFF, r, g, b);
735 }
736 
737 // similar to SkPixel16ToPixel32, but returns SkColor instead of SkPMColor
738 static inline SkColor SkPixel16ToColor(U16CPU src) {
739  SkASSERT(src == SkToU16(src));
740 
741  unsigned r = SkPacked16ToR32(src);
742  unsigned g = SkPacked16ToG32(src);
743  unsigned b = SkPacked16ToB32(src);
744 
745  SkASSERT((r >> (8 - SK_R16_BITS)) == SkGetPackedR16(src));
746  SkASSERT((g >> (8 - SK_G16_BITS)) == SkGetPackedG16(src));
747  SkASSERT((b >> (8 - SK_B16_BITS)) == SkGetPackedB16(src));
748 
749  return SkColorSetRGB(r, g, b);
750 }
751 
753 
754 typedef uint16_t SkPMColor16;
755 
756 // Put in OpenGL order (r g b a)
757 #define SK_A4444_SHIFT 0
758 #define SK_R4444_SHIFT 12
759 #define SK_G4444_SHIFT 8
760 #define SK_B4444_SHIFT 4
761 
762 #define SkA32To4444(a) ((unsigned)(a) >> 4)
763 #define SkR32To4444(r) ((unsigned)(r) >> 4)
764 #define SkG32To4444(g) ((unsigned)(g) >> 4)
765 #define SkB32To4444(b) ((unsigned)(b) >> 4)
766 
767 static inline U8CPU SkReplicateNibble(unsigned nib) {
768  SkASSERT(nib <= 0xF);
769  return (nib << 4) | nib;
770 }
771 
772 #define SkA4444ToA32(a) SkReplicateNibble(a)
773 #define SkR4444ToR32(r) SkReplicateNibble(r)
774 #define SkG4444ToG32(g) SkReplicateNibble(g)
775 #define SkB4444ToB32(b) SkReplicateNibble(b)
776 
777 #define SkGetPackedA4444(c) (((unsigned)(c) >> SK_A4444_SHIFT) & 0xF)
778 #define SkGetPackedR4444(c) (((unsigned)(c) >> SK_R4444_SHIFT) & 0xF)
779 #define SkGetPackedG4444(c) (((unsigned)(c) >> SK_G4444_SHIFT) & 0xF)
780 #define SkGetPackedB4444(c) (((unsigned)(c) >> SK_B4444_SHIFT) & 0xF)
781 
782 #define SkPacked4444ToA32(c) SkReplicateNibble(SkGetPackedA4444(c))
783 #define SkPacked4444ToR32(c) SkReplicateNibble(SkGetPackedR4444(c))
784 #define SkPacked4444ToG32(c) SkReplicateNibble(SkGetPackedG4444(c))
785 #define SkPacked4444ToB32(c) SkReplicateNibble(SkGetPackedB4444(c))
786 
787 #ifdef SK_DEBUG
788 static inline void SkPMColor16Assert(U16CPU c) {
789  unsigned a = SkGetPackedA4444(c);
790  unsigned r = SkGetPackedR4444(c);
791  unsigned g = SkGetPackedG4444(c);
792  unsigned b = SkGetPackedB4444(c);
793 
794  SkASSERT(a <= 0xF);
795  SkASSERT(r <= a);
796  SkASSERT(g <= a);
797  SkASSERT(b <= a);
798 }
799 #else
800 #define SkPMColor16Assert(c)
801 #endif
802 
803 static inline unsigned SkAlpha15To16(unsigned a) {
804  SkASSERT(a <= 0xF);
805  return a + (a >> 3);
806 }
807 
808 #ifdef SK_DEBUG
809  static inline int SkAlphaMul4(int value, int scale) {
810  SkASSERT((unsigned)scale <= 0x10);
811  return value * scale >> 4;
812  }
813 #else
814  #define SkAlphaMul4(value, scale) ((value) * (scale) >> 4)
815 #endif
816 
817 static inline unsigned SkR4444ToR565(unsigned r) {
818  SkASSERT(r <= 0xF);
819  return (r << (SK_R16_BITS - 4)) | (r >> (8 - SK_R16_BITS));
820 }
821 
822 static inline unsigned SkG4444ToG565(unsigned g) {
823  SkASSERT(g <= 0xF);
824  return (g << (SK_G16_BITS - 4)) | (g >> (8 - SK_G16_BITS));
825 }
826 
827 static inline unsigned SkB4444ToB565(unsigned b) {
828  SkASSERT(b <= 0xF);
829  return (b << (SK_B16_BITS - 4)) | (b >> (8 - SK_B16_BITS));
830 }
831 
832 static inline SkPMColor16 SkPackARGB4444(unsigned a, unsigned r,
833  unsigned g, unsigned b) {
834  SkASSERT(a <= 0xF);
835  SkASSERT(r <= a);
836  SkASSERT(g <= a);
837  SkASSERT(b <= a);
838 
839  return (SkPMColor16)((a << SK_A4444_SHIFT) | (r << SK_R4444_SHIFT) |
840  (g << SK_G4444_SHIFT) | (b << SK_B4444_SHIFT));
841 }
842 
843 static inline SkPMColor16 SkAlphaMulQ4(SkPMColor16 c, int scale) {
844  SkASSERT(scale <= 16);
845 
846  const unsigned mask = 0xF0F; //gMask_0F0F;
847 
848 #if 0
849  unsigned rb = ((c & mask) * scale) >> 4;
850  unsigned ag = ((c >> 4) & mask) * scale;
851  return (rb & mask) | (ag & ~mask);
852 #else
853  unsigned expanded_c = (c & mask) | ((c & (mask << 4)) << 12);
854  unsigned scaled_c = (expanded_c * scale) >> 4;
855  return (scaled_c & mask) | ((scaled_c >> 12) & (mask << 4));
856 #endif
857 }
858 
862 static inline uint32_t SkExpand_4444(U16CPU c) {
863  SkASSERT(c == (uint16_t)c);
864 
865  const unsigned mask = 0xF0F; //gMask_0F0F;
866  return (c & mask) | ((c & ~mask) << 12);
867 }
868 
869 static inline uint16_t SkSrcOver4444To16(SkPMColor16 s, uint16_t d) {
870  unsigned sa = SkGetPackedA4444(s);
871  unsigned sr = SkR4444ToR565(SkGetPackedR4444(s));
872  unsigned sg = SkG4444ToG565(SkGetPackedG4444(s));
873  unsigned sb = SkB4444ToB565(SkGetPackedB4444(s));
874 
875  // To avoid overflow, we have to clear the low bit of the synthetic sg
876  // if the src alpha is <= 7.
877  // to see why, try blending 0x4444 on top of 565-white and watch green
878  // overflow (sum == 64)
879  sg &= ~(~(sa >> 3) & 1);
880 
881  unsigned scale = SkAlpha15To16(15 - sa);
882  unsigned dr = SkAlphaMul4(SkGetPackedR16(d), scale);
883  unsigned dg = SkAlphaMul4(SkGetPackedG16(d), scale);
884  unsigned db = SkAlphaMul4(SkGetPackedB16(d), scale);
885 
886 #if 0
887  if (sg + dg > 63) {
888  SkDebugf("---- SkSrcOver4444To16 src=%x dst=%x scale=%d, sg=%d dg=%d\n", s, d, scale, sg, dg);
889  }
890 #endif
891  return SkPackRGB16(sr + dr, sg + dg, sb + db);
892 }
893 
894 static inline uint16_t SkBlend4444To16(SkPMColor16 src, uint16_t dst, int scale16) {
895  SkASSERT((unsigned)scale16 <= 16);
896 
897  return SkSrcOver4444To16(SkAlphaMulQ4(src, scale16), dst);
898 }
899 
900 static inline SkPMColor SkPixel4444ToPixel32(U16CPU c) {
901  uint32_t d = (SkGetPackedA4444(c) << SK_A32_SHIFT) |
902  (SkGetPackedR4444(c) << SK_R32_SHIFT) |
903  (SkGetPackedG4444(c) << SK_G32_SHIFT) |
904  (SkGetPackedB4444(c) << SK_B32_SHIFT);
905  return d | (d << 4);
906 }
907 
908 static inline SkPMColor16 SkPixel32ToPixel4444(SkPMColor c) {
909  return (((c >> (SK_A32_SHIFT + 4)) & 0xF) << SK_A4444_SHIFT) |
910  (((c >> (SK_R32_SHIFT + 4)) & 0xF) << SK_R4444_SHIFT) |
911  (((c >> (SK_G32_SHIFT + 4)) & 0xF) << SK_G4444_SHIFT) |
912  (((c >> (SK_B32_SHIFT + 4)) & 0xF) << SK_B4444_SHIFT);
913 }
914 
915 // cheap 2x2 dither
916 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r,
917  U8CPU g, U8CPU b) {
918  // to ensure that we stay a legal premultiplied color, we take the max()
919  // of the truncated and dithered alpha values. If we didn't, cases like
920  // SkDitherARGB32To4444(0x31, 0x2E, ...) would generate SkPackARGB4444(2, 3, ...)
921  // which is not legal premultiplied, since a < color
922  unsigned dithered_a = ((a << 1) - ((a >> 4 << 4) | (a >> 4))) >> 4;
923  a = SkMax32(a >> 4, dithered_a);
924  // these we just dither in place
925  r = ((r << 1) - ((r >> 4 << 4) | (r >> 4))) >> 4;
926  g = ((g << 1) - ((g >> 4 << 4) | (g >> 4))) >> 4;
927  b = ((b << 1) - ((b >> 4 << 4) | (b >> 4))) >> 4;
928 
929  return SkPackARGB4444(a, r, g, b);
930 }
931 
932 static inline SkPMColor16 SkDitherPixel32To4444(SkPMColor c) {
933  return SkDitherARGB32To4444(SkGetPackedA32(c), SkGetPackedR32(c),
934  SkGetPackedG32(c), SkGetPackedB32(c));
935 }
936 
937 /* Assumes 16bit is in standard RGBA order.
938  Transforms a normal ARGB_8888 into the same byte order as
939  expanded ARGB_4444, but keeps each component 8bits
940 */
941 static inline uint32_t SkExpand_8888(SkPMColor c) {
942  return (((c >> SK_R32_SHIFT) & 0xFF) << 24) |
943  (((c >> SK_G32_SHIFT) & 0xFF) << 8) |
944  (((c >> SK_B32_SHIFT) & 0xFF) << 16) |
945  (((c >> SK_A32_SHIFT) & 0xFF) << 0);
946 }
947 
948 /* Undo the operation of SkExpand_8888, turning the argument back into
949  a SkPMColor.
950 */
951 static inline SkPMColor SkCompact_8888(uint32_t c) {
952  return (((c >> 24) & 0xFF) << SK_R32_SHIFT) |
953  (((c >> 8) & 0xFF) << SK_G32_SHIFT) |
954  (((c >> 16) & 0xFF) << SK_B32_SHIFT) |
955  (((c >> 0) & 0xFF) << SK_A32_SHIFT);
956 }
957 
958 /* Like SkExpand_8888, this transforms a pmcolor into the expanded 4444 format,
959  but this routine just keeps the high 4bits of each component in the low
960  4bits of the result (just like a newly expanded PMColor16).
961 */
962 static inline uint32_t SkExpand32_4444(SkPMColor c) {
963  return (((c >> (SK_R32_SHIFT + 4)) & 0xF) << 24) |
964  (((c >> (SK_G32_SHIFT + 4)) & 0xF) << 8) |
965  (((c >> (SK_B32_SHIFT + 4)) & 0xF) << 16) |
966  (((c >> (SK_A32_SHIFT + 4)) & 0xF) << 0);
967 }
968 
969 // takes two values and alternamtes them as part of a memset16
970 // used for cheap 2x2 dithering when the colors are opaque
971 void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, int n);
972 
974 
975 static inline int SkUpscale31To32(int value) {
976  SkASSERT((unsigned)value <= 31);
977  return value + (value >> 4);
978 }
979 
980 static inline int SkBlend32(int src, int dst, int scale) {
981  SkASSERT((unsigned)src <= 0xFF);
982  SkASSERT((unsigned)dst <= 0xFF);
983  SkASSERT((unsigned)scale <= 32);
984  return dst + ((src - dst) * scale >> 5);
985 }
986 
987 static inline SkPMColor SkBlendLCD16(int srcA, int srcR, int srcG, int srcB,
988  SkPMColor dst, uint16_t mask) {
989  if (mask == 0) {
990  return dst;
991  }
992 
993  /* We want all of these in 5bits, hence the shifts in case one of them
994  * (green) is 6bits.
995  */
996  int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
997  int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
998  int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
999 
1000  // Now upscale them to 0..32, so we can use blend32
1001  maskR = SkUpscale31To32(maskR);
1002  maskG = SkUpscale31To32(maskG);
1003  maskB = SkUpscale31To32(maskB);
1004 
1005  // srcA has been upscaled to 256 before passed into this function
1006  maskR = maskR * srcA >> 8;
1007  maskG = maskG * srcA >> 8;
1008  maskB = maskB * srcA >> 8;
1009 
1010  int dstR = SkGetPackedR32(dst);
1011  int dstG = SkGetPackedG32(dst);
1012  int dstB = SkGetPackedB32(dst);
1013 
1014  // LCD blitting is only supported if the dst is known/required
1015  // to be opaque
1016  return SkPackARGB32(0xFF,
1017  SkBlend32(srcR, dstR, maskR),
1018  SkBlend32(srcG, dstG, maskG),
1019  SkBlend32(srcB, dstB, maskB));
1020 }
1021 
1022 static inline SkPMColor SkBlendLCD16Opaque(int srcR, int srcG, int srcB,
1023  SkPMColor dst, uint16_t mask,
1024  SkPMColor opaqueDst) {
1025  if (mask == 0) {
1026  return dst;
1027  }
1028 
1029  if (0xFFFF == mask) {
1030  return opaqueDst;
1031  }
1032 
1033  /* We want all of these in 5bits, hence the shifts in case one of them
1034  * (green) is 6bits.
1035  */
1036  int maskR = SkGetPackedR16(mask) >> (SK_R16_BITS - 5);
1037  int maskG = SkGetPackedG16(mask) >> (SK_G16_BITS - 5);
1038  int maskB = SkGetPackedB16(mask) >> (SK_B16_BITS - 5);
1039 
1040  // Now upscale them to 0..32, so we can use blend32
1041  maskR = SkUpscale31To32(maskR);
1042  maskG = SkUpscale31To32(maskG);
1043  maskB = SkUpscale31To32(maskB);
1044 
1045  int dstR = SkGetPackedR32(dst);
1046  int dstG = SkGetPackedG32(dst);
1047  int dstB = SkGetPackedB32(dst);
1048 
1049  // LCD blitting is only supported if the dst is known/required
1050  // to be opaque
1051  return SkPackARGB32(0xFF,
1052  SkBlend32(srcR, dstR, maskR),
1053  SkBlend32(srcG, dstG, maskG),
1054  SkBlend32(srcB, dstB, maskB));
1055 }
1056 
1057 static inline void SkBlitLCD16Row(SkPMColor dst[], const uint16_t mask[],
1058  SkColor src, int width, SkPMColor) {
1059  int srcA = SkColorGetA(src);
1060  int srcR = SkColorGetR(src);
1061  int srcG = SkColorGetG(src);
1062  int srcB = SkColorGetB(src);
1063 
1064  srcA = SkAlpha255To256(srcA);
1065 
1066  for (int i = 0; i < width; i++) {
1067  dst[i] = SkBlendLCD16(srcA, srcR, srcG, srcB, dst[i], mask[i]);
1068  }
1069 }
1070 
1071 static inline void SkBlitLCD16OpaqueRow(SkPMColor dst[], const uint16_t mask[],
1072  SkColor src, int width,
1073  SkPMColor opaqueDst) {
1074  int srcR = SkColorGetR(src);
1075  int srcG = SkColorGetG(src);
1076  int srcB = SkColorGetB(src);
1077 
1078  for (int i = 0; i < width; i++) {
1079  dst[i] = SkBlendLCD16Opaque(srcR, srcG, srcB, dst[i], mask[i],
1080  opaqueDst);
1081  }
1082 }
1083 
1084 #endif
unsigned U16CPU
Fast type for unsigned 16 bits.
Definition: SkTypes.h:203
#define SkColorGetG(color)
return the green byte from a SkColor value
Definition: SkColor.h:66
uint32_t SkPMColor
32 bit ARGB color value, premultiplied.
Definition: SkColor.h:161
uint32_t SkColor
32 bit ARGB color value, not premultiplied.
Definition: SkColor.h:28
#define SkColorGetB(color)
return the blue byte from a SkColor value
Definition: SkColor.h:68
#define SkColorGetR(color)
return the red byte from a SkColor value
Definition: SkColor.h:64
#define SkColorSetRGB(r, g, b)
Return a SkColor value from 8 bit component values, with an implied value of 0xFF for alpha (fully op...
Definition: SkColor.h:59
#define SkColorGetA(color)
return the alpha byte from a SkColor value
Definition: SkColor.h:62
unsigned U8CPU
Fast type for unsigned 8 bits.
Definition: SkTypes.h:191
Types and macros for colors.
int S16CPU
Fast type for signed 16 bits.
Definition: SkTypes.h:197