2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 typedef struct _List
{
33 /* a circular linked list, a pointer to the tail, and the tail points to the head */
34 /* this is so we can free the last */
35 static List
*queue_tail
= NULL
;
36 static int queue_count
= 0;
38 #define VIK_CONFIG_MAPCACHE_MAX_SIZE 50331648 /* 48 meggerbytes */
39 static guint32 queue_size
= 0;
42 static GHashTable
*cache
= NULL
;
44 #define HASHKEY_FORMAT_STRING "%d-%d-%d-%d-%d-%d-%.3f-%.3f"
45 #define HASHKEY_FORMAT_STRING_NOSHRINK_NOR_ALPHA "%d-%d-%d-%d-%d-"
47 void a_mapcache_init ()
49 cache
= g_hash_table_new_full ( g_str_hash
, g_str_equal
, g_free
, g_object_unref
);
52 /* returns key from head, adds on newtailkey to tail. */
53 static gchar
*list_shift_add_entry ( gchar
*newtailkey
)
55 gchar
*oldheadkey
= queue_tail
->next
->key
;
56 queue_tail
->next
->key
= newtailkey
;
57 queue_tail
= queue_tail
->next
;
61 static gchar
*list_shift ()
63 gchar
*oldheadkey
= queue_tail
->next
->key
;
64 List
*oldhead
= queue_tail
->next
;
65 queue_tail
->next
= queue_tail
->next
->next
;
70 /* adds key to tail */
71 static void list_add_entry ( gchar
*key
)
73 List
*newlist
= g_malloc ( sizeof ( List
) );
76 newlist
->next
= queue_tail
->next
;
77 queue_tail
->next
= newlist
;
80 newlist
->next
= newlist
;
85 void a_mapcache_add ( GdkPixbuf
*pixbuf
, gint x
, gint y
, gint z
, guint8 type
, guint zoom
, guint8 alpha
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
87 gchar
*key
= g_strdup_printf ( HASHKEY_FORMAT_STRING
, x
, y
, z
, type
, zoom
, alpha
, xshrinkfactor
, yshrinkfactor
);
90 /* FIXME: what if already exists? problem! */
91 g_hash_table_insert ( cache
, key
, pixbuf
);
93 queue_size
+= gdk_pixbuf_get_rowstride(pixbuf
) * gdk_pixbuf_get_height(pixbuf
);
97 if ( queue_size
> VIK_CONFIG_MAPCACHE_SIZE
) {
98 gchar
*oldkey
= list_shift_add_entry ( key
);
99 GdkPixbuf
*oldbuf
= g_hash_table_lookup ( cache
, oldkey
);
100 queue_size
-= gdk_pixbuf_get_rowstride(oldbuf
) * gdk_pixbuf_get_height(oldbuf
);
103 g_hash_table_remove ( cache
, oldkey
);
105 /* should delete BEFORE adding -- not really possible because don't know size,
106 * but you could guess size (only applic if add big file to full cache) */
109 while ( queue_size
> VIK_CONFIG_MAPCACHE_SIZE
&&
110 (queue_tail
->next
!= queue_tail
) ) { /* make sure there's more than one thing to delete */
111 oldkey
= list_shift ();
112 oldbuf
= g_hash_table_lookup ( cache
, oldkey
);
113 queue_size
-= gdk_pixbuf_get_rowstride(oldbuf
) * gdk_pixbuf_get_height(oldbuf
);
116 g_hash_table_remove ( cache
, oldkey
);
119 /* chop off 'start' etc */
121 list_add_entry ( key
);
122 /* business as usual */
125 if ( (++tmp
== 100 )) { g_print("DEBUG: queue count=%d %u\n", queue_count
, queue_size
); tmp
=0; }
128 GdkPixbuf
*a_mapcache_get ( gint x
, gint y
, gint z
, guint8 type
, guint zoom
, guint8 alpha
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
131 g_snprintf ( key
, sizeof(key
), HASHKEY_FORMAT_STRING
, x
, y
, z
, type
, zoom
, alpha
, xshrinkfactor
, yshrinkfactor
);
132 return g_hash_table_lookup ( cache
, key
);
135 void a_mapcache_remove_all_shrinkfactors ( gint x
, gint y
, gint z
, guint8 type
, guint zoom
)
138 List
*loop
= queue_tail
;
142 if ( queue_tail
== NULL
)
145 g_snprintf ( key
, sizeof(key
), HASHKEY_FORMAT_STRING_NOSHRINK_NOR_ALPHA
, x
, y
, z
, type
, zoom
);
148 /* TODO: check logic here */
151 if ( strncmp(tmp
->key
, key
, len
) == 0 )
153 g_hash_table_remove ( cache
, tmp
->key
);
154 if ( tmp
== loop
) /* we deleted the last thing in the queue! */
155 loop
= queue_tail
= NULL
;
157 loop
->next
= tmp
->next
;
158 if ( tmp
== queue_tail
)
159 queue_tail
= tmp
->next
;
167 } while ( loop
&& (loop
!= queue_tail
|| tmp
== NULL
) );
169 /* loop thru list, looking for the one, compare first whatever chars */
171 g_hash_table_remove ( cache
, key
);
174 void a_mapcache_uninit ()
176 g_hash_table_destroy ( cache
);