1 /*
2  * overviewcolor.c - This file is part of the Geany Overview plugin
3  *
4  * Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  *
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26 
27 #include "overviewcolor.h"
28 #include <string.h>
29 
30 OverviewColor *
overview_color_copy(OverviewColor * color)31 overview_color_copy (OverviewColor *color)
32 {
33   OverviewColor *new_color = g_slice_new0 (OverviewColor);
34   memcpy (new_color, color, sizeof (OverviewColor));
35   return new_color;
36 }
37 
38 void
overview_color_free(OverviewColor * color)39 overview_color_free (OverviewColor *color)
40 {
41   if (color != NULL)
42     g_slice_free (OverviewColor, color);
43 }
44 
45 gboolean
overview_color_equal(const OverviewColor * color1,const OverviewColor * color2)46 overview_color_equal (const OverviewColor *color1,
47                       const OverviewColor *color2)
48 {
49   return (color1->red   == color2->red &&
50           color1->green == color2->green &&
51           color1->blue  == color2->blue &&
52           color1->alpha == color2->alpha);
53 }
54 
55 gboolean
overview_color_parse(OverviewColor * color,const gchar * color_str)56 overview_color_parse (OverviewColor *color,
57                       const gchar   *color_str)
58 {
59   g_return_val_if_fail (color != NULL, FALSE);
60   g_return_val_if_fail (color_str != NULL, FALSE);
61 
62 #if GTK_CHECK_VERSION (3, 0, 0)
63   GdkRGBA gcolor;
64   if (gdk_rgba_parse (&gcolor, color_str))
65     {
66       overview_color_from_rgba (color, &gcolor);
67       return TRUE;
68     }
69 #else
70   GdkColor gcolor;
71   if (gdk_color_parse (color_str, &gcolor))
72     {
73       overview_color_from_gdk_color (color, &gcolor, 1.0);
74       return TRUE;
75     }
76 #endif
77 
78   return FALSE;
79 }
80 
81 gchar *
overview_color_to_string(const OverviewColor * color)82 overview_color_to_string (const OverviewColor *color)
83 {
84   g_return_val_if_fail (color != NULL, NULL);
85 
86 #if GTK_CHECK_VERSION (3, 0, 0)
87   GdkRGBA gcolor;
88   overview_color_to_rgba (color, &gcolor);
89   return gdk_rgba_to_string (&gcolor);
90 #else
91   GdkColor gcolor;
92   overview_color_to_gdk_color (color, &gcolor);
93   return gdk_color_to_string (&gcolor);
94 #endif
95 }
96 
97 void
overview_color_from_gdk_color(OverviewColor * color,const GdkColor * gcolor,gdouble alpha)98 overview_color_from_gdk_color (OverviewColor  *color,
99                                const GdkColor *gcolor,
100                                gdouble         alpha)
101 {
102   g_return_if_fail (color != NULL);
103   g_return_if_fail (gcolor != NULL);
104 
105   color->red   = (gdouble) gcolor->red / G_MAXUINT16;
106   color->green = (gdouble) gcolor->green / G_MAXUINT16;
107   color->blue  = (gdouble) gcolor->blue / G_MAXUINT16;
108   color->alpha = alpha;
109 }
110 
111 void
overview_color_to_gdk_color(const OverviewColor * color,GdkColor * gcolor)112 overview_color_to_gdk_color (const OverviewColor *color,
113                              GdkColor            *gcolor)
114 {
115   g_return_if_fail (color != NULL);
116   g_return_if_fail (gcolor != NULL);
117 
118   gcolor->red   = (guint16)(color->red * G_MAXUINT16);
119   gcolor->green = (guint16)(color->green * G_MAXUINT16);
120   gcolor->blue  = (guint16)(color->blue * G_MAXUINT16);
121 }
122 
123 #if GTK_CHECK_VERSION (3, 0, 0)
124 void
overview_color_from_rgba(OverviewColor * color,const GdkRGBA * rgba)125 overview_color_from_rgba (OverviewColor *color,
126                           const GdkRGBA *rgba)
127 {
128   g_return_if_fail (color != NULL);
129   g_return_if_fail (rgba != NULL);
130 
131   color->red   = rgba->red;
132   color->green = rgba->green;
133   color->blue  = rgba->blue;
134   color->alpha = rgba->alpha;
135 }
136 
137 void
overview_color_to_rgba(const OverviewColor * color,GdkRGBA * rgba)138 overview_color_to_rgba (const OverviewColor *color,
139                         GdkRGBA             *rgba)
140 {
141   g_return_if_fail (color != NULL);
142   g_return_if_fail (rgba != NULL);
143 
144   rgba->red   = color->red;
145   rgba->green = color->green;
146   rgba->blue  = color->blue;
147   rgba->alpha = color->alpha;
148 }
149 #endif
150 
151 void
overview_color_from_int(OverviewColor * color,guint32 abgr,gboolean with_alpha)152 overview_color_from_int (OverviewColor *color,
153                          guint32        abgr,
154                          gboolean       with_alpha)
155 {
156   g_return_if_fail (color != NULL);
157   guint8 r = abgr & 0xFF;
158   guint8 g = (abgr>>8) & 0xFF;
159   guint8 b = (abgr>>16) & 0xFF;
160   guint8 a = 255;
161 
162   if (with_alpha)
163     a = (abgr>>24) & 0xFF;
164 
165   color->red   = (gdouble)r / G_MAXUINT8;
166   color->green = (gdouble)g / G_MAXUINT8;
167   color->blue  = (gdouble)b / G_MAXUINT8;
168   color->alpha = (gdouble)a / G_MAXUINT8;
169 }
170 
171 guint32
overview_color_to_int(const OverviewColor * color,gboolean with_alpha)172 overview_color_to_int (const OverviewColor *color,
173                        gboolean             with_alpha)
174 {
175   g_return_val_if_fail (color != NULL, 0);
176 
177   guint32 r = (guint8)(color->red * 255.0);
178   guint32 g = (guint8)(color->green * 255.0);
179   guint32 b = (guint8)(color->blue * 255.0);
180   guint32 a = 0;
181 
182   if (with_alpha)
183     a = (guint8)(color->alpha * 255.0);
184 
185   return (a<<24) | (b<<16) | (g<<8) | r;
186 }
187 
188 gboolean
overview_color_from_keyfile(OverviewColor * color,GKeyFile * keyfile,const gchar * section,const gchar * option,GError ** error)189 overview_color_from_keyfile   (OverviewColor *color,
190                                GKeyFile      *keyfile,
191                                const gchar   *section,
192                                const gchar   *option,
193                                GError       **error)
194 {
195   gchar  *color_key;
196   gchar  *alpha_key;
197   gchar  *clr_str;
198   gdouble alpha;
199 
200   g_return_val_if_fail (color != NULL, FALSE);
201   g_return_val_if_fail (keyfile != NULL, FALSE);
202   g_return_val_if_fail (section != NULL, FALSE);
203   g_return_val_if_fail (option != NULL, FALSE);
204 
205   color_key = g_strdup_printf ("%s-color", option);
206   alpha_key = g_strdup_printf ("%s-alpha", option);
207 
208   clr_str = g_key_file_get_string (keyfile, section, color_key, error);
209   if (*error != NULL)
210     {
211       g_free (color_key);
212       g_free (alpha_key);
213       return FALSE;
214     }
215 
216   g_free (color_key);
217 
218   alpha = g_key_file_get_double (keyfile, section, alpha_key, error);
219   if (*error != NULL)
220     {
221       g_free (alpha_key);
222       g_free (clr_str);
223       return FALSE;
224     }
225 
226   g_free (alpha_key);
227 
228   if (alpha < 0.0 || alpha > 1.0)
229     g_warning ("alpha value '%g' from keyfile out of 0-1 range", alpha);
230 
231   overview_color_parse (color, clr_str);
232   color->alpha = alpha;
233 
234   g_free (clr_str);
235 
236   return TRUE;
237 }
238 
239 gboolean
overview_color_to_keyfile(const OverviewColor * color,GKeyFile * keyfile,const gchar * section,const gchar * option)240 overview_color_to_keyfile (const OverviewColor *color,
241                            GKeyFile            *keyfile,
242                            const gchar         *section,
243                            const gchar         *option)
244 {
245   gchar *color_key;
246   gchar *alpha_key;
247   gchar *clr_str;
248 
249   g_return_val_if_fail (color != NULL, FALSE);
250   g_return_val_if_fail (keyfile != NULL, FALSE);
251   g_return_val_if_fail (section != NULL, FALSE);
252   g_return_val_if_fail (option != NULL, FALSE);
253 
254   color_key = g_strdup_printf ("%s-color", option);
255   alpha_key = g_strdup_printf ("%s-alpha", option);
256 
257   clr_str = overview_color_to_string (color);
258   g_key_file_set_string (keyfile, section, color_key, clr_str);
259   g_free (color_key);
260   g_free (clr_str);
261 
262   g_key_file_set_double (keyfile, section, alpha_key, color->alpha);
263   g_free (alpha_key);
264 
265   return TRUE;
266 }
267 
268 void
overview_color_from_color_button(OverviewColor * color,GtkColorButton * button)269 overview_color_from_color_button (OverviewColor  *color,
270                                   GtkColorButton *button)
271 {
272   GdkColor gcolor;
273   guint16  alpha;
274   gdouble  falpha;
275   gtk_color_button_get_color (button, &gcolor);
276   alpha = gtk_color_button_get_alpha (button);
277   falpha = (gdouble) alpha / (gdouble) G_MAXUINT16;
278   overview_color_from_gdk_color (color, &gcolor, falpha);
279 }
280 
281 void
overview_color_to_color_button(const OverviewColor * color,GtkColorButton * button)282 overview_color_to_color_button (const OverviewColor *color,
283                                 GtkColorButton      *button)
284 {
285   GdkColor gcolor;
286   guint16  alpha;
287   overview_color_to_gdk_color (color, &gcolor);
288   gtk_color_button_set_color (button, &gcolor);
289   alpha = (guint16)(color->alpha * (gdouble) G_MAXUINT16);
290   gtk_color_button_set_alpha (button, alpha);
291 }
292 
293 GType
overview_color_get_type(void)294 overview_color_get_type (void)
295 {
296   static GType type = 0;
297   if (type == 0)
298     {
299       type =
300         g_boxed_type_register_static ("OverviewColor",
301                                       (GBoxedCopyFunc) overview_color_copy,
302                                       (GBoxedFreeFunc) overview_color_free);
303     }
304   return type;
305 }
306