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, see <http://www.gnu.org/licenses/>.
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * files for a list of changes. These files are distributed with
22 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
31 #include "fallback-c89.c"
35 * @Short_description: RGBA colors
38 * The #GdkRGBA struct is a convenient way to pass rgba colors around.
39 * It's based on cairo's way to deal with colors and mirrors its behavior.
40 * All values are in the range from 0.0 to 1.0 inclusive. So the color
41 * (0.0, 0.0, 0.0, 0.0) represents transparent black and
42 * (1.0, 1.0, 1.0, 1.0) is opaque white. Other values will be clamped
43 * to this range when drawing.
46 G_DEFINE_BOXED_TYPE (GdkRGBA, gdk_rgba,
47 gdk_rgba_copy, gdk_rgba_free)
51 * @red: The intensity of the red channel from 0.0 to 1.0 inclusive
52 * @green: The intensity of the green channel from 0.0 to 1.0 inclusive
53 * @blue: The intensity of the blue channel from 0.0 to 1.0 inclusive
54 * @alpha: The opacity of the color from 0.0 for completely translucent to
57 * The GdkRGBA structure is used to represent a (possibly translucent)
58 * color, in a way that is compatible with cairos notion of color.
65 * Makes a copy of a #GdkRGBA structure.
67 * The result must be freed through gdk_rgba_free().
69 * Returns: A newly allocated #GdkRGBA, with the same contents as @rgba
74 gdk_rgba_copy (const GdkRGBA *rgba)
76 return g_slice_dup (GdkRGBA, rgba);
83 * Frees a #GdkRGBA struct created with gdk_rgba_copy()
88 gdk_rgba_free (GdkRGBA *rgba)
90 g_slice_free (GdkRGBA, rgba);
93 #define SKIP_WHITESPACES(s) while (*(s) == ' ') (s)++;
95 /* Parses a single color component from a rgb() or rgba() specification
96 * according to CSS3 rules. Compared to exact CSS3 parsing we are liberal
97 * in what we accept as follows:
99 * - For non-percentage values, we accept floats in the range 0-255
100 * not just [0-9]+ integers
101 * - For percentage values we accept any float, not just
102 * [ 0-9]+ | [0-9]* '.' [0-9]+
103 * - We accept mixed percentages and non-percentages in a single
104 * rgb() or rgba() specification.
107 parse_rgb_value (const gchar *str,
113 *number = g_ascii_strtod (str, endp);
114 if (errno == ERANGE || *endp == str ||
115 isinf (*number) || isnan (*number))
120 SKIP_WHITESPACES (p);
124 *endp = (char *)(p + 1);
125 *number = CLAMP(*number / 100., 0., 1.);
129 *number = CLAMP(*number / 255., 0., 1.);
137 * @rgba: the #GdkRGBA struct to fill in
138 * @spec: the string specifying the color
140 * Parses a textual representation of a color, filling in
141 * the <structfield>red</structfield>, <structfield>green</structfield>,
142 * <structfield>blue</structfield> and <structfield>alpha</structfield>
143 * fields of the @rgba struct.
145 * The string can be either one of:
148 * A standard name (Taken from the X11 rgb.txt file).
151 * A hex value in the form '#rgb' '#rrggbb' '#rrrgggbbb'
152 * or '#rrrrggggbbbb'
155 * A RGB color in the form 'rgb(r,g,b)' (In this case the color will
159 * A RGBA color in the form 'rgba(r,g,b,a)'
163 * Where 'r', 'g', 'b' and 'a' are respectively the red, green, blue and
164 * alpha color values. In the last two cases, r g and b are either integers
165 * in the range 0 to 255 or precentage values in the range 0% to 100%, and
166 * a is a floating point value in the range 0 to 1.
168 * Returns: %TRUE if the parsing succeeded
173 gdk_rgba_parse (GdkRGBA *rgba,
178 gchar *str = (gchar *) spec;
181 if (strncmp (str, "rgba", 4) == 0)
186 else if (strncmp (str, "rgb", 3) == 0)
194 PangoColor pango_color;
196 /* Resort on PangoColor for rgb.txt color
197 * map and '#' prefixed colors
199 if (pango_color_parse (&pango_color, str))
203 rgba->red = pango_color.red / 65535.;
204 rgba->green = pango_color.green / 65535.;
205 rgba->blue = pango_color.blue / 65535.;
215 SKIP_WHITESPACES (str);
223 SKIP_WHITESPACES (str);
224 if (!parse_rgb_value (str, &str, &r))
226 SKIP_WHITESPACES (str);
234 SKIP_WHITESPACES (str);
235 if (!parse_rgb_value (str, &str, &g))
237 SKIP_WHITESPACES (str);
245 SKIP_WHITESPACES (str);
246 if (!parse_rgb_value (str, &str, &b))
248 SKIP_WHITESPACES (str);
257 SKIP_WHITESPACES (str);
258 a = g_ascii_strtod (str, &p);
259 if (errno == ERANGE || p == str ||
260 isinf (a) || isnan (a))
263 SKIP_WHITESPACES (str);
271 SKIP_WHITESPACES (str);
278 rgba->red = CLAMP (r, 0, 1);
279 rgba->green = CLAMP (g, 0, 1);
280 rgba->blue = CLAMP (b, 0, 1);
281 rgba->alpha = CLAMP (a, 0, 1);
287 #undef SKIP_WHITESPACES
291 * @p: (type GdkRGBA): a #GdkRGBA pointer
293 * A hash function suitable for using for a hash
294 * table that stores #GdkRGBAs.
296 * Return value: The hash value for @p
301 gdk_rgba_hash (gconstpointer p)
303 const GdkRGBA *rgba = p;
305 return ((guint) (rgba->red * 65535) +
306 ((guint) (rgba->green * 65535) << 11) +
307 ((guint) (rgba->blue * 65535) << 22) +
308 ((guint) (rgba->alpha * 65535) >> 6));
313 * @p1: (type GdkRGBA): a #GdkRGBA pointer
314 * @p2: (type GdkRGBA): another #GdkRGBA pointer
316 * Compares two RGBA colors.
318 * Return value: %TRUE if the two colors compare equal
323 gdk_rgba_equal (gconstpointer p1,
326 const GdkRGBA *rgba1, *rgba2;
331 if (rgba1->red == rgba2->red &&
332 rgba1->green == rgba2->green &&
333 rgba1->blue == rgba2->blue &&
334 rgba1->alpha == rgba2->alpha)
341 * gdk_rgba_to_string:
344 * Returns a textual specification of @rgba in the form
345 * <literal>rgb (r, g, b)</literal> or
346 * <literal>rgba (r, g, b, a)</literal>,
347 * where 'r', 'g', 'b' and 'a' represent the red, green,
348 * blue and alpha values respectively. r, g, and b are
349 * represented as integers in the range 0 to 255, and a
350 * is represented as floating point value in the range 0 to 1.
352 * These string forms are string forms those supported by
353 * the CSS3 colors module, and can be parsed by gdk_rgba_parse().
355 * Note that this string representation may loose some
356 * precision, since r, g and b are represented as 8-bit
357 * integers. If this is a concern, you should use a
358 * different representation.
360 * Returns: A newly allocated text string
365 gdk_rgba_to_string (const GdkRGBA *rgba)
367 if (rgba->alpha > 0.999)
369 return g_strdup_printf ("rgb(%d,%d,%d)",
370 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
371 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
372 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.));
376 gchar alpha[G_ASCII_DTOSTR_BUF_SIZE];
378 g_ascii_dtostr (alpha, G_ASCII_DTOSTR_BUF_SIZE, CLAMP (rgba->alpha, 0, 1));
380 return g_strdup_printf ("rgba(%d,%d,%d,%s)",
381 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
382 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
383 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.),