1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
33 * @Short_description: RGBA colors
37 G_DEFINE_BOXED_TYPE (GdkRGBA, gdk_rgba,
38 gdk_rgba_copy, gdk_rgba_free)
44 * Makes a copy of a #GdkRGBA structure, the result must be freed
45 * through gdk_rgba_free().
47 * Returns: A newly allocated #GdkRGBA
52 gdk_rgba_copy (GdkRGBA *rgba)
56 copy = g_slice_new (GdkRGBA);
57 copy->red = rgba->red;
58 copy->green = rgba->green;
59 copy->blue = rgba->blue;
60 copy->alpha = rgba->alpha;
69 * Frees a #GdkRGBA struct created with gdk_rgba_copy()
74 gdk_rgba_free (GdkRGBA *rgba)
76 g_slice_free (GdkRGBA, rgba);
79 #define SKIP_WHITESPACES(s) while (*(s) == ' ') (s)++;
81 /* Parses a single color component from a rgb() or rgba() specification
82 * according to CSS3 rules. Compared to exact CSS3 parsing we are liberal
83 * in what we accept as follows:
85 * - For non-percentage values, we accept floats in the range 0-255
86 * not just [0-9]+ integers
87 * - For percentage values we accept any float, not just
88 * [ 0-9]+ | [0-9]* '.' [0-9]+
89 * - We accept mixed percentages and non-percentages in a single
90 * rgb() or rgba() specification.
93 parse_rgb_value (const char *str,
99 number = g_ascii_strtod (str, endp);
103 SKIP_WHITESPACES (p);
107 *endp = (char *)(p + 1);
108 return CLAMP(number / 100., 0., 1.);
112 return CLAMP(number / 255., 0., 1.);
118 * @rgba: the #GdkRGBA struct to fill in
119 * @spec: the string specifying the color
121 * Parses a textual representation of a color, filling in
122 * the <structfield>red</structfield>, <structfield>green</structfield>,
123 * <structfield>blue</structfield> and <structfield>alpha</structfield>
124 * fields of the @rgba struct.
126 * The string can be either one of:
129 * A standard name (Taken from the X11 rgb.txt file).
132 * A hex value in the form '#rgb' '#rrggbb' '#rrrgggbbb' or '#rrrrggggbbbb'
135 * A RGB color in the form 'rgb(r,g,b)' (In this case the color will
139 * A RGBA color in the form 'rgba(r,g,b,a)'
143 * Where 'r', 'g', 'b' and 'a' are respectively the red, green, blue and
144 * alpha color values. In the last two cases, r g and b are either integers
145 * in the range 0 to 255 or precentage values in the range 0% to 100%, and
146 * a is a floating point value in the range 0 to 1.
148 * Returns: %TRUE if the parsing succeeded
153 gdk_rgba_parse (GdkRGBA *rgba,
158 gchar *str = (gchar *) spec;
160 if (strncmp (str, "rgba", 4) == 0)
165 else if (strncmp (str, "rgb", 3) == 0)
173 PangoColor pango_color;
175 /* Resort on PangoColor for rgb.txt color
176 * map and '#' prefixed colors */
177 if (pango_color_parse (&pango_color, str))
181 rgba->red = pango_color.red / 65535.;
182 rgba->green = pango_color.green / 65535.;
183 rgba->blue = pango_color.blue / 65535.;
193 SKIP_WHITESPACES (str);
201 SKIP_WHITESPACES (str);
202 r = parse_rgb_value (str, &str);
203 SKIP_WHITESPACES (str);
211 SKIP_WHITESPACES (str);
212 g = parse_rgb_value (str, &str);
213 SKIP_WHITESPACES (str);
221 SKIP_WHITESPACES (str);
222 b = parse_rgb_value (str, &str);
223 SKIP_WHITESPACES (str);
232 SKIP_WHITESPACES (str);
233 a = g_ascii_strtod (str, &str);
234 SKIP_WHITESPACES (str);
242 rgba->red = CLAMP (r, 0, 1);
243 rgba->green = CLAMP (g, 0, 1);
244 rgba->blue = CLAMP (b, 0, 1);
245 rgba->alpha = CLAMP (a, 0, 1);
251 #undef SKIP_WHITESPACES
255 * @p: a #GdkRGBA pointer.
257 * A hash function suitable for using for a hash
258 * table that stores #GdkRGBA<!-- -->s.
260 * Return value: The hash function applied to @p
265 gdk_rgba_hash (gconstpointer p)
267 const GdkRGBA *rgba = p;
269 return ((guint) (rgba->red * 65535) +
270 ((guint) (rgba->green * 65535) << 11) +
271 ((guint) (rgba->blue * 65535) << 22) +
272 ((guint) (rgba->alpha * 65535) >> 6));
277 * @p1: a #GdkRGBA pointer.
278 * @p2: another #GdkRGBA pointer.
280 * Compares two RGBA colors.
282 * Return value: %TRUE if the two colors compare equal
287 gdk_rgba_equal (gconstpointer p1,
290 const GdkRGBA *rgba1, *rgba2;
295 if (rgba1->red == rgba2->red &&
296 rgba1->green == rgba2->green &&
297 rgba1->blue == rgba2->blue &&
298 rgba1->alpha == rgba2->alpha)
305 * gdk_rgba_to_string:
308 * Returns a textual specification of @rgba in the form <literal>rgb
309 * (r, g, b)</literal> or <literal>rgba (r, g, b, a)</literal>,
310 * where 'r', 'g', 'b' and 'a' represent the red, green, blue and alpha values
311 * respectively. r, g, and b are integers in the range 0 to 255, and a
312 * is a floating point value in the range 0 to 1.
314 * (These string forms are string forms those supported by the CSS3 colors module)
316 * Returns: A newly allocated text string
321 gdk_rgba_to_string (const GdkRGBA *rgba)
323 if (rgba->alpha > 0.999)
325 return g_strdup_printf ("rgb(%d,%d,%d)",
326 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
327 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
328 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.));
332 gchar alpha[G_ASCII_DTOSTR_BUF_SIZE];
334 g_ascii_dtostr (alpha, G_ASCII_DTOSTR_BUF_SIZE, CLAMP (rgba->alpha, 0, 1));
336 return g_strdup_printf ("rgba(%d,%d,%d,%s)",
337 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
338 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
339 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.),