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), (CLUTTER_INT_TO_FIXED (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);
416 dest->alpha = src->alpha;
420 * clutter_color_to_pixel:
421 * @src: a #ClutterColor
423 * Converts @src into a packed 32 bit integer, containing
424 * all the four 8 bit channels used by #ClutterColor.
426 * Return value: a packed color
429 clutter_color_to_pixel (const ClutterColor *src)
431 g_return_val_if_fail (src != NULL, 0);
433 return (src->alpha | src->blue << 8 | src->green << 16 | src->red << 24);
437 * clutter_color_from_pixel:
438 * @dest: return location for a #ClutterColor
439 * @pixel: a 32 bit packed integer containing a color
441 * Converts @pixel from the packed representation of a four 8 bit channel
442 * color to a #ClutterColor.
445 clutter_color_from_pixel (ClutterColor *dest,
448 g_return_if_fail (dest != NULL);
450 dest->red = pixel >> 24;
451 dest->green = (pixel >> 16) & 0xff;
452 dest->blue = (pixel >> 8) & 0xff;
453 dest->alpha = pixel & 0xff;
457 * clutter_color_parse:
458 * @color: a string specifiying a color (named color or #RRGGBBAA)
459 * @dest: return location for a #ClutterColor
461 * Parses a string definition of a color, filling the
462 * <structfield>red</structfield>, <structfield>green</structfield>,
463 * <structfield>blue</structfield> and <structfield>alpha</structfield>
464 * channels of @dest. If alpha is not specified it will be set full opaque.
465 * The color in @dest is not allocated.
467 * The color may be defined by any of the formats understood by
468 * <function>pango_color_parse</function>; these include literal color
469 * names, like <literal>Red</literal> or <literal>DarkSlateGray</literal>,
470 * or hexadecimal specifications like <literal>#3050b2</literal> or
471 * <literal>#333</literal>.
473 * Return value: %TRUE if parsing succeeded.
478 clutter_color_parse (const gchar *color,
481 PangoColor pango_color;
483 /* parse ourselves to get alpha */
488 if (sscanf (color + 1, "%x", &result))
490 if (strlen (color) == 9)
492 dest->red = result >> 24 & 0xff;
493 dest->green = (result >> 16) & 0xff;
494 dest->blue = (result >> 8) & 0xff;
495 dest->alpha = result & 0xff;
499 else if (strlen (color) == 7)
501 dest->red = (result >> 16) & 0xff;
502 dest->green = (result >> 8) & 0xff;
503 dest->blue = result & 0xff;
511 /* Fall back to pango for named colors - note pango does not handle alpha */
512 if (pango_color_parse (&pango_color, color))
514 dest->red = pango_color.red;
515 dest->green = pango_color.green;
516 dest->blue = pango_color.blue;
526 * clutter_color_to_string:
527 * @color: a #ClutterColor
529 * Returns a textual specification of @color in the hexadecimal form
530 * <literal>#rrggbbaa</literal>, where <literal>r</literal>,
531 * <literal>g</literal>, <literal>b</literal> and <literal>a</literal> are
532 * hex digits representing the red, green, blue and alpha components
535 * Return value: a newly-allocated text string
540 clutter_color_to_string (const ClutterColor *color)
542 g_return_val_if_fail (color != NULL, NULL);
544 return g_strdup_printf ("#%02x%02x%02x%02x",
552 * clutter_color_equal:
553 * @a: a #ClutterColor
554 * @b: a #ClutterColor
556 * Compares two #ClutterColor<!-- -->s and checks if they are the same.
558 * Return value: %TRUE if the two colors are the same.
563 clutter_color_equal (const ClutterColor *a,
564 const ClutterColor *b)
566 g_return_val_if_fail (a != NULL, FALSE);
567 g_return_val_if_fail (b != NULL, FALSE);
572 return (a->red == b->red &&
573 a->green == b->green &&
574 a->blue == b->blue &&
575 a->alpha == b->alpha);
579 * clutter_color_copy:
580 * @color: a #ClutterColor
582 * Makes a copy of the color structure. The result must be
583 * freed using clutter_color_free().
585 * Return value: an allocated copy of @color.
590 clutter_color_copy (const ClutterColor *color)
592 ClutterColor *result;
594 g_return_val_if_fail (color != NULL, NULL);
596 result = g_slice_new (ClutterColor);
603 * clutter_color_free:
604 * @color: a #ClutterColor
606 * Frees a color structure created with clutter_color_copy().
611 clutter_color_free (ClutterColor *color)
613 g_return_if_fail (color != NULL);
615 g_slice_free (ClutterColor, color);
619 clutter_color_get_type (void)
621 static GType our_type = 0;
624 our_type = g_boxed_type_register_static (I_("ClutterColor"),
625 (GBoxedCopyFunc) clutter_color_copy,
626 (GBoxedFreeFunc) clutter_color_free);