1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #ifndef GFX_COLOR_H
7 #define GFX_COLOR_H
8
9 #include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE
10 #include "mozilla/EndianUtils.h" // for mozilla::NativeEndian::swapToBigEndian
11
12 /**
13 * GFX_BLOCK_RGB_TO_FRGB(from,to)
14 * sizeof(*from) == sizeof(char)
15 * sizeof(*to) == sizeof(uint32_t)
16 *
17 * Copy 4 pixels at a time, reading blocks of 12 bytes (RGB x4)
18 * and writing blocks of 16 bytes (FRGB x4)
19 */
20 #define GFX_BLOCK_RGB_TO_FRGB(from,to) \
21 PR_BEGIN_MACRO \
22 uint32_t m0 = ((uint32_t*)from)[0], \
23 m1 = ((uint32_t*)from)[1], \
24 m2 = ((uint32_t*)from)[2], \
25 rgbr = mozilla::NativeEndian::swapToBigEndian(m0), \
26 gbrg = mozilla::NativeEndian::swapToBigEndian(m1), \
27 brgb = mozilla::NativeEndian::swapToBigEndian(m2), \
28 p0, p1, p2, p3; \
29 p0 = 0xFF000000 | ((rgbr) >> 8); \
30 p1 = 0xFF000000 | ((rgbr) << 16) | ((gbrg) >> 16); \
31 p2 = 0xFF000000 | ((gbrg) << 8) | ((brgb) >> 24); \
32 p3 = 0xFF000000 | (brgb); \
33 to[0] = p0; to[1] = p1; to[2] = p2; to[3] = p3; \
34 PR_END_MACRO
35
36 /**
37 * Fast approximate division by 255. It has the property that
38 * for all 0 <= n <= 255*255, GFX_DIVIDE_BY_255(n) == n/255.
39 * But it only uses two adds and two shifts instead of an
40 * integer division (which is expensive on many processors).
41 *
42 * equivalent to ((v)/255)
43 */
44 #define GFX_DIVIDE_BY_255(v) \
45 (((((unsigned)(v)) << 8) + ((unsigned)(v)) + 255) >> 16)
46
47 /**
48 * Fast premultiply
49 *
50 * equivalent to (((c)*(a))/255)
51 */
gfxPreMultiply(uint8_t c,uint8_t a)52 uint8_t MOZ_ALWAYS_INLINE gfxPreMultiply(uint8_t c, uint8_t a) {
53 return GFX_DIVIDE_BY_255((c)*(a));
54 }
55
56 /**
57 * Pack the 4 8-bit channels (A,R,G,B)
58 * into a 32-bit packed NON-premultiplied pixel.
59 */
60 uint32_t MOZ_ALWAYS_INLINE
gfxPackedPixelNoPreMultiply(uint8_t a,uint8_t r,uint8_t g,uint8_t b)61 gfxPackedPixelNoPreMultiply(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
62 return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b));
63 }
64
65 /**
66 * Pack the 4 8-bit channels (A,R,G,B)
67 * into a 32-bit packed premultiplied pixel.
68 */
69 uint32_t MOZ_ALWAYS_INLINE
gfxPackedPixel(uint8_t a,uint8_t r,uint8_t g,uint8_t b)70 gfxPackedPixel(uint8_t a, uint8_t r, uint8_t g, uint8_t b) {
71 if (a == 0x00)
72 return 0x00000000;
73 else if (a == 0xFF) {
74 return gfxPackedPixelNoPreMultiply(a, r, g, b);
75 } else {
76 return ((a) << 24) |
77 (gfxPreMultiply(r,a) << 16) |
78 (gfxPreMultiply(g,a) << 8) |
79 (gfxPreMultiply(b,a));
80 }
81 }
82
83 #endif /* _GFX_COLOR_H */
84