]> git.sur5r.net Git - glabels/blob - src/svg-cache.c
Imported Upstream version 3.0.0
[glabels] / src / svg-cache.c
1 /*
2  *  svg-cache.c
3  *  Copyright (C) 2003-2009  Jim Evins <evins@snaught.com>.
4  *
5  *  This file is part of gLabels.
6  *
7  *  gLabels is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  gLabels is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with gLabels.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22
23 #include <string.h>
24
25 #include "svg-cache.h"
26
27 #include "debug.h"
28
29
30 /*========================================================*/
31 /* Private types.                                         */
32 /*========================================================*/
33
34 typedef struct {
35         gchar      *key;
36         guint       references;
37         RsvgHandle *svg_handle;
38         gchar      *contents;
39 } CacheRecord;
40
41
42 /*========================================================*/
43 /* Private globals.                                       */
44 /*========================================================*/
45
46
47 /*========================================================*/
48 /* Private function prototypes.                           */
49 /*========================================================*/
50
51 static void  record_destroy   (gpointer val);
52
53 static void  add_name_to_list (gpointer key,
54                                gpointer val,
55                                gpointer user_data);
56
57
58 /*---------------------------------------------------------------------------*/
59 /* PRIVATE.  Destroy cache record.                                           */
60 /*---------------------------------------------------------------------------*/
61 static void
62 record_destroy (gpointer val)
63 {
64         CacheRecord *record = (CacheRecord *)val;
65
66         g_return_if_fail (record);
67
68         g_free (record->key);
69         g_object_unref (record->svg_handle);
70         g_free (record->contents);
71         g_free (record);
72 }
73
74
75 /*****************************************************************************/
76 /* Create a new hash table to keep track of cached svgs.                     */
77 /*****************************************************************************/
78 GHashTable *
79 gl_svg_cache_new (void)
80 {
81         GHashTable *svg_cache;
82
83         gl_debug (DEBUG_SVG_CACHE, "START");
84
85         svg_cache = g_hash_table_new_full (g_str_hash,
86                                               g_str_equal,
87                                               NULL,
88                                               record_destroy);
89
90         gl_debug (DEBUG_SVG_CACHE, "END svg_cache=%p", svg_cache);
91
92         return svg_cache;
93 }
94
95
96 /*****************************************************************************/
97 /* Free up previously allocated hash table and its contents.                 */
98 /*****************************************************************************/
99 void
100 gl_svg_cache_free (GHashTable *svg_cache)
101 {
102         gl_debug (DEBUG_SVG_CACHE, "START");
103
104         g_hash_table_destroy (svg_cache);
105
106         gl_debug (DEBUG_SVG_CACHE, "END");
107 }
108
109
110 /*****************************************************************************/
111 /* Add svg to cache explicitly.                                              */
112 /*****************************************************************************/
113 void
114 gl_svg_cache_add_svg (GHashTable  *svg_cache,
115                       gchar       *name,
116                       const gchar *contents)
117 {
118         CacheRecord *test_record, *record;
119
120         gl_debug (DEBUG_SVG_CACHE, "START");
121
122         test_record = g_hash_table_lookup (svg_cache, name);
123         if (test_record != NULL) {
124                 /* svg is already in the cache. */
125                 gl_debug (DEBUG_SVG_CACHE, "END already in cache");
126                 return;
127         }
128
129         record = g_new0 (CacheRecord, 1);
130         record->key        = g_strdup (name);
131         record->references = 0; /* No references yet. */
132         record->svg_handle = rsvg_handle_new_from_data ((guchar *)contents, strlen(contents), NULL);
133         record->contents   = g_strdup (contents);
134
135         g_hash_table_insert (svg_cache, record->key, record);
136
137         gl_debug (DEBUG_SVG_CACHE, "END");
138 }
139
140
141 /*****************************************************************************/
142 /* Get svg handle adding a reference.  If not in cache, read it and add.     */
143 /*****************************************************************************/
144 RsvgHandle *
145 gl_svg_cache_get_handle (GHashTable *svg_cache,
146                          gchar      *name)
147 {
148         CacheRecord *record;
149         RsvgHandle  *svg_handle = NULL;
150         gchar       *buffer;
151         gsize        length;
152         GFile       *file;
153
154         gl_debug (DEBUG_SVG_CACHE, "START svg_cache=%p", svg_cache);
155
156         record = g_hash_table_lookup (svg_cache, name);
157
158         if (record != NULL)
159         {
160                 record->references++;
161                 gl_debug (DEBUG_SVG_CACHE, "references=%d", record->references);
162                 gl_debug (DEBUG_SVG_CACHE, "END cached");
163                 return record->svg_handle;
164         }
165
166
167         file = g_file_new_for_path (name);
168         if ( g_file_load_contents (file, NULL, &buffer, &length, NULL, NULL) )
169         {
170                 svg_handle = rsvg_handle_new_from_data ((guchar *)buffer, length, NULL);
171                 if ( svg_handle != NULL) {
172                         record = g_new0 (CacheRecord, 1);
173                         record->key        = g_strdup (name);
174                         record->references = 1;
175                         record->svg_handle = svg_handle;
176                         record->contents   = buffer;
177
178                         g_hash_table_insert (svg_cache, record->key, record);
179                 }
180         }
181         g_object_unref (file);
182
183         gl_debug (DEBUG_SVG_CACHE, "END");
184
185         return svg_handle;
186 }
187
188
189 /*****************************************************************************/
190 /* Get contents.   Do not add reference.                                     */
191 /*****************************************************************************/
192 gchar *
193 gl_svg_cache_get_contents (GHashTable *svg_cache,
194                            gchar      *name)
195 {
196         CacheRecord *record;
197
198         gl_debug (DEBUG_SVG_CACHE, "START svg_cache=%p", svg_cache);
199
200         record = g_hash_table_lookup (svg_cache, name);
201
202         if (record != NULL)
203         {
204                 gl_debug (DEBUG_SVG_CACHE, "references=%d", record->references);
205                 gl_debug (DEBUG_SVG_CACHE, "END cached");
206                 return g_strdup (record->contents);
207         }
208
209         gl_debug (DEBUG_SVG_CACHE, "END");
210
211         return NULL;
212 }
213
214
215 /*****************************************************************************/
216 /* Remove svg, but only if no references left.                               */
217 /*****************************************************************************/
218 void
219 gl_svg_cache_remove_svg (GHashTable *svg_cache,
220                          gchar      *name)
221 {
222         CacheRecord *record;
223
224         if (name == NULL) return;
225
226         gl_debug (DEBUG_SVG_CACHE, "START");
227
228         record = g_hash_table_lookup (svg_cache, name);
229         if (record == NULL) {
230                 gl_debug (DEBUG_SVG_CACHE, "END not in cache");
231                 return;
232         }
233
234         record->references--;
235
236         if ( record->references == 0 ) {
237                 g_hash_table_remove (svg_cache, name);
238         }
239
240         gl_debug (DEBUG_SVG_CACHE, "END");
241 }
242
243
244 /*---------------------------------------------------------------------------*/
245 /* PRIVATE.  Add a name to a GList while iterating over cache.               */
246 /*---------------------------------------------------------------------------*/
247 static void
248 add_name_to_list (gpointer key,
249                   gpointer val,
250                   gpointer user_data)
251 {
252         gchar     *name       = (gchar *)key;
253         GList     **name_list = (GList **)user_data;
254
255         gl_debug (DEBUG_SVG_CACHE, "START");
256
257         gl_debug (DEBUG_SVG_CACHE, "adding name=%s", name);
258
259         *name_list = g_list_append (*name_list, g_strdup(name));
260
261         gl_debug (DEBUG_SVG_CACHE, "END");
262 }
263
264
265 /*****************************************************************************/
266 /* Return a list of names for all svgs in the cache.                         */
267 /*****************************************************************************/
268 GList *
269 gl_svg_cache_get_name_list (GHashTable *svg_cache)
270 {
271         GList *name_list = NULL;
272
273         gl_debug (DEBUG_SVG_CACHE, "START");
274
275         g_hash_table_foreach (svg_cache, add_name_to_list, &name_list);
276
277         gl_debug (DEBUG_SVG_CACHE, "END");
278
279         return name_list;
280 }
281
282
283 /*****************************************************************************/
284 /* Free up a list of svg names.                                              */
285 /*****************************************************************************/
286 void
287 gl_svg_cache_free_name_list (GList *name_list)
288 {
289         GList *p_name;
290
291         gl_debug (DEBUG_SVG_CACHE, "START");
292
293         for (p_name = name_list; p_name != NULL; p_name = p_name->next) {
294                 g_free (p_name->data);
295                 p_name->data = NULL;
296         }
297
298         g_list_free (name_list);
299
300         gl_debug (DEBUG_SVG_CACHE, "END");
301 }
302
303
304
305
306 /*
307  * Local Variables:       -- emacs
308  * mode: C                -- emacs
309  * c-basic-offset: 8      -- emacs
310  * tab-width: 8           -- emacs
311  * indent-tabs-mode: nil  -- emacs
312  * End:                   -- emacs
313  */