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
50 gdk_rgba_copy (GdkRGBA *rgba)
54 copy = g_slice_new (GdkRGBA);
55 copy->red = rgba->red;
56 copy->green = rgba->green;
57 copy->blue = rgba->blue;
58 copy->alpha = rgba->alpha;
67 * Frees a #GdkRGBA struct created with gdk_rgba_copy()
70 gdk_rgba_free (GdkRGBA *rgba)
72 g_slice_free (GdkRGBA, rgba);
75 #define SKIP_WHITESPACES(s) while (*(s) == ' ') (s)++;
77 /* Parses a single color component from a rgb() or rgba() specification
78 * according to CSS3 rules. Compared to exact CSS3 parsing we are liberal
79 * in what we accept as follows:
81 * - For non-percentage values, we accept floats in the range 0-255
82 * not just [0-9]+ integers
83 * - For percentage values we accept any float, not just
84 * [ 0-9]+ | [0-9]* '.' [0-9]+
85 * - We accept mixed percentages and non-percentages in a single
86 * rgb() or rgba() specification.
89 parse_rgb_value (const char *str,
95 number = g_ascii_strtod (str, endp);
103 *endp = (char *)(p + 1);
104 return CLAMP(number / 100., 0., 1.);
108 return CLAMP(number / 255., 0., 1.);
114 * @spec: the string specifying the color
115 * @rgba: the #GdkRGBA struct to fill in
117 * Parses a textual representation of a color, filling in
118 * the <structfield>red</structfield>, <structfield>green</structfield>,
119 * <structfield>blue</structfield> and <structfield>alpha</structfield>
120 * fields of the @rgba struct.
122 * The string can be either one of:
125 * A standard name (Taken from the X11 rgb.txt file).
128 * A hex value in the form '#rgb' '#rrggbb' '#rrrgggbbb' or '#rrrrggggbbbb'
131 * A RGB color in the form 'rgb(r,g,b)' (In this case the color will
135 * A RGBA color in the form 'rgba(r,g,b,a)'
139 * Where 'r', 'g', 'b' and 'a' are respectively the red, green, blue and
140 * alpha color values. In the last two cases, r g and b are either integers
141 * in the range 0 to 255 or precentage values in the range 0% to 100%, and
142 * a is a floating point value in the range 0 to 1.
144 * Returns: %TRUE if the parsing succeeded
147 gdk_rgba_parse (const gchar *spec,
152 gchar *str = (gchar *) spec;
154 if (strncmp (str, "rgba", 4) == 0)
159 else if (strncmp (str, "rgb", 3) == 0)
167 PangoColor pango_color;
169 /* Resort on PangoColor for rgb.txt color
170 * map and '#' prefixed colors */
171 if (pango_color_parse (&pango_color, str))
175 rgba->red = pango_color.red / 65535.;
176 rgba->green = pango_color.green / 65535.;
177 rgba->blue = pango_color.blue / 65535.;
187 SKIP_WHITESPACES (str);
195 SKIP_WHITESPACES (str);
196 r = parse_rgb_value (str, &str);
197 SKIP_WHITESPACES (str);
205 SKIP_WHITESPACES (str);
206 g = parse_rgb_value (str, &str);
207 SKIP_WHITESPACES (str);
215 SKIP_WHITESPACES (str);
216 b = parse_rgb_value (str, &str);
217 SKIP_WHITESPACES (str);
226 SKIP_WHITESPACES (str);
227 a = g_ascii_strtod (str, &str);
228 SKIP_WHITESPACES (str);
236 rgba->red = CLAMP (r, 0, 1);
237 rgba->green = CLAMP (g, 0, 1);
238 rgba->blue = CLAMP (b, 0, 1);
239 rgba->alpha = CLAMP (a, 0, 1);
245 #undef SKIP_WHITESPACES
249 * @p: a #GdkRGBA pointer.
251 * A hash function suitable for using for a hash
252 * table that stores #GdkRGBA<!-- -->s.
254 * Return value: The hash function applied to @p
257 gdk_rgba_hash (gconstpointer p)
259 const GdkRGBA *rgba = p;
261 return ((guint) (rgba->red * 65535) +
262 ((guint) (rgba->green * 65535) << 11) +
263 ((guint) (rgba->blue * 65535) << 22) +
264 ((guint) (rgba->alpha * 65535) >> 6));
269 * @p1: a #GdkRGBA pointer.
270 * @p2: another #GdkRGBA pointer.
272 * Compares two RGBA colors.
274 * Return value: %TRUE if the two colors compare equal
277 gdk_rgba_equal (gconstpointer p1,
280 const GdkRGBA *rgba1, *rgba2;
285 if (rgba1->red == rgba2->red &&
286 rgba1->green == rgba2->green &&
287 rgba1->blue == rgba2->blue &&
288 rgba1->alpha == rgba2->alpha)
295 * gdk_rgba_to_string:
298 * Returns a textual specification of @rgba in the form <literal>rgb
299 * (r, g, b)</literal> or <literal>rgba (r, g, b, a)</literal>,
300 * where 'r', 'g', 'b' and 'a' represent the red, green, blue and alpha values
301 * respectively. r, g, and b are integers in the range 0 to 255, and a
302 * is a floating point value in the range 0 to 1.
304 * (These string forms are string forms those supported by the CSS3 colors module)
306 * Returns: A newly allocated text string
309 gdk_rgba_to_string (const GdkRGBA *rgba)
311 if (rgba->alpha > 0.999)
313 return g_strdup_printf ("rgb(%d,%d,%d)",
314 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
315 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
316 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.));
320 gchar alpha[G_ASCII_DTOSTR_BUF_SIZE];
322 g_ascii_dtostr (alpha, G_ASCII_DTOSTR_BUF_SIZE, CLAMP (rgba->alpha, 0, 1));
324 return g_strdup_printf ("rgba(%d,%d,%d,%s)",
325 (int)(0.5 + CLAMP (rgba->red, 0., 1.) * 255.),
326 (int)(0.5 + CLAMP (rgba->green, 0., 1.) * 255.),
327 (int)(0.5 + CLAMP (rgba->blue, 0., 1.) * 255.),