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
77 * color inside @dest. This function assumes that the components
78 * of @src1 are greater than the components of @src2; the result is,
79 * otherwise, undefined.
81 * The alpha channel of @dest is set as the minimum value
82 * between the alpha channels of @src1 and @src2.
85 clutter_color_subtract (const ClutterColor *src1,
86 const ClutterColor *src2,
89 g_return_if_fail (src1 != NULL);
90 g_return_if_fail (src2 != NULL);
91 g_return_if_fail (dest != NULL);
93 dest->red = CLAMP (src1->red - src2->red, 0, 255);
94 dest->green = CLAMP (src1->green - src2->green, 0, 255);
95 dest->blue = CLAMP (src1->blue - src2->blue, 0, 255);
97 dest->alpha = MIN (src1->alpha, src2->alpha);
101 * clutter_color_lighten:
102 * @src: a #ClutterColor
103 * @dest: return location for the lighter color
105 * Lightens @src by a fixed amount, and saves the changed
109 clutter_color_lighten (const ClutterColor *src,
112 /* 0x14ccd is ClutterFixed for 1.3 */
113 clutter_color_shadex (src, dest, 0x14ccd);
117 * clutter_color_darken:
118 * @src: a #ClutterColor
119 * @dest: return location for the darker color
121 * Darkens @src by a fixed amount, and saves the changed color
125 clutter_color_darken (const ClutterColor *src,
128 /* 0xb333 is ClutterFixed for 0.7 */
129 clutter_color_shadex (src, dest, 0xb333);
133 * clutter_color_to_hlsx:
134 * @src: a #ClutterColor
135 * @hue: return location for the hue value or %NULL
136 * @luminance: return location for the luminance value or %NULL
137 * @saturation: return location for the saturation value or %NULL
139 * Converts @src to the HLS format. Returned hue is in degrees (0 .. 360),
140 * luminance and saturation from interval <0 .. 1>.
143 clutter_color_to_hlsx (const ClutterColor *src,
145 ClutterFixed *luminance,
146 ClutterFixed *saturation)
148 ClutterFixed red, green, blue;
149 ClutterFixed min, max, delta;
150 ClutterFixed h, l, s;
152 g_return_if_fail (src != NULL);
154 red = CLUTTER_INT_TO_FIXED (src->red) / 255;
155 green = CLUTTER_INT_TO_FIXED (src->green) / 255;
156 blue = CLUTTER_INT_TO_FIXED (src->blue) / 255;
190 s = CFX_DIV ((max - min), (max + min));
192 s = CFX_DIV ((max - min), (2 - max - min));
196 h = CFX_DIV ((green - blue), delta);
197 else if (green == max)
198 h = CLUTTER_INT_TO_FIXED (2) + CFX_DIV ((blue - red), delta);
199 else if (blue == max)
200 h = CLUTTER_INT_TO_FIXED (4) + CFX_DIV ((red - green), delta);
204 h += CLUTTER_INT_TO_FIXED (360);
218 * clutter_color_from_hlsx:
219 * @dest: return location for a #ClutterColor
220 * @hue: hue value (0 .. 360)
221 * @luminance: luminance value (0 .. 1)
222 * @saturation: saturation value (0 .. 1)
224 * Converts a color expressed in HLS (hue, luminance and saturation)
225 * values into a #ClutterColor.
229 clutter_color_from_hlsx (ClutterColor *dest,
231 ClutterFixed luminance,
232 ClutterFixed saturation)
234 ClutterFixed h, l, s;
237 g_return_if_fail (dest != NULL);
243 m2 = CFX_MUL (l, (CFX_ONE + s));
245 m2 = l + s - CFX_MUL (l,s);
251 dest->red = (guint8) CFX_INT (l * 255);
252 dest->green = (guint8) CFX_INT (l * 255);
253 dest->blue = (guint8) CFX_INT (l * 255);
264 dest->red = (guint8) CFX_INT((m1 + CFX_MUL((m2-m1), h) / 60) * 255);
265 else if (h < CFX_180)
266 dest->red = (guint8) CFX_INT (m2 * 255);
267 else if (h < CFX_240)
268 dest->red = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
270 dest->red = (guint8) CFX_INT (m1 * 255);
279 dest->green = (guint8)CFX_INT((m1 + CFX_MUL((m2 - m1), h) / 60) * 255);
280 else if (h < CFX_180)
281 dest->green = (guint8) CFX_INT (m2 * 255);
282 else if (h < CFX_240)
284 (guint8) CFX_INT((m1 + CFX_MUL ((m2-m1), (CFX_240-h)) / 60) * 255);
286 dest->green = (guint8) CFX_INT (m1 * 255);
295 dest->blue = (guint8) CFX_INT ((m1 + CFX_MUL ((m2-m1), h) / 60) * 255);
296 else if (h < CFX_180)
297 dest->blue = (guint8) CFX_INT (m2 * 255);
298 else if (h < CFX_240)
299 dest->blue = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
301 dest->blue = (guint8) CFX_INT(m1 * 255);
306 * clutter_color_to_hls:
307 * @src: a #ClutterColor
308 * @hue: return location for the hue value or %NULL
309 * @luminance: return location for the luminance value or %NULL
310 * @saturation: return location for the saturation value or %NULL
312 * Converts @src to the HLS format. Returned HLS values are from interval
316 clutter_color_to_hls (const ClutterColor *src,
321 ClutterFixed h, l, s;
323 clutter_color_to_hlsx (src, &h, &l, &s);
326 *hue = (guint8) CFX_INT (h * 255) / 360;
329 *luminance = (guint8) CFX_INT (l * 255);
332 *saturation = (guint8) CFX_INT (s * 255);
336 * clutter_color_from_hls:
337 * @dest: return location for a #ClutterColor
338 * @hue: hue value (0 .. 255)
339 * @luminance: luminance value (0 .. 255)
340 * @saturation: saturation value (0 .. 255)
342 * Converts a color expressed in HLS (hue, luminance and saturation)
343 * values into a #ClutterColor.
347 clutter_color_from_hls (ClutterColor *dest,
352 ClutterFixed h, l, s;
354 h = CLUTTER_INT_TO_FIXED (hue * 360) / 255;
355 l = CLUTTER_INT_TO_FIXED (luminance) / 255;
356 s = CLUTTER_INT_TO_FIXED (saturation) / 255;
358 clutter_color_from_hlsx (dest, h, l, s);
362 * clutter_color_shade:
363 * @src: a #ClutterColor
364 * @dest: return location for the shaded color
365 * @shade: the shade factor to apply
367 * Shades @src by the factor of @shade and saves the modified
371 clutter_color_shade (const ClutterColor *src,
375 clutter_color_shadex (src, dest, CLUTTER_FLOAT_TO_FIXED (shade));
379 * clutter_color_shadex:
380 * @src: a #ClutterColor
381 * @dest: return location for the shaded color
382 * @shade: #ClutterFixed the shade factor to apply
384 * Fixed point version of clutter_color_shade().
386 * Shades @src by the factor of @shade and saves the modified
392 clutter_color_shadex (const ClutterColor *src,
396 ClutterFixed h, l, s;
398 g_return_if_fail (src != NULL);
399 g_return_if_fail (dest != NULL);
401 clutter_color_to_hlsx (src, &h, &l, &s);
403 l = CFX_MUL (l, shade);
409 s = CFX_MUL (s, shade);
415 clutter_color_from_hlsx (dest, h, l, s);
419 * clutter_color_to_pixel:
420 * @src: a #ClutterColor
422 * Converts @src into a packed 32 bit integer, containing
423 * all the four 8 bit channels used by #ClutterColor.
425 * Return value: a packed color
428 clutter_color_to_pixel (const ClutterColor *src)
430 g_return_val_if_fail (src != NULL, 0);
432 return (src->alpha | src->blue << 8 | src->green << 16 | src->red << 24);
436 * clutter_color_from_pixel:
437 * @dest: return location for a #ClutterColor
438 * @pixel: a 32 bit packed integer containing a color
440 * Converts @pixel from the packed representation of a four 8 bit channel
441 * color to a #ClutterColor.
444 clutter_color_from_pixel (ClutterColor *dest,
447 g_return_if_fail (dest != NULL);
449 dest->red = pixel >> 24;
450 dest->green = (pixel >> 16) & 0xff;
451 dest->blue = (pixel >> 8) & 0xff;
452 dest->alpha = pixel & 0xff;
456 * clutter_color_parse:
457 * @color: a string specifiying a color (named color or #RRGGBBAA)
458 * @dest: return location for a #ClutterColor
460 * Parses a string definition of a color, filling the
461 * <structfield>red</structfield>, <structfield>green</structfield>,
462 * <structfield>blue</structfield> and <structfield>alpha</structfield>
463 * channels of @dest. If alpha is not specified it will be set full opaque.
464 * The color in @dest is not allocated.
466 * The color may be defined by any of the formats understood by
467 * <function>pango_color_parse</function>; these include literal color
468 * names, like <literal>Red</literal> or <literal>DarkSlateGray</literal>,
469 * or hexadecimal specifications like <literal>#3050b2</literal> or
470 * <literal>#333</literal>.
472 * Return value: %TRUE if parsing succeeded.
477 clutter_color_parse (const gchar *color,
480 PangoColor pango_color;
482 /* parse ourselves to get alpha */
487 if (sscanf (color+1, "%x", &result))
489 if (strlen(color) == 9)
491 dest->red = result >> 24 & 0xff;
492 dest->green = (result >> 16) & 0xff;
493 dest->blue = (result >> 8) & 0xff;
494 dest->alpha = result & 0xff;
497 else if (strlen(color) == 7)
499 dest->red = (result >> 16) & 0xff;
500 dest->green = (result >> 8) & 0xff;
501 dest->blue = result & 0xff;
508 /* Fall back to pango for named colors - note pango does not handle alpha */
509 if (pango_color_parse (&pango_color, color))
511 dest->red = pango_color.red;
512 dest->green = pango_color.green;
513 dest->blue = pango_color.blue;
522 * clutter_color_to_string:
523 * @color: a #ClutterColor
525 * Returns a textual specification of @color in the hexadecimal form
526 * <literal>#rrrrggggbbbbaaaa</literal>, where <literal>r</literal>,
527 * <literal>g</literal>, <literal>b</literal> and <literal>a</literal> are
528 * hex digits representing the red, green, blue and alpha components
531 * Note: the returned string cannot be used to get the color back with
532 * clutter_color_parse().
534 * Return value: a newly-allocated text string
539 clutter_color_to_string (const ClutterColor *color)
541 g_return_val_if_fail (color != NULL, NULL);
543 return g_strdup_printf ("#%04x%04x%04x%04x",
551 * clutter_color_equal:
552 * @a: a #ClutterColor
553 * @b: a #ClutterColor
555 * Compares two #ClutterColor<!-- -->s and checks if they are the same.
557 * Return value: %TRUE if the two colors are the same.
562 clutter_color_equal (const ClutterColor *a,
563 const ClutterColor *b)
565 g_return_val_if_fail (a != NULL, FALSE);
566 g_return_val_if_fail (b != NULL, FALSE);
571 return (a->red == b->red &&
572 a->green == b->green &&
573 a->blue == b->blue &&
574 a->alpha == b->alpha);
578 * clutter_color_copy:
579 * @color: a #ClutterColor
581 * Makes a copy of the color structure. The result must be
582 * freed using clutter_color_free().
584 * Return value: an allocated copy of @color.
589 clutter_color_copy (const ClutterColor *color)
591 ClutterColor *result;
593 g_return_val_if_fail (color != NULL, NULL);
595 result = g_slice_new (ClutterColor);
602 * clutter_color_free:
603 * @color: a #ClutterColor
605 * Frees a color structure created with clutter_color_copy().
610 clutter_color_free (ClutterColor *color)
612 g_return_if_fail (color != NULL);
614 g_slice_free (ClutterColor, color);
618 clutter_color_get_type (void)
620 static GType our_type = 0;
623 our_type = g_boxed_type_register_static ("ClutterColor",
624 (GBoxedCopyFunc) clutter_color_copy,
625 (GBoxedFreeFunc) clutter_color_free);