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 static guint32 queue_size
= 0;
41 static GHashTable
*cache
= NULL
;
43 static GMutex
*mc_mutex
= NULL
;
45 #define HASHKEY_FORMAT_STRING "%d-%d-%d-%d-%d-%d-%.3f-%.3f"
46 #define HASHKEY_FORMAT_STRING_NOSHRINK_NOR_ALPHA "%d-%d-%d-%d-%d-"
48 void a_mapcache_init ()
50 mc_mutex
= g_mutex_new();
51 cache
= g_hash_table_new_full ( g_str_hash
, g_str_equal
, g_free
, g_object_unref
);
54 static void cache_add(gchar
*key
, GdkPixbuf
*pixbuf
)
56 /* TODO: Check if already exists */
57 g_hash_table_insert ( cache
, key
, pixbuf
);
58 queue_size
+= gdk_pixbuf_get_rowstride(pixbuf
) * gdk_pixbuf_get_height(pixbuf
);
63 static void cache_remove(const gchar
*key
)
65 GdkPixbuf
*buf
= g_hash_table_lookup ( cache
, key
);
67 queue_size
-= gdk_pixbuf_get_rowstride(buf
) * gdk_pixbuf_get_height(buf
);
70 g_hash_table_remove ( cache
, key
);
74 /* returns key from head, adds on newtailkey to tail. */
75 static gchar
*list_shift_add_entry ( gchar
*newtailkey
)
77 gchar
*oldheadkey
= queue_tail
->next
->key
;
78 queue_tail
->next
->key
= newtailkey
;
79 queue_tail
= queue_tail
->next
;
83 static gchar
*list_shift ()
85 gchar
*oldheadkey
= queue_tail
->next
->key
;
86 List
*oldhead
= queue_tail
->next
;
87 queue_tail
->next
= queue_tail
->next
->next
;
92 /* adds key to tail */
93 static void list_add_entry ( gchar
*key
)
95 List
*newlist
= g_malloc ( sizeof ( List
) );
98 newlist
->next
= queue_tail
->next
;
99 queue_tail
->next
= newlist
;
100 queue_tail
= newlist
;
102 newlist
->next
= newlist
;
103 queue_tail
= newlist
;
107 void a_mapcache_add ( GdkPixbuf
*pixbuf
, gint x
, gint y
, gint z
, guint8 type
, guint zoom
, guint8 alpha
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
109 gchar
*key
= g_strdup_printf ( HASHKEY_FORMAT_STRING
, x
, y
, z
, type
, zoom
, alpha
, xshrinkfactor
, yshrinkfactor
);
112 g_mutex_lock(mc_mutex
);
113 cache_add(key
, pixbuf
);
115 if ( queue_size
> VIK_CONFIG_MAPCACHE_SIZE
) {
116 gchar
*oldkey
= list_shift_add_entry ( key
);
117 cache_remove(oldkey
);
119 while ( queue_size
> VIK_CONFIG_MAPCACHE_SIZE
&&
120 (queue_tail
->next
!= queue_tail
) ) { /* make sure there's more than one thing to delete */
121 oldkey
= list_shift ();
122 cache_remove(oldkey
);
125 /* chop off 'start' etc */
127 list_add_entry ( key
);
128 /* business as usual */
130 g_mutex_unlock(mc_mutex
);
132 if ( (++tmp
== 100 )) { g_print("DEBUG: queue count=%d %u\n", queue_count
, queue_size
); tmp
=0; }
135 GdkPixbuf
*a_mapcache_get ( gint x
, gint y
, gint z
, guint8 type
, guint zoom
, guint8 alpha
, gdouble xshrinkfactor
, gdouble yshrinkfactor
)
138 g_snprintf ( key
, sizeof(key
), HASHKEY_FORMAT_STRING
, x
, y
, z
, type
, zoom
, alpha
, xshrinkfactor
, yshrinkfactor
);
139 return g_hash_table_lookup ( cache
, key
);
142 void a_mapcache_remove_all_shrinkfactors ( gint x
, gint y
, gint z
, guint8 type
, guint zoom
)
145 List
*loop
= queue_tail
;
149 if ( queue_tail
== NULL
)
152 g_snprintf ( key
, sizeof(key
), HASHKEY_FORMAT_STRING_NOSHRINK_NOR_ALPHA
, x
, y
, z
, type
, zoom
);
155 g_mutex_lock(mc_mutex
);
156 /* TODO: check logic here */
159 if ( strncmp(tmp
->key
, key
, len
) == 0 )
161 cache_remove(tmp
->key
);
162 if ( tmp
== loop
) /* we deleted the last thing in the queue! */
163 loop
= queue_tail
= NULL
;
165 loop
->next
= tmp
->next
;
166 if ( tmp
== queue_tail
)
167 queue_tail
= tmp
->next
;
175 } while ( loop
&& (loop
!= queue_tail
|| tmp
== NULL
) );
177 /* loop thru list, looking for the one, compare first whatever chars */
179 g_mutex_unlock(mc_mutex
);
182 void a_mapcache_uninit ()
184 g_hash_table_destroy ( cache
);