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 <pango/pango-attributes.h>
39 #include "clutter-main.h"
40 #include "clutter-color.h"
41 #include "clutter-private.h"
42 #include "clutter-debug.h"
46 * @src1: a #ClutterColor
47 * @src2: a #ClutterColor
48 * @dest: return location for the result
50 * Adds @src2 to @src1 and saves the resulting color
53 * The alpha channel of @dest is as the maximum value
54 * between the alpha channels of @src1 and @src2.
57 clutter_color_add (const ClutterColor *src1,
58 const ClutterColor *src2,
61 g_return_if_fail (src1 != NULL);
62 g_return_if_fail (src2 != NULL);
63 g_return_if_fail (dest != NULL);
65 dest->red = CLAMP (src1->red + src2->red, 0, 255);
66 dest->green = CLAMP (src1->green + src2->green, 0, 255);
67 dest->blue = CLAMP (src1->blue + src2->blue, 0, 255);
69 dest->alpha = MAX (src1->alpha, src2->alpha);
73 * clutter_color_subtract:
74 * @src1: a #ClutterColor
75 * @src2: a #ClutterColor
76 * @dest: return location for the result
78 * Subtracts @src2 from @src1 and saves the resulting
79 * color inside @dest. This function assumes that the components
80 * of @src1 are greater than the components of @src2; the result is,
81 * otherwise, undefined.
83 * The alpha channel of @dest is set as the minimum value
84 * between the alpha channels of @src1 and @src2.
87 clutter_color_subtract (const ClutterColor *src1,
88 const ClutterColor *src2,
91 g_return_if_fail (src1 != NULL);
92 g_return_if_fail (src2 != NULL);
93 g_return_if_fail (dest != NULL);
95 dest->red = CLAMP (src1->red - src2->red, 0, 255);
96 dest->green = CLAMP (src1->green - src2->green, 0, 255);
97 dest->blue = CLAMP (src1->blue - src2->blue, 0, 255);
99 dest->alpha = MIN (src1->alpha, src2->alpha);
103 * clutter_color_lighten:
104 * @src: a #ClutterColor
105 * @dest: return location for the lighter color
107 * Lightens @src by a fixed amount, and saves the changed
111 clutter_color_lighten (const ClutterColor *src,
114 /* 0x14ccd is ClutterFixed for 1.3 */
115 clutter_color_shadex (src, dest, 0x14ccd);
119 * clutter_color_darken:
120 * @src: a #ClutterColor
121 * @dest: return location for the darker color
123 * Darkens @src by a fixed amount, and saves the changed color
127 clutter_color_darken (const ClutterColor *src,
130 /* 0xb333 is ClutterFixed for 0.7 */
131 clutter_color_shadex (src, dest, 0xb333);
135 * clutter_color_to_hlsx:
136 * @src: a #ClutterColor
137 * @hue: return location for the hue value or %NULL
138 * @luminance: return location for the luminance value or %NULL
139 * @saturation: return location for the saturation value or %NULL
141 * Converts @src to the HLS format. Returned hue is in degrees (0 .. 360),
142 * luminance and saturation from interval <0 .. 1>.
145 clutter_color_to_hlsx (const ClutterColor *src,
147 ClutterFixed *luminance,
148 ClutterFixed *saturation)
150 ClutterFixed red, green, blue;
151 ClutterFixed min, max, delta;
152 ClutterFixed h, l, s;
154 g_return_if_fail (src != NULL);
156 red = CLUTTER_INT_TO_FIXED (src->red) / 255;
157 green = CLUTTER_INT_TO_FIXED (src->green) / 255;
158 blue = CLUTTER_INT_TO_FIXED (src->blue) / 255;
192 s = CFX_DIV ((max - min), (max + min));
194 s = CFX_DIV ((max - min), (CLUTTER_INT_TO_FIXED (2) - max - min));
198 h = CFX_DIV ((green - blue), delta);
199 else if (green == max)
200 h = CLUTTER_INT_TO_FIXED (2) + CFX_DIV ((blue - red), delta);
201 else if (blue == max)
202 h = CLUTTER_INT_TO_FIXED (4) + CFX_DIV ((red - green), delta);
206 h += CLUTTER_INT_TO_FIXED (360);
220 * clutter_color_from_hlsx:
221 * @dest: return location for a #ClutterColor
222 * @hue: hue value (0 .. 360)
223 * @luminance: luminance value (0 .. 1)
224 * @saturation: saturation value (0 .. 1)
226 * Converts a color expressed in HLS (hue, luminance and saturation)
227 * values into a #ClutterColor.
231 clutter_color_from_hlsx (ClutterColor *dest,
233 ClutterFixed luminance,
234 ClutterFixed saturation)
236 ClutterFixed h, l, s;
239 g_return_if_fail (dest != NULL);
245 m2 = CFX_MUL (l, (CFX_ONE + s));
247 m2 = l + s - CFX_MUL (l,s);
253 dest->red = (guint8) CFX_INT (l * 255);
254 dest->green = (guint8) CFX_INT (l * 255);
255 dest->blue = (guint8) CFX_INT (l * 255);
266 dest->red = (guint8) CFX_INT((m1 + CFX_MUL((m2-m1), h) / 60) * 255);
267 else if (h < CFX_180)
268 dest->red = (guint8) CFX_INT (m2 * 255);
269 else if (h < CFX_240)
270 dest->red = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
272 dest->red = (guint8) CFX_INT (m1 * 255);
281 dest->green = (guint8)CFX_INT((m1 + CFX_MUL((m2 - m1), h) / 60) * 255);
282 else if (h < CFX_180)
283 dest->green = (guint8) CFX_INT (m2 * 255);
284 else if (h < CFX_240)
286 (guint8) CFX_INT((m1 + CFX_MUL ((m2-m1), (CFX_240-h)) / 60) * 255);
288 dest->green = (guint8) CFX_INT (m1 * 255);
297 dest->blue = (guint8) CFX_INT ((m1 + CFX_MUL ((m2-m1), h) / 60) * 255);
298 else if (h < CFX_180)
299 dest->blue = (guint8) CFX_INT (m2 * 255);
300 else if (h < CFX_240)
301 dest->blue = (guint8)CFX_INT((m1+CFX_MUL((m2-m1),(CFX_240-h))/60)*255);
303 dest->blue = (guint8) CFX_INT(m1 * 255);
308 * clutter_color_to_hls:
309 * @src: a #ClutterColor
310 * @hue: return location for the hue value or %NULL
311 * @luminance: return location for the luminance value or %NULL
312 * @saturation: return location for the saturation value or %NULL
314 * Converts @src to the HLS format. Returned HLS values are from interval
318 clutter_color_to_hls (const ClutterColor *src,
323 ClutterFixed h, l, s;
325 clutter_color_to_hlsx (src, &h, &l, &s);
328 *hue = (guint8) CFX_INT (h * 255) / 360;
331 *luminance = (guint8) CFX_INT (l * 255);
334 *saturation = (guint8) CFX_INT (s * 255);
338 * clutter_color_from_hls:
339 * @dest: return location for a #ClutterColor
340 * @hue: hue value (0 .. 255)
341 * @luminance: luminance value (0 .. 255)
342 * @saturation: saturation value (0 .. 255)
344 * Converts a color expressed in HLS (hue, luminance and saturation)
345 * values into a #ClutterColor.
349 clutter_color_from_hls (ClutterColor *dest,
354 ClutterFixed h, l, s;
356 h = CLUTTER_INT_TO_FIXED (hue * 360) / 255;
357 l = CLUTTER_INT_TO_FIXED (luminance) / 255;
358 s = CLUTTER_INT_TO_FIXED (saturation) / 255;
360 clutter_color_from_hlsx (dest, h, l, s);
364 * clutter_color_shade:
365 * @src: a #ClutterColor
366 * @dest: return location for the shaded color
367 * @shade: the shade factor to apply
369 * Shades @src by the factor of @shade and saves the modified
373 clutter_color_shade (const ClutterColor *src,
377 clutter_color_shadex (src, dest, CLUTTER_FLOAT_TO_FIXED (shade));
381 * clutter_color_shadex:
382 * @src: a #ClutterColor
383 * @dest: return location for the shaded color
384 * @shade: #ClutterFixed the shade factor to apply
386 * Fixed point version of clutter_color_shade().
388 * Shades @src by the factor of @shade and saves the modified
394 clutter_color_shadex (const ClutterColor *src,
398 ClutterFixed h, l, s;
400 g_return_if_fail (src != NULL);
401 g_return_if_fail (dest != NULL);
403 clutter_color_to_hlsx (src, &h, &l, &s);
405 l = CFX_MUL (l, shade);
411 s = CFX_MUL (s, shade);
417 clutter_color_from_hlsx (dest, h, l, s);
418 dest->alpha = src->alpha;
422 * clutter_color_to_pixel:
423 * @src: a #ClutterColor
425 * Converts @src into a packed 32 bit integer, containing
426 * all the four 8 bit channels used by #ClutterColor.
428 * Return value: a packed color
431 clutter_color_to_pixel (const ClutterColor *src)
433 g_return_val_if_fail (src != NULL, 0);
435 return (src->alpha | src->blue << 8 | src->green << 16 | src->red << 24);
439 * clutter_color_from_pixel:
440 * @dest: return location for a #ClutterColor
441 * @pixel: a 32 bit packed integer containing a color
443 * Converts @pixel from the packed representation of a four 8 bit channel
444 * color to a #ClutterColor.
447 clutter_color_from_pixel (ClutterColor *dest,
450 g_return_if_fail (dest != NULL);
452 dest->red = pixel >> 24;
453 dest->green = (pixel >> 16) & 0xff;
454 dest->blue = (pixel >> 8) & 0xff;
455 dest->alpha = pixel & 0xff;
459 * clutter_color_parse:
460 * @color: a string specifiying a color (named color or #RRGGBBAA)
461 * @dest: return location for a #ClutterColor
463 * Parses a string definition of a color, filling the
464 * <structfield>red</structfield>, <structfield>green</structfield>,
465 * <structfield>blue</structfield> and <structfield>alpha</structfield>
466 * channels of @dest. If alpha is not specified it will be set full opaque.
467 * The color in @dest is not allocated.
469 * The color may be defined by any of the formats understood by
470 * <function>pango_color_parse</function>; these include literal color
471 * names, like <literal>Red</literal> or <literal>DarkSlateGray</literal>,
472 * or hexadecimal specifications like <literal>#3050b2</literal> or
473 * <literal>#333</literal>.
475 * Return value: %TRUE if parsing succeeded.
480 clutter_color_parse (const gchar *color,
483 PangoColor pango_color;
485 /* parse ourselves to get alpha */
490 if (sscanf (color + 1, "%x", &result))
492 if (strlen (color) == 9)
494 dest->red = result >> 24 & 0xff;
495 dest->green = (result >> 16) & 0xff;
496 dest->blue = (result >> 8) & 0xff;
497 dest->alpha = result & 0xff;
501 else if (strlen (color) == 7)
503 dest->red = (result >> 16) & 0xff;
504 dest->green = (result >> 8) & 0xff;
505 dest->blue = result & 0xff;
513 /* Fall back to pango for named colors - note pango does not handle alpha */
514 if (pango_color_parse (&pango_color, color))
516 dest->red = pango_color.red;
517 dest->green = pango_color.green;
518 dest->blue = pango_color.blue;
528 * clutter_color_to_string:
529 * @color: a #ClutterColor
531 * Returns a textual specification of @color in the hexadecimal form
532 * <literal>#rrggbbaa</literal>, where <literal>r</literal>,
533 * <literal>g</literal>, <literal>b</literal> and <literal>a</literal> are
534 * hex digits representing the red, green, blue and alpha components
537 * Return value: a newly-allocated text string
542 clutter_color_to_string (const ClutterColor *color)
544 g_return_val_if_fail (color != NULL, NULL);
546 return g_strdup_printf ("#%02x%02x%02x%02x",
554 * clutter_color_equal:
555 * @a: a #ClutterColor
556 * @b: a #ClutterColor
558 * Compares two #ClutterColor<!-- -->s and checks if they are the same.
560 * Return value: %TRUE if the two colors are the same.
565 clutter_color_equal (const ClutterColor *a,
566 const ClutterColor *b)
568 g_return_val_if_fail (a != NULL, FALSE);
569 g_return_val_if_fail (b != NULL, FALSE);
574 return (a->red == b->red &&
575 a->green == b->green &&
576 a->blue == b->blue &&
577 a->alpha == b->alpha);
581 * clutter_color_copy:
582 * @color: a #ClutterColor
584 * Makes a copy of the color structure. The result must be
585 * freed using clutter_color_free().
587 * Return value: an allocated copy of @color.
592 clutter_color_copy (const ClutterColor *color)
594 ClutterColor *result;
596 g_return_val_if_fail (color != NULL, NULL);
598 result = g_slice_new (ClutterColor);
605 * clutter_color_free:
606 * @color: a #ClutterColor
608 * Frees a color structure created with clutter_color_copy().
613 clutter_color_free (ClutterColor *color)
615 g_return_if_fail (color != NULL);
617 g_slice_free (ClutterColor, color);
621 clutter_color_get_type (void)
623 static GType our_type = 0;
626 our_type = g_boxed_type_register_static (I_("ClutterColor"),
627 (GBoxedCopyFunc) clutter_color_copy,
628 (GBoxedFreeFunc) clutter_color_free);