4 * An OpenGL based 'interactive canvas' library.
6 * Authored By Matthew Allum <mallum@openedhand.com>
8 * Copyright (C) 2006 OpenedHand
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the
22 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
27 * SECTION:clutter-color
28 * @short_description: Color management and manipulation.
30 * #ClutterColor is a simple type for representing colors.
37 #include "clutter-main.h"
38 #include "clutter-color.h"
39 #include "clutter-private.h"
40 #include "clutter-debug.h"
44 * @src1: a #ClutterColor
45 * @src2: a #ClutterColor
46 * @dest: return location for the result
48 * Adds @src2 to @src1 and saves the resulting color
51 * The alpha channel of @dest is as the maximum value
52 * between the alpha channels of @src1 and @src2.
55 clutter_color_add (const ClutterColor *src1,
56 const ClutterColor *src2,
59 g_return_if_fail (src1 != NULL);
60 g_return_if_fail (src2 != NULL);
61 g_return_if_fail (dest != NULL);
63 dest->red = CLAMP (src1->red + src2->red, 0, 255);
64 dest->green = CLAMP (src1->green + src2->green, 0, 255);
65 dest->blue = CLAMP (src1->blue + src2->blue, 0, 255);
67 dest->alpha = MAX (src1->alpha, src2->alpha);
71 * clutter_color_subtract:
72 * @src1: a #ClutterColor
73 * @src2: a #ClutterColor
74 * @dest: return location for the result
76 * Subtracts @src2 from @src1 and saves the resulting
79 * The alpha channel of @dest is set as the minimum value
80 * between the alpha channels of @src1 and @src2.
83 clutter_color_subtract (const ClutterColor *src1,
84 const ClutterColor *src2,
87 g_return_if_fail (src1 != NULL);
88 g_return_if_fail (src2 != NULL);
89 g_return_if_fail (dest != NULL);
91 dest->red = CLAMP (src2->red - src1->red, 0, 255);
92 dest->green = CLAMP (src2->green - src1->green, 0, 255);
93 dest->blue = CLAMP (src2->blue - src1->blue, 0, 255);
95 dest->alpha = MIN (src1->alpha, src2->alpha);
99 * clutter_color_lighten:
100 * @src: a #ClutterColor
101 * @dest: return location for the lighter color
103 * Lightens @src by a fixed amount, and saves the changed
107 clutter_color_lighten (const ClutterColor *src,
110 /* 0x14ccd is ClutterFixed for 1.3 */
111 clutter_color_shade (src, dest, 0x14ccd);
115 * clutter_color_darken:
116 * @src: a #ClutterColor
117 * @dest: return location for the darker color
119 * Darkens @src by a fixed amount, and saves the changed color
123 clutter_color_darken (const ClutterColor *src,
126 /* 0xb333 is ClutterFixed for 0.7 */
127 clutter_color_shade (src, dest, 0xb333);
131 * clutter_color_to_hls:
132 * @src: a #ClutterColor
133 * @hue: return location for the hue value or %NULL
134 * @luminance: return location for the luminance value or %NULL
135 * @saturation: return location for the saturation value or %NULL
137 * Converts @src to the HLS format.
140 clutter_color_to_hls (const ClutterColor *src,
145 ClutterFixed red, green, blue;
146 ClutterFixed min, max, delta;
147 ClutterFixed h, l, s;
149 g_return_if_fail (src != NULL);
151 red = CLUTTER_INT_TO_FIXED (src->red) / 255;
152 green = CLUTTER_INT_TO_FIXED (src->green) / 255;
153 blue = CLUTTER_INT_TO_FIXED (src->blue) / 255;
187 s = CFX_DIV ((max - min), (max + min));
189 s = CFX_DIV ((max - min), (2 - max - min));
193 h = CFX_DIV ((green - blue), delta);
194 else if (green == max)
195 h = CLUTTER_INT_TO_FIXED (2) + CFX_DIV ((blue - red), delta);
196 else if (blue == max)
197 h = CLUTTER_INT_TO_FIXED (4) + CFX_DIV ((red - green), delta);
201 h += CLUTTER_INT_TO_FIXED (360);
205 *hue = (guint8) CFX_INT (h * 255);
208 *luminance = (guint8) CFX_INT (l * 255);
211 *saturation = (guint8) CFX_INT (s * 255);
215 * clutter_color_from_hls:
216 * @dest: return location for a #ClutterColor
217 * @hue: hue value (0 .. 255)
218 * @luminance: luminance value (0 .. 255)
219 * @saturation: saturation value (0 .. 255)
221 * Converts a color expressed in HLS (hue, luminance and saturation)
222 * values into a #ClutterColor.
226 clutter_color_from_hls (ClutterColor *dest,
231 ClutterFixed h, l, s;
234 g_return_if_fail (dest != NULL);
236 l = CLUTTER_INT_TO_FIXED (luminance) / 255;
237 s = CLUTTER_INT_TO_FIXED (saturation) / 255;
240 m2 = CFX_MUL (l, (CFX_ONE - s));
242 m2 = l + s - CFX_MUL (l,s);
248 dest->red = (guint8) CFX_INT (l * 255);
249 dest->green = (guint8) CFX_INT (l * 255);
250 dest->blue = (guint8) CFX_INT (l * 255);
254 h = (CLUTTER_INT_TO_FIXED (hue)/ 255) + CFX_120;
261 dest->red = (guint8) CFX_INT((m1 + CFX_MUL((m2-m1), h) / 60) * 255);
262 else if (h < CFX_180)
263 dest->red = (guint8) CFX_INT (m2 * 255);
264 else if (h < CFX_240)
265 dest->red = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
267 dest->red = (guint8) CFX_INT (m1 * 255);
269 h = CLUTTER_INT_TO_FIXED (hue) / 255;
276 dest->green = (guint8)CFX_INT((m1 + CFX_MUL((m2 - m1), h) / 60) * 255);
277 else if (h < CFX_180)
278 dest->green = (guint8) CFX_INT (m2 * 255);
279 else if (h < CFX_240)
281 (guint8) CFX_INT((m1 + CFX_MUL ((m2-m1), (CFX_240-h)) / 60) * 255);
283 dest->green = (guint8) CFX_INT (m1 * 255);
285 h = (CLUTTER_INT_TO_FIXED (hue) / 255) - CFX_120;
292 dest->blue = (guint8) CFX_INT ((m1 + CFX_MUL ((m2-m1), h) / 60) * 255);
293 else if (h < CFX_180)
294 dest->blue = (guint8) CFX_INT (m2 * 255);
295 else if (h < CFX_240)
296 dest->blue = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
298 dest->blue = (guint8) CFX_INT(m1 * 255);
303 * clutter_color_shade:
304 * @src: a #ClutterColor
305 * @dest: return location for the shaded color
306 * @shade: the shade factor to apply
308 * Shades @src by the factor of @shade and saves the modified
312 clutter_color_shade (const ClutterColor *src,
316 clutter_color_shadex (src, dest, CLUTTER_FLOAT_TO_FIXED (shade));
320 * clutter_color_shade:
321 * @src: a #ClutterColor
322 * @dest: return location for the shaded color
323 * @shade: #ClutterFixed the shade factor to apply
325 * Shades @src by the factor of @shade and saves the modified
329 clutter_color_shadex (const ClutterColor *src,
336 g_return_if_fail (src != NULL);
337 g_return_if_fail (dest != NULL);
339 clutter_color_to_hls (src, &h, &l, &s);
341 l1 = CLUTTER_INT_TO_FIXED (l) / 255;
342 s1 = CLUTTER_INT_TO_FIXED (s) / 255;
344 l1 = CFX_MUL (l1, shade);
350 s1 = CFX_MUL (s1, shade);
356 l = (guint8) CFX_INT (l1 * 255);
357 s = (guint8) CFX_INT (s1 * 255);
359 clutter_color_from_hls (dest, h, l, s);
363 * clutter_color_to_pixel:
364 * @src: a #ClutterColor
366 * Converts @src into a packed 32 bit integer, containing
367 * all the four 8 bit channels used by #ClutterColor.
369 * Return value: a packed color
372 clutter_color_to_pixel (const ClutterColor *src)
374 g_return_val_if_fail (src != NULL, 0);
376 return (src->alpha | src->blue << 8 | src->green << 16 | src->red << 24);
380 * clutter_color_from_pixel:
381 * @dest: return location for a #ClutterColor
382 * @pixel: a 32 bit packed integer containing a color
384 * Converts @pixel from the packed representation of a four 8 bit channel
385 * color to a #ClutterColor.
388 clutter_color_from_pixel (ClutterColor *dest,
391 g_return_if_fail (dest != NULL);
393 dest->red = pixel >> 24;
394 dest->green = (pixel >> 16) & 0xff;
395 dest->blue = (pixel >> 8) & 0xff;
396 dest->alpha = pixel % 0xff;
400 * clutter_color_parse:
401 * @color: a string specifiying a color
402 * @dest: return location for a #ClutterColor
404 * Parses a string definition of a color, filling the
405 * <structfield>red</structfield>, <structfield>green</structfield> and
406 * <structfield>blue</structfield> channels of @dest. The
407 * <structfield>alpha</structfield> channel is not changed. The
408 * color in @dest is not allocated.
410 * The color may be defined by any of the formats understood by
411 * <function>XParseColor</function>; these include literal color
412 * names, like <literal>Red</literal> or <literal>DarkSlateGray</literal>,
413 * or hexadecimal specifications like <literal>#3050b2</literal> or
414 * <literal>#333</literal>.
416 * Return value: %TRUE if parsing succeeded.
421 clutter_color_parse (const gchar *color,
424 PangoColor pango_color;
426 if (pango_color_parse (&pango_color, color))
428 dest->red = pango_color.red;
429 dest->green = pango_color.green;
430 dest->blue = pango_color.blue;
439 * clutter_color_to_string:
440 * @color: a #ClutterColor
442 * Returns a textual specification of @color in the hexadecimal form
443 * <literal>#rrrrggggbbbbaaaa</literal>, where <literal>r</literal>,
444 * <literal>g</literal>, <literal>b</literal> and <literal>a</literal> are
445 * hex digits representing the red, green, blue and alpha components
448 * Note: the returned string cannot be used to get the color back with
449 * clutter_color_parse().
451 * Return value: a newly-allocated text string
456 clutter_color_to_string (const ClutterColor *color)
458 g_return_val_if_fail (color != NULL, NULL);
460 return g_strdup_printf ("#%04x%04x%04x%04x",
468 * clutter_color_equal:
469 * @a: a #ClutterColor
470 * @b: a #ClutterColor
472 * Compares two #ClutterColor<!-- -->s and checks if they are the same.
474 * Return: %TRUE if the two colors are the same.
479 clutter_color_equal (const ClutterColor *a,
480 const ClutterColor *b)
482 g_return_val_if_fail (a != NULL, FALSE);
483 g_return_val_if_fail (b != NULL, FALSE);
488 return (a->red == b->red &&
489 a->green == b->green &&
490 a->blue == b->blue &&
491 a->alpha == b->alpha);
495 * clutter_color_copy:
496 * @color: a #ClutterColor
498 * Makes a copy of the color structure. The result must be
499 * freed using clutter_color_free().
501 * Return value: an allocated copy of @color.
506 clutter_color_copy (const ClutterColor *color)
508 ClutterColor *result;
510 g_return_val_if_fail (color != NULL, NULL);
512 result = g_slice_new (ClutterColor);
519 * clutter_color_free:
520 * @color: a #ClutterColor
522 * Frees a color structure created with clutter_color_copy().
527 clutter_color_free (ClutterColor *color)
529 g_return_if_fail (color != NULL);
531 g_slice_free (ClutterColor, color);
535 clutter_color_get_type (void)
537 static GType our_type = 0;
540 our_type = g_boxed_type_register_static ("ClutterColor",
541 (GBoxedCopyFunc) clutter_color_copy,
542 (GBoxedFreeFunc) clutter_color_free);