1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include "gtkcssrgbavalueprivate.h"
21 
22 #include "gtkcssstylepropertyprivate.h"
23 #include "gtkstylecontextprivate.h"
24 
25 struct _GtkCssValue {
26   GTK_CSS_VALUE_BASE
27   GdkRGBA rgba;
28 };
29 
30 static void
gtk_css_value_rgba_free(GtkCssValue * value)31 gtk_css_value_rgba_free (GtkCssValue *value)
32 {
33   g_slice_free (GtkCssValue, value);
34 }
35 
36 static GtkCssValue *
gtk_css_value_rgba_compute(GtkCssValue * value,guint property_id,GtkStyleProviderPrivate * provider,GtkCssStyle * style,GtkCssStyle * parent_style)37 gtk_css_value_rgba_compute (GtkCssValue             *value,
38                             guint                    property_id,
39                             GtkStyleProviderPrivate *provider,
40                             GtkCssStyle             *style,
41                             GtkCssStyle             *parent_style)
42 {
43   return _gtk_css_value_ref (value);
44 }
45 
46 static gboolean
gtk_css_value_rgba_equal(const GtkCssValue * rgba1,const GtkCssValue * rgba2)47 gtk_css_value_rgba_equal (const GtkCssValue *rgba1,
48                           const GtkCssValue *rgba2)
49 {
50   return gdk_rgba_equal (&rgba1->rgba, &rgba2->rgba);
51 }
52 
53 static inline double
transition(double start,double end,double progress)54 transition (double start,
55             double end,
56             double progress)
57 {
58   return start + (end - start) * progress;
59 }
60 
61 static GtkCssValue *
gtk_css_value_rgba_transition(GtkCssValue * start,GtkCssValue * end,guint property_id,double progress)62 gtk_css_value_rgba_transition (GtkCssValue *start,
63                                GtkCssValue *end,
64                                guint        property_id,
65                                double       progress)
66 {
67   GdkRGBA result;
68 
69   progress = CLAMP (progress, 0, 1);
70   result.alpha = transition (start->rgba.alpha, end->rgba.alpha, progress);
71   if (result.alpha <= 0.0)
72     {
73       result.red = result.green = result.blue = 0.0;
74     }
75   else
76     {
77       result.red = transition (start->rgba.red * start->rgba.alpha,
78                                end->rgba.red * end->rgba.alpha,
79                                progress) / result.alpha;
80       result.green = transition (start->rgba.green * start->rgba.alpha,
81                                  end->rgba.green * end->rgba.alpha,
82                                  progress) / result.alpha;
83       result.blue = transition (start->rgba.blue * start->rgba.alpha,
84                                 end->rgba.blue * end->rgba.alpha,
85                                 progress) / result.alpha;
86     }
87 
88   return _gtk_css_rgba_value_new_from_rgba (&result);
89 }
90 
91 static void
gtk_css_value_rgba_print(const GtkCssValue * rgba,GString * string)92 gtk_css_value_rgba_print (const GtkCssValue *rgba,
93                           GString           *string)
94 {
95   char *s = gdk_rgba_to_string (&rgba->rgba);
96   g_string_append (string, s);
97   g_free (s);
98 }
99 
100 static const GtkCssValueClass GTK_CSS_VALUE_RGBA = {
101   gtk_css_value_rgba_free,
102   gtk_css_value_rgba_compute,
103   gtk_css_value_rgba_equal,
104   gtk_css_value_rgba_transition,
105   gtk_css_value_rgba_print
106 };
107 
108 GtkCssValue *
_gtk_css_rgba_value_new_from_rgba(const GdkRGBA * rgba)109 _gtk_css_rgba_value_new_from_rgba (const GdkRGBA *rgba)
110 {
111   GtkCssValue *value;
112 
113   g_return_val_if_fail (rgba != NULL, NULL);
114 
115   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_RGBA);
116   value->rgba = *rgba;
117 
118   return value;
119 }
120 
121 const GdkRGBA *
_gtk_css_rgba_value_get_rgba(const GtkCssValue * rgba)122 _gtk_css_rgba_value_get_rgba (const GtkCssValue *rgba)
123 {
124   g_return_val_if_fail (rgba->class == &GTK_CSS_VALUE_RGBA, NULL);
125 
126   return &rgba->rgba;
127 }
128