1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2015 Benjamin Otte <otte@gnome.org>
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 "gtkimagedefinitionprivate.h"
21 
22 #include "deprecated/gtkiconfactory.h"
23 
24 typedef struct _GtkImageDefinitionEmpty GtkImageDefinitionEmpty;
25 typedef struct _GtkImageDefinitionPixbuf GtkImageDefinitionPixbuf;
26 typedef struct _GtkImageDefinitionStock GtkImageDefinitionStock;
27 typedef struct _GtkImageDefinitionIconSet GtkImageDefinitionIconSet;
28 typedef struct _GtkImageDefinitionAnimation GtkImageDefinitionAnimation;
29 typedef struct _GtkImageDefinitionIconName GtkImageDefinitionIconName;
30 typedef struct _GtkImageDefinitionGIcon GtkImageDefinitionGIcon;
31 typedef struct _GtkImageDefinitionSurface GtkImageDefinitionSurface;
32 
33 struct _GtkImageDefinitionEmpty {
34   GtkImageType type;
35   gint ref_count;
36 };
37 
38 struct _GtkImageDefinitionPixbuf {
39   GtkImageType type;
40   gint ref_count;
41 
42   GdkPixbuf *pixbuf;
43   int scale;
44 };
45 
46 struct _GtkImageDefinitionStock {
47   GtkImageType type;
48   gint ref_count;
49 
50   char *id;
51 };
52 
53 struct _GtkImageDefinitionIconSet {
54   GtkImageType type;
55   gint ref_count;
56 
57   GtkIconSet *icon_set;
58 };
59 
60 struct _GtkImageDefinitionAnimation {
61   GtkImageType type;
62   gint ref_count;
63 
64   GdkPixbufAnimation *animation;
65   int scale;
66 };
67 
68 struct _GtkImageDefinitionIconName {
69   GtkImageType type;
70   gint ref_count;
71 
72   char *icon_name;
73 };
74 
75 struct _GtkImageDefinitionGIcon {
76   GtkImageType type;
77   gint ref_count;
78 
79   GIcon *gicon;
80 };
81 
82 struct _GtkImageDefinitionSurface {
83   GtkImageType type;
84   gint ref_count;
85 
86   cairo_surface_t *surface;
87 };
88 
89 union _GtkImageDefinition
90 {
91   GtkImageType type;
92   GtkImageDefinitionEmpty empty;
93   GtkImageDefinitionPixbuf pixbuf;
94   GtkImageDefinitionStock stock;
95   GtkImageDefinitionIconSet icon_set;
96   GtkImageDefinitionAnimation animation;
97   GtkImageDefinitionIconName icon_name;
98   GtkImageDefinitionGIcon gicon;
99   GtkImageDefinitionSurface surface;
100 };
101 
102 GtkImageDefinition *
gtk_image_definition_new_empty(void)103 gtk_image_definition_new_empty (void)
104 {
105   static GtkImageDefinitionEmpty empty = { GTK_IMAGE_EMPTY, 1 };
106 
107   return gtk_image_definition_ref ((GtkImageDefinition *) &empty);
108 }
109 
110 static inline GtkImageDefinition *
gtk_image_definition_alloc(GtkImageType type)111 gtk_image_definition_alloc (GtkImageType type)
112 {
113   static gsize sizes[] = {
114     sizeof (GtkImageDefinitionEmpty),
115     sizeof (GtkImageDefinitionPixbuf),
116     sizeof (GtkImageDefinitionStock),
117     sizeof (GtkImageDefinitionIconSet),
118     sizeof (GtkImageDefinitionAnimation),
119     sizeof (GtkImageDefinitionIconName),
120     sizeof (GtkImageDefinitionGIcon),
121     sizeof (GtkImageDefinitionSurface)
122   };
123   GtkImageDefinition *def;
124 
125   g_assert (type < G_N_ELEMENTS (sizes));
126 
127   def = g_malloc0 (sizes[type]);
128   def->type = type;
129   def->empty.ref_count = 1;
130 
131   return def;
132 }
133 
134 GtkImageDefinition *
gtk_image_definition_new_pixbuf(GdkPixbuf * pixbuf,int scale)135 gtk_image_definition_new_pixbuf (GdkPixbuf *pixbuf,
136                                  int        scale)
137 {
138   GtkImageDefinition *def;
139 
140   if (pixbuf == NULL || scale <= 0)
141     return NULL;
142 
143   def = gtk_image_definition_alloc (GTK_IMAGE_PIXBUF);
144   def->pixbuf.pixbuf = g_object_ref (pixbuf);
145   def->pixbuf.scale = scale;
146 
147   return def;
148 }
149 
150 GtkImageDefinition *
gtk_image_definition_new_stock(const char * stock_id)151 gtk_image_definition_new_stock (const char *stock_id)
152 {
153   GtkImageDefinition *def;
154 
155   if (stock_id == NULL || stock_id[0] == '\0')
156     return NULL;
157 
158   def = gtk_image_definition_alloc (GTK_IMAGE_STOCK);
159   def->stock.id = g_strdup (stock_id);
160 
161   return def;
162 }
163 
164 GtkImageDefinition *
gtk_image_definition_new_icon_set(GtkIconSet * icon_set)165 gtk_image_definition_new_icon_set (GtkIconSet *icon_set)
166 {
167   GtkImageDefinition *def;
168 
169   if (icon_set == NULL)
170     return NULL;
171 
172   def = gtk_image_definition_alloc (GTK_IMAGE_ICON_SET);
173 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
174   def->icon_set.icon_set = gtk_icon_set_ref (icon_set);
175 G_GNUC_END_IGNORE_DEPRECATIONS;
176 
177   return def;
178 }
179 
180 GtkImageDefinition *
gtk_image_definition_new_animation(GdkPixbufAnimation * animation,int scale)181 gtk_image_definition_new_animation (GdkPixbufAnimation *animation,
182                                     int                 scale)
183 {
184   GtkImageDefinition *def;
185 
186   if (animation == NULL || scale <= 0)
187     return NULL;
188 
189   def = gtk_image_definition_alloc (GTK_IMAGE_ANIMATION);
190   def->animation.animation = g_object_ref (animation);
191   def->animation.scale = scale;
192 
193   return def;
194 }
195 
196 GtkImageDefinition *
gtk_image_definition_new_icon_name(const char * icon_name)197 gtk_image_definition_new_icon_name (const char *icon_name)
198 {
199   GtkImageDefinition *def;
200 
201   if (icon_name == NULL || icon_name[0] == '\0')
202     return NULL;
203 
204   def = gtk_image_definition_alloc (GTK_IMAGE_ICON_NAME);
205   def->icon_name.icon_name = g_strdup (icon_name);
206 
207   return def;
208 }
209 
210 GtkImageDefinition *
gtk_image_definition_new_gicon(GIcon * gicon)211 gtk_image_definition_new_gicon (GIcon *gicon)
212 {
213   GtkImageDefinition *def;
214 
215   if (gicon == NULL)
216     return NULL;
217 
218   def = gtk_image_definition_alloc (GTK_IMAGE_GICON);
219   def->gicon.gicon = g_object_ref (gicon);
220 
221   return def;
222 }
223 
224 GtkImageDefinition *
gtk_image_definition_new_surface(cairo_surface_t * surface)225 gtk_image_definition_new_surface (cairo_surface_t *surface)
226 {
227   GtkImageDefinition *def;
228 
229   if (surface == NULL)
230     return NULL;
231 
232   def = gtk_image_definition_alloc (GTK_IMAGE_SURFACE);
233   def->surface.surface = cairo_surface_reference (surface);
234 
235   return def;
236 }
237 
238 GtkImageDefinition *
gtk_image_definition_ref(GtkImageDefinition * def)239 gtk_image_definition_ref (GtkImageDefinition *def)
240 {
241   def->empty.ref_count++;
242 
243   return def;
244 }
245 
246 void
gtk_image_definition_unref(GtkImageDefinition * def)247 gtk_image_definition_unref (GtkImageDefinition *def)
248 {
249   def->empty.ref_count--;
250 
251   if (def->empty.ref_count > 0)
252     return;
253 
254   switch (def->type)
255     {
256     default:
257     case GTK_IMAGE_EMPTY:
258       g_assert_not_reached ();
259       break;
260     case GTK_IMAGE_PIXBUF:
261       g_object_unref (def->pixbuf.pixbuf);
262       break;
263     case GTK_IMAGE_ANIMATION:
264       g_object_unref (def->animation.animation);
265       break;
266     case GTK_IMAGE_SURFACE:
267       cairo_surface_destroy (def->surface.surface);
268       break;
269     case GTK_IMAGE_STOCK:
270       g_free (def->stock.id);
271       break;
272     case GTK_IMAGE_ICON_SET:
273 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
274       gtk_icon_set_unref (def->icon_set.icon_set);
275 G_GNUC_END_IGNORE_DEPRECATIONS;
276       break;
277     case GTK_IMAGE_ICON_NAME:
278       g_free (def->icon_name.icon_name);
279       break;
280     case GTK_IMAGE_GICON:
281       g_object_unref (def->gicon.gicon);
282       break;
283     }
284 
285   g_free (def);
286 }
287 
288 GtkImageType
gtk_image_definition_get_storage_type(const GtkImageDefinition * def)289 gtk_image_definition_get_storage_type (const GtkImageDefinition *def)
290 {
291   return def->type;
292 }
293 
294 gint
gtk_image_definition_get_scale(const GtkImageDefinition * def)295 gtk_image_definition_get_scale (const GtkImageDefinition *def)
296 {
297   switch (def->type)
298     {
299     default:
300       g_assert_not_reached ();
301     case GTK_IMAGE_EMPTY:
302     case GTK_IMAGE_SURFACE:
303     case GTK_IMAGE_STOCK:
304     case GTK_IMAGE_ICON_SET:
305     case GTK_IMAGE_ICON_NAME:
306     case GTK_IMAGE_GICON:
307       return 1;
308     case GTK_IMAGE_PIXBUF:
309       return def->pixbuf.scale;
310     case GTK_IMAGE_ANIMATION:
311       return def->animation.scale;
312     }
313 }
314 
315 GdkPixbuf *
gtk_image_definition_get_pixbuf(const GtkImageDefinition * def)316 gtk_image_definition_get_pixbuf (const GtkImageDefinition *def)
317 {
318   if (def->type != GTK_IMAGE_PIXBUF)
319     return NULL;
320 
321   return def->pixbuf.pixbuf;
322 }
323 
324 const gchar *
gtk_image_definition_get_stock(const GtkImageDefinition * def)325 gtk_image_definition_get_stock (const GtkImageDefinition *def)
326 {
327   if (def->type != GTK_IMAGE_STOCK)
328     return NULL;
329 
330   return def->stock.id;
331 }
332 
333 GtkIconSet *
gtk_image_definition_get_icon_set(const GtkImageDefinition * def)334 gtk_image_definition_get_icon_set (const GtkImageDefinition *def)
335 {
336   if (def->type != GTK_IMAGE_ICON_SET)
337     return NULL;
338 
339   return def->icon_set.icon_set;
340 }
341 
342 GdkPixbufAnimation *
gtk_image_definition_get_animation(const GtkImageDefinition * def)343 gtk_image_definition_get_animation (const GtkImageDefinition *def)
344 {
345   if (def->type != GTK_IMAGE_ANIMATION)
346     return NULL;
347 
348   return def->animation.animation;
349 }
350 
351 const gchar *
gtk_image_definition_get_icon_name(const GtkImageDefinition * def)352 gtk_image_definition_get_icon_name (const GtkImageDefinition *def)
353 {
354   if (def->type != GTK_IMAGE_ICON_NAME)
355     return NULL;
356 
357   return def->icon_name.icon_name;
358 }
359 
360 GIcon *
gtk_image_definition_get_gicon(const GtkImageDefinition * def)361 gtk_image_definition_get_gicon (const GtkImageDefinition *def)
362 {
363   if (def->type != GTK_IMAGE_GICON)
364     return NULL;
365 
366   return def->gicon.gicon;
367 }
368 
369 cairo_surface_t *
gtk_image_definition_get_surface(const GtkImageDefinition * def)370 gtk_image_definition_get_surface (const GtkImageDefinition *def)
371 {
372   if (def->type != GTK_IMAGE_SURFACE)
373     return NULL;
374 
375   return def->surface.surface;
376 }
377