Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / gfx / thebes / public / gfxColor.h
blobd7241b66f26cc769a32e2867f7be4a577551a8b9
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, FAST_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))
153 * A color value, storing red, green, blue and alpha components.
154 * This class does not use premultiplied alpha.
156 * XXX should this use doubles (instead of gfxFloat), for consistency with
157 * cairo?
159 struct THEBES_API gfxRGBA {
160 gfxFloat r, g, b, a;
162 enum PackedColorType {
163 PACKED_ABGR,
164 PACKED_ABGR_PREMULTIPLIED,
166 PACKED_ARGB,
167 PACKED_ARGB_PREMULTIPLIED,
169 PACKED_XBGR,
170 PACKED_XRGB
173 gfxRGBA() { }
174 gfxRGBA(const gfxRGBA& c) : r(c.r), g(c.g), b(c.b), a(c.a) {}
176 * Intialize this color using explicit red, green, blue and alpha
177 * values.
179 gfxRGBA(gfxFloat _r, gfxFloat _g, gfxFloat _b, gfxFloat _a=1.0) : r(_r), g(_g), b(_b), a(_a) {}
182 * Initialize this color from a packed 32-bit color.
183 * The color value is interpreted based on colorType;
184 * all values use the native platform endianness.
186 * @see gfxRGBA::Packed
188 gfxRGBA(PRUint32 c, PackedColorType colorType = PACKED_ABGR) {
189 if (colorType == PACKED_ABGR ||
190 colorType == PACKED_XBGR ||
191 colorType == PACKED_ABGR_PREMULTIPLIED)
193 r = ((c >> 0) & 0xff) / 255.0;
194 g = ((c >> 8) & 0xff) / 255.0;
195 b = ((c >> 16) & 0xff) / 255.0;
196 a = ((c >> 24) & 0xff) / 255.0;
197 } else if (colorType == PACKED_ARGB ||
198 colorType == PACKED_XRGB ||
199 colorType == PACKED_ARGB_PREMULTIPLIED)
201 b = ((c >> 0) & 0xff) / 255.0;
202 g = ((c >> 8) & 0xff) / 255.0;
203 r = ((c >> 16) & 0xff) / 255.0;
204 a = ((c >> 24) & 0xff) / 255.0;
207 if (colorType == PACKED_ABGR_PREMULTIPLIED ||
208 colorType == PACKED_ARGB_PREMULTIPLIED)
210 if (a > 0.0) {
211 r /= a;
212 g /= a;
213 b /= a;
215 } else if (colorType == PACKED_XBGR ||
216 colorType == PACKED_XRGB)
218 a = 1.0;
223 * Initialize this color by parsing the given string.
224 * XXX implement me!
226 #if 0
227 gfxRGBA(const char* str) {
228 a = 1.0;
229 // if aString[0] is a #, parse it as hex
230 // if aString[0] is a letter, parse it as a color name
231 // if aString[0] is a number, parse it loosely as hex
233 #endif
236 * Returns this color value as a packed 32-bit integer. This reconstructs
237 * the int32 based on the given colorType, always in the native byte order.
239 * Note: gcc 4.2.3 on at least Ubuntu (x86) does something strange with
240 * (PRUint8)(c * 255.0) << x, where the result is different than
241 * double d = c * 255.0; v = ((PRUint8) d) << x.
243 PRUint32 Packed(PackedColorType colorType = PACKED_ABGR) const {
244 gfxFloat rb = (r * 255.0);
245 gfxFloat gb = (g * 255.0);
246 gfxFloat bb = (b * 255.0);
247 gfxFloat ab = (a * 255.0);
249 if (colorType == PACKED_ABGR || colorType == PACKED_XBGR) {
250 return (PRUint8(ab) << 24) |
251 (PRUint8(bb) << 16) |
252 (PRUint8(gb) << 8) |
253 (PRUint8(rb) << 0);
254 } else if (colorType == PACKED_ARGB || colorType == PACKED_XRGB) {
255 return (PRUint8(ab) << 24) |
256 (PRUint8(rb) << 16) |
257 (PRUint8(gb) << 8) |
258 (PRUint8(bb) << 0);
261 rb = (r*a) * 255.0;
262 gb = (g*a) * 255.0;
263 bb = (b*a) * 255.0;
265 if (colorType == PACKED_ABGR_PREMULTIPLIED) {
266 return (((PRUint8)(ab) << 24) |
267 ((PRUint8)(bb) << 16) |
268 ((PRUint8)(gb) << 8) |
269 ((PRUint8)(rb) << 0));
270 } else if (colorType == PACKED_ARGB_PREMULTIPLIED) {
271 return (((PRUint8)(ab) << 24) |
272 ((PRUint8)(rb) << 16) |
273 ((PRUint8)(gb) << 8) |
274 ((PRUint8)(bb) << 0));
277 return 0;
280 #ifdef MOZILLA_INTERNAL_API
282 * Convert this color to a hex value. For example, for rgb(255,0,0),
283 * this will return FF0000.
285 // XXX I'd really prefer to just have this return an nsACString
286 // Does this function even make sense, since we're just ignoring the alpha value?
287 void Hex(nsACString& result) const {
288 nsPrintfCString hex(8, "%02x%02x%02x", PRUint8(r*255.0), PRUint8(g*255.0), PRUint8(b*255.0));
289 result.Assign(hex);
291 #endif
295 #endif /* _GFX_COLOR_H */