Backed out changeset b88172246b66 due to Win32 debug failures.
[mozilla-central.git] / gfx / thebes / gfxColor.h
blob6dbe76fe469e4effcd4c67f2943d727c5ae79c5b
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Oracle Corporation code.
17 * The Initial Developer of the Original Code is Oracle Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2005
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Stuart Parmenter <pavlov@pavlov.net>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #ifndef GFX_COLOR_H
39 #define GFX_COLOR_H
41 #ifdef MOZILLA_INTERNAL_API
42 #include "nsPrintfCString.h"
43 #endif
45 #include "gfxTypes.h"
47 #include "prbit.h" // for PR_ROTATE_(LEFT,RIGHT)32
48 #include "prio.h" // for ntohl
50 #define GFX_UINT32_FROM_BPTR(pbptr,i) (((PRUint32*)(pbptr))[i])
52 #if defined(IS_BIG_ENDIAN)
53 #define GFX_NTOHL(x) (x)
54 #define GFX_HAVE_CHEAP_NTOHL
55 #elif defined(_WIN32)
56 #if (_MSC_VER >= 1300) // also excludes MinGW
57 #include <stdlib.h>
58 #pragma intrinsic(_byteswap_ulong)
59 #define GFX_NTOHL(x) _byteswap_ulong(x)
60 #define GFX_HAVE_CHEAP_NTOHL
61 #else
62 // A reasonably fast generic little-endian implementation.
63 #define GFX_NTOHL(x) \
64 ( (PR_ROTATE_RIGHT32((x),8) & 0xFF00FF00) | \
65 (PR_ROTATE_LEFT32((x),8) & 0x00FF00FF) )
66 #endif
67 #else
68 #define GFX_NTOHL(x) ntohl(x)
69 #define GFX_HAVE_CHEAP_NTOHL
70 #endif
72 /**
73 * GFX_0XFF_PPIXEL_FROM_BPTR(x)
75 * Avoid tortured construction of 32-bit ARGB pixel from 3 individual bytes
76 * of memory plus constant 0xFF. RGB bytes are already contiguous!
77 * Equivalent to: GFX_PACKED_PIXEL(0xff,r,g,b)
79 * Attempt to use fast byte-swapping instruction(s), e.g. bswap on x86, in
80 * preference to a sequence of shift/or operations.
82 #if defined(GFX_HAVE_CHEAP_NTOHL)
83 #define GFX_0XFF_PPIXEL_FROM_UINT32(x) \
84 ( (GFX_NTOHL(x) >> 8) | (0xFF << 24) )
85 #else
86 // A reasonably fast generic little-endian implementation.
87 #define GFX_0XFF_PPIXEL_FROM_UINT32(x) \
88 ( (PR_ROTATE_LEFT32((x),16) | 0xFF00FF00) & ((x) | 0xFFFF00FF) )
89 #endif
91 #define GFX_0XFF_PPIXEL_FROM_BPTR(x) \
92 ( GFX_0XFF_PPIXEL_FROM_UINT32(GFX_UINT32_FROM_BPTR((x),0)) )
94 /**
95 * GFX_BLOCK_RGB_TO_FRGB(from,to)
96 * sizeof(*from) == sizeof(char)
97 * sizeof(*to) == sizeof(PRUint32)
99 * Copy 4 pixels at a time, reading blocks of 12 bytes (RGB x4)
100 * and writing blocks of 16 bytes (FRGB x4)
102 #define GFX_BLOCK_RGB_TO_FRGB(from,to) \
103 PR_BEGIN_MACRO \
104 PRUint32 m0 = GFX_UINT32_FROM_BPTR(from,0), \
105 m1 = GFX_UINT32_FROM_BPTR(from,1), \
106 m2 = GFX_UINT32_FROM_BPTR(from,2), \
107 rgbr = GFX_NTOHL(m0), \
108 gbrg = GFX_NTOHL(m1), \
109 brgb = GFX_NTOHL(m2), \
110 p0, p1, p2, p3; \
111 p0 = 0xFF000000 | ((rgbr) >> 8); \
112 p1 = 0xFF000000 | ((rgbr) << 16) | ((gbrg) >> 16); \
113 p2 = 0xFF000000 | ((gbrg) << 8) | ((brgb) >> 24); \
114 p3 = 0xFF000000 | (brgb); \
115 to[0] = p0; to[1] = p1; to[2] = p2; to[3] = p3; \
116 PR_END_MACRO
119 * Fast approximate division by 255. It has the property that
120 * for all 0 <= n <= 255*255, GFX_DIVIDE_BY_255(n) == n/255.
121 * But it only uses two adds and two shifts instead of an
122 * integer division (which is expensive on many processors).
124 * equivalent to ((v)/255)
126 #define GFX_DIVIDE_BY_255(v) \
127 (((((unsigned)(v)) << 8) + ((unsigned)(v)) + 255) >> 16)
130 * Fast premultiply macro
132 * equivalent to (((c)*(a))/255)
134 #define GFX_PREMULTIPLY(c,a) GFX_DIVIDE_BY_255((c)*(a))
136 /**
137 * Macro to pack the 4 8-bit channels (A,R,G,B)
138 * into a 32-bit packed premultiplied pixel.
140 * The checks for 0 alpha or max alpha ensure that the
141 * compiler selects the quicked calculation when alpha is constant.
143 #define GFX_PACKED_PIXEL(a,r,g,b) \
144 ((a) == 0x00) ? 0x00000000 : \
145 ((a) == 0xFF) ? ((0xFF << 24) | ((r) << 16) | ((g) << 8) | (b)) \
146 : ((a) << 24) | \
147 (GFX_PREMULTIPLY(r,a) << 16) | \
148 (GFX_PREMULTIPLY(g,a) << 8) | \
149 (GFX_PREMULTIPLY(b,a))
151 /**
152 * Macro to pack the 4 8-bit channels (A,R,G,B)
153 * into a 32-bit packed NON-premultiplied pixel.
155 #define GFX_PACKED_PIXEL_NO_PREMULTIPLY(a,r,g,b) \
156 (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
160 * A color value, storing red, green, blue and alpha components.
161 * This class does not use premultiplied alpha.
163 * XXX should this use doubles (instead of gfxFloat), for consistency with
164 * cairo?
166 struct THEBES_API gfxRGBA {
167 gfxFloat r, g, b, a;
169 enum PackedColorType {
170 PACKED_ABGR,
171 PACKED_ABGR_PREMULTIPLIED,
173 PACKED_ARGB,
174 PACKED_ARGB_PREMULTIPLIED,
176 PACKED_XBGR,
177 PACKED_XRGB
180 gfxRGBA() { }
181 gfxRGBA(const gfxRGBA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {}
183 * Intialize this color using explicit red, green, blue and alpha
184 * values.
186 gfxRGBA(gfxFloat _r, gfxFloat _g, gfxFloat _b, gfxFloat _a=1.0) : r(_r), g(_g), b(_b), a(_a) {}
189 * Initialize this color from a packed 32-bit color.
190 * The color value is interpreted based on colorType;
191 * all values use the native platform endianness.
193 * @see gfxRGBA::Packed
195 gfxRGBA(PRUint32 c, PackedColorType colorType = PACKED_ABGR) {
196 if (colorType == PACKED_ABGR ||
197 colorType == PACKED_XBGR ||
198 colorType == PACKED_ABGR_PREMULTIPLIED)
200 r = ((c >> 0) & 0xff) * (1.0 / 255.0);
201 g = ((c >> 8) & 0xff) * (1.0 / 255.0);
202 b = ((c >> 16) & 0xff) * (1.0 / 255.0);
203 a = ((c >> 24) & 0xff) * (1.0 / 255.0);
204 } else if (colorType == PACKED_ARGB ||
205 colorType == PACKED_XRGB ||
206 colorType == PACKED_ARGB_PREMULTIPLIED)
208 b = ((c >> 0) & 0xff) * (1.0 / 255.0);
209 g = ((c >> 8) & 0xff) * (1.0 / 255.0);
210 r = ((c >> 16) & 0xff) * (1.0 / 255.0);
211 a = ((c >> 24) & 0xff) * (1.0 / 255.0);
214 if (colorType == PACKED_ABGR_PREMULTIPLIED ||
215 colorType == PACKED_ARGB_PREMULTIPLIED)
217 if (a > 0.0) {
218 r /= a;
219 g /= a;
220 b /= a;
222 } else if (colorType == PACKED_XBGR ||
223 colorType == PACKED_XRGB)
225 a = 1.0;
230 * Initialize this color by parsing the given string.
231 * XXX implement me!
233 #if 0
234 gfxRGBA(const char* str) {
235 a = 1.0;
236 // if aString[0] is a #, parse it as hex
237 // if aString[0] is a letter, parse it as a color name
238 // if aString[0] is a number, parse it loosely as hex
240 #endif
242 bool operator==(const gfxRGBA& other) const
244 return r == other.r && g == other.g && b == other.b && a == other.a;
248 * Returns this color value as a packed 32-bit integer. This reconstructs
249 * the int32 based on the given colorType, always in the native byte order.
251 * Note: gcc 4.2.3 on at least Ubuntu (x86) does something strange with
252 * (PRUint8)(c * 255.0) << x, where the result is different than
253 * double d = c * 255.0; v = ((PRUint8) d) << x.
255 PRUint32 Packed(PackedColorType colorType = PACKED_ABGR) const {
256 gfxFloat rb = (r * 255.0);
257 gfxFloat gb = (g * 255.0);
258 gfxFloat bb = (b * 255.0);
259 gfxFloat ab = (a * 255.0);
261 if (colorType == PACKED_ABGR || colorType == PACKED_XBGR) {
262 return (PRUint8(ab) << 24) |
263 (PRUint8(bb) << 16) |
264 (PRUint8(gb) << 8) |
265 (PRUint8(rb) << 0);
266 } else if (colorType == PACKED_ARGB || colorType == PACKED_XRGB) {
267 return (PRUint8(ab) << 24) |
268 (PRUint8(rb) << 16) |
269 (PRUint8(gb) << 8) |
270 (PRUint8(bb) << 0);
273 rb = (r*a) * 255.0;
274 gb = (g*a) * 255.0;
275 bb = (b*a) * 255.0;
277 if (colorType == PACKED_ABGR_PREMULTIPLIED) {
278 return (((PRUint8)(ab) << 24) |
279 ((PRUint8)(bb) << 16) |
280 ((PRUint8)(gb) << 8) |
281 ((PRUint8)(rb) << 0));
282 } else if (colorType == PACKED_ARGB_PREMULTIPLIED) {
283 return (((PRUint8)(ab) << 24) |
284 ((PRUint8)(rb) << 16) |
285 ((PRUint8)(gb) << 8) |
286 ((PRUint8)(bb) << 0));
289 return 0;
292 #ifdef MOZILLA_INTERNAL_API
294 * Convert this color to a hex value. For example, for rgb(255,0,0),
295 * this will return FF0000.
297 // XXX I'd really prefer to just have this return an nsACString
298 // Does this function even make sense, since we're just ignoring the alpha value?
299 void Hex(nsACString& result) const {
300 nsPrintfCString hex(8, "%02x%02x%02x", PRUint8(r*255.0), PRUint8(g*255.0), PRUint8(b*255.0));
301 result.Assign(hex);
303 #endif
307 #endif /* _GFX_COLOR_H */