1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
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 #include "gtksymboliccolor.h"
22 #include "gtkstyleproperties.h"
26 * SECTION:gtksymboliccolor
27 * @Short_description: Symbolic colors
28 * @Title: GtkSymbolicColor
30 * GtkSymbolicColor is a boxed type that represents a symbolic color.
31 * It is the result of parsing a
32 * <link linkend="gtkcssprovider-symbolic-colors">color expression</link>.
33 * To obtain the color represented by a GtkSymbolicColor, it has to
34 * be resolved with gtk_symbolic_color_resolve(), which replaces all
35 * symbolic color references by the colors they refer to (in a given
36 * context) and evaluates mix, shade and other expressions, resulting
37 * in a #GdkRGBA value.
39 * It is not normally necessary to deal directly with #GtkSymbolicColors,
40 * since they are mostly used behind the scenes by #GtkStyleContext and
44 G_DEFINE_BOXED_TYPE (GtkSymbolicColor, gtk_symbolic_color,
45 gtk_symbolic_color_ref, gtk_symbolic_color_unref)
56 struct _GtkSymbolicColor
68 GtkSymbolicColor *color;
74 GtkSymbolicColor *color1;
75 GtkSymbolicColor *color2;
82 * gtk_symbolic_color_new_literal:
85 * Creates a symbolic color pointing to a literal color.
87 * Returns: a newly created #GtkSymbolicColor
92 gtk_symbolic_color_new_literal (const GdkRGBA *color)
94 GtkSymbolicColor *symbolic_color;
96 g_return_val_if_fail (color != NULL, NULL);
98 symbolic_color = g_slice_new0 (GtkSymbolicColor);
99 symbolic_color->type = COLOR_TYPE_LITERAL;
100 symbolic_color->color = *color;
101 symbolic_color->ref_count = 1;
103 return symbolic_color;
107 * gtk_symbolic_color_new_name:
110 * Creates a symbolic color pointing to an unresolved named
111 * color. See gtk_style_context_lookup_color() and
112 * gtk_style_properties_lookup_color().
114 * Returns: a newly created #GtkSymbolicColor
119 gtk_symbolic_color_new_name (const gchar *name)
121 GtkSymbolicColor *symbolic_color;
123 g_return_val_if_fail (name != NULL, NULL);
125 symbolic_color = g_slice_new0 (GtkSymbolicColor);
126 symbolic_color->type = COLOR_TYPE_NAME;
127 symbolic_color->name = g_strdup (name);
128 symbolic_color->ref_count = 1;
130 return symbolic_color;
134 * gtk_symbolic_color_new_shade:
135 * @color: another #GtkSymbolicColor
136 * @factor: shading factor to apply to @color
138 * Creates a symbolic color defined as a shade of
139 * another color. A factor > 1.0 would resolve to
140 * a brighter color, while < 1.0 would resolve to
143 * Returns: A newly created #GtkSymbolicColor
148 gtk_symbolic_color_new_shade (GtkSymbolicColor *color,
151 GtkSymbolicColor *symbolic_color;
153 g_return_val_if_fail (color != NULL, NULL);
155 symbolic_color = g_slice_new0 (GtkSymbolicColor);
156 symbolic_color->type = COLOR_TYPE_SHADE;
157 symbolic_color->shade.color = gtk_symbolic_color_ref (color);
158 symbolic_color->shade.factor = factor;
159 symbolic_color->ref_count = 1;
161 return symbolic_color;
165 * gtk_symbolic_color_new_alpha:
166 * @color: another #GtkSymbolicColor
167 * @factor: factor to apply to @color alpha
169 * Creates a symbolic color by modifying the relative alpha
170 * value of @color. A factor < 1.0 would resolve to a more
171 * transparent color, while > 1.0 would resolve to a more
174 * Returns: A newly created #GtkSymbolicColor
179 gtk_symbolic_color_new_alpha (GtkSymbolicColor *color,
182 GtkSymbolicColor *symbolic_color;
184 g_return_val_if_fail (color != NULL, NULL);
186 symbolic_color = g_slice_new0 (GtkSymbolicColor);
187 symbolic_color->type = COLOR_TYPE_ALPHA;
188 symbolic_color->alpha.color = gtk_symbolic_color_ref (color);
189 symbolic_color->alpha.factor = factor;
190 symbolic_color->ref_count = 1;
192 return symbolic_color;
196 * gtk_symbolic_color_new_mix:
197 * @color1: color to mix
198 * @color2: another color to mix
199 * @factor: mix factor
201 * Creates a symbolic color defined as a mix of another
202 * two colors. a mix factor of 0 would resolve to @color1,
203 * while a factor of 1 would resolve to @color2.
205 * Returns: A newly created #GtkSymbolicColor
210 gtk_symbolic_color_new_mix (GtkSymbolicColor *color1,
211 GtkSymbolicColor *color2,
214 GtkSymbolicColor *symbolic_color;
216 g_return_val_if_fail (color1 != NULL, NULL);
217 g_return_val_if_fail (color1 != NULL, NULL);
219 symbolic_color = g_slice_new0 (GtkSymbolicColor);
220 symbolic_color->type = COLOR_TYPE_MIX;
221 symbolic_color->mix.color1 = gtk_symbolic_color_ref (color1);
222 symbolic_color->mix.color2 = gtk_symbolic_color_ref (color2);
223 symbolic_color->mix.factor = factor;
224 symbolic_color->ref_count = 1;
226 return symbolic_color;
230 * gtk_symbolic_color_ref:
231 * @color: a #GtkSymbolicColor
233 * Increases the reference count of @color
235 * Returns: the same @color
240 gtk_symbolic_color_ref (GtkSymbolicColor *color)
242 g_return_val_if_fail (color != NULL, NULL);
250 * gtk_symbolic_color_unref:
251 * @color: a #GtkSymbolicColor
253 * Decreases the reference count of @color, freeing its memory if the
254 * reference count reaches 0.
259 gtk_symbolic_color_unref (GtkSymbolicColor *color)
261 g_return_if_fail (color != NULL);
265 if (color->ref_count == 0)
269 case COLOR_TYPE_NAME:
270 g_free (color->name);
272 case COLOR_TYPE_SHADE:
273 gtk_symbolic_color_unref (color->shade.color);
275 case COLOR_TYPE_ALPHA:
276 gtk_symbolic_color_unref (color->alpha.color);
279 gtk_symbolic_color_unref (color->mix.color1);
280 gtk_symbolic_color_unref (color->mix.color2);
286 g_slice_free (GtkSymbolicColor, color);
291 rgb_to_hls (gdouble *r,
339 s = (max - min) / (max + min);
341 s = (max - min) / (2 - max - min);
345 h = (green - blue) / delta;
346 else if (green == max)
347 h = 2 + (blue - red) / delta;
348 else if (blue == max)
349 h = 4 + (red - green) / delta;
362 hls_to_rgb (gdouble *h,
375 if (lightness <= 0.5)
376 m2 = lightness * (1 + saturation);
378 m2 = lightness + saturation - lightness * saturation;
379 m1 = 2 * lightness - m2;
396 r = m1 + (m2 - m1) * hue / 60;
400 r = m1 + (m2 - m1) * (240 - hue) / 60;
411 g = m1 + (m2 - m1) * hue / 60;
415 g = m1 + (m2 - m1) * (240 - hue) / 60;
426 b = m1 + (m2 - m1) * hue / 60;
430 b = m1 + (m2 - m1) * (240 - hue) / 60;
441 _shade_color (GdkRGBA *color,
447 rgb_to_hls (&temp.red, &temp.green, &temp.blue);
449 temp.green *= factor;
450 if (temp.green > 1.0)
452 else if (temp.green < 0.0)
458 else if (temp.blue < 0.0)
461 hls_to_rgb (&temp.red, &temp.green, &temp.blue);
466 * gtk_symbolic_color_resolve:
467 * @color: a #GtkSymbolicColor
468 * @props: (allow-none): #GtkStyleProperties to use when resolving
469 * named colors, or %NULL
470 * @resolved_color: (out): return location for the resolved color
472 * If @color is resolvable, @resolved_color will be filled in
473 * with the resolved color, and %TRUE will be returned. Generally,
474 * if @color can't be resolved, it is due to it being defined on
475 * top of a named color that doesn't exist in @props.
477 * @props must be non-%NULL if @color was created using
478 * gtk_symbolic_color_named_new(), but can be omitted in other cases.
480 * Returns: %TRUE if the color has been resolved
485 gtk_symbolic_color_resolve (GtkSymbolicColor *color,
486 GtkStyleProperties *props,
487 GdkRGBA *resolved_color)
489 g_return_val_if_fail (color != NULL, FALSE);
490 g_return_val_if_fail (resolved_color != NULL, FALSE);
494 case COLOR_TYPE_LITERAL:
495 *resolved_color = color->color;
497 case COLOR_TYPE_NAME:
499 GtkSymbolicColor *named_color;
501 g_return_val_if_fail (GTK_IS_STYLE_PROPERTIES (props), FALSE);
503 named_color = gtk_style_properties_lookup_color (props, color->name);
508 return gtk_symbolic_color_resolve (named_color, props, resolved_color);
512 case COLOR_TYPE_SHADE:
516 if (!gtk_symbolic_color_resolve (color->shade.color, props, &shade))
519 _shade_color (&shade, color->shade.factor);
520 *resolved_color = shade;
526 case COLOR_TYPE_ALPHA:
530 if (!gtk_symbolic_color_resolve (color->alpha.color, props, &alpha))
533 *resolved_color = alpha;
534 resolved_color->alpha = CLAMP (alpha.alpha * color->alpha.factor, 0, 1);
540 GdkRGBA color1, color2;
542 if (!gtk_symbolic_color_resolve (color->mix.color1, props, &color1))
545 if (!gtk_symbolic_color_resolve (color->mix.color2, props, &color2))
548 resolved_color->red = CLAMP (color1.red + ((color2.red - color1.red) * color->mix.factor), 0, 1);
549 resolved_color->green = CLAMP (color1.green + ((color2.green - color1.green) * color->mix.factor), 0, 1);
550 resolved_color->blue = CLAMP (color1.blue + ((color2.blue - color1.blue) * color->mix.factor), 0, 1);
551 resolved_color->alpha = CLAMP (color1.alpha + ((color2.alpha - color1.alpha) * color->mix.factor), 0, 1);
558 g_assert_not_reached ();