1
2
3 #include <glib.h>
4 #include <gtk/gtk.h>
5 #include <math.h>
6 #include "support.h"
7 #include "globals.h"
8 #include "map_management.h"
9 #include "converter.h"
10 #include "tile_management.h"
11 #include "callbacks.h"
12 #include "friends.h"
13 #include "gps_functions.h"
14 #include "geo_photos.h"
15 #include "poi.h"
16 #include "wp.h"
17 #include "tracks.h"
18 #include "route.h"
19
20 typedef struct {
21 GdkPixbuf *pixbuf;
22 gboolean reused;
23 } tile_hash_t;
24
25
26 static GdkGC *gc_map = NULL;
27
28 static GtkWidget *drawingarea11 = NULL;
29 static GHashTable *hash_table = NULL;
30
31 void hash_destroy_key_func (gpointer data);
32 void hash_destroy_value_func (gpointer data);
33 gboolean hash_sieve_func (gpointer key, gpointer value, gpointer user_data);
34
35 void
hash_destroy_key_func(gpointer data)36 hash_destroy_key_func (gpointer data)
37 {
38 g_free(data);
39 }
40
41 void
hash_destroy_value_func(gpointer data)42 hash_destroy_value_func (gpointer data)
43 {
44 tile_hash_t *tile_hash = data;
45
46 g_object_unref(tile_hash->pixbuf);
47 g_free(data);
48 }
49
50 gboolean
hash_sieve_func(gpointer key,gpointer value,gpointer user_data)51 hash_sieve_func (gpointer key, gpointer value, gpointer user_data)
52 {
53 gboolean remove = TRUE;
54
55 tile_hash_t *tile_hash = value;
56
57 if(tile_hash->reused)
58 {
59 tile_hash->reused = FALSE;
60 remove = FALSE;
61 }
62
63 return remove;
64 }
65
66
67 void
load_tile(gchar * dir,int zoom,int x,int y,int offset_x,int offset_y)68 load_tile( gchar *dir,
69 int zoom,
70 int x,
71 int y,
72 int offset_x,
73 int offset_y)
74 {
75 int detail_zoom = global_detail_zoom; /* round (dpi/96.0) */
76 int detail_scale = (int) pow (2.0, (float) detail_zoom);
77 int overzoom = 0;
78 int upscale = 1;
79 gboolean hash_not_found = TRUE;
80 static gchar filename[256];
81 static gchar wanted_filename[256];
82
83 GdkPixbuf *pixbuf = NULL;
84 repo_t *repo;
85 tile_hash_t *tile_hash;
86
87
88 if(gc_map)
89 g_object_unref(gc_map);
90 if(pixmap)
91 {
92 gc_map = gdk_gc_new(pixmap);
93 }
94 else printf("no drawable -> NULL\n");
95
96 upscale = detail_scale;
97 zoom -= detail_zoom;
98
99 g_snprintf(wanted_filename, 255, "%s/%u/%u/%u.png", dir, zoom, x, y);
100 tile_hash = g_hash_table_lookup(hash_table, wanted_filename);
101
102 if(tile_hash)
103 {
104 pixbuf = tile_hash->pixbuf;
105
106 tile_hash->reused = TRUE;
107 hash_not_found = FALSE;
108 }
109
110 else
111 {
112
113 for(overzoom=0; overzoom<=3; overzoom++)
114 {
115 g_snprintf(filename, 255, "%s/%u/%u/%u.png", dir, zoom-overzoom, x/upscale, y/upscale);
116
117 pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
118
119 if(pixbuf)
120 break;
121
122 upscale *= 2;
123 }
124
125 if(pixbuf && upscale > 1)
126 {
127 GdkPixbuf *pixbuf_scaled = NULL;
128 pixbuf_scaled = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 256, 256);
129
130 gdk_pixbuf_scale ( pixbuf, pixbuf_scaled,
131 0, 0,
132 TILESIZE, TILESIZE,
133 -TILESIZE*(x%upscale), -TILESIZE*(y%upscale),
134 upscale, upscale,
135 GDK_INTERP_BILINEAR );
136
137 if (pixbuf) {
138 g_object_unref (pixbuf);
139 }
140
141 pixbuf = pixbuf_scaled;
142 }
143 }
144
145 if(!pixbuf)
146 {
147
148 GtkWidget *widget;
149
150 widget = lookup_widget(window1, "drawingarea1");
151
152 gdk_draw_rectangle (
153 pixmap,
154 widget->style->white_gc,
155 TRUE,
156 offset_x, offset_y,
157 256,
158 256);
159
160 gtk_widget_queue_draw_area (
161 widget,
162 offset_x,offset_y,256,256);
163 }
164
165 else
166 {
167
168 gdk_draw_pixbuf (
169 pixmap,
170 gc_map,
171 pixbuf,
172 0,0,
173 offset_x,offset_y,
174 TILESIZE,TILESIZE,
175 GDK_RGB_DITHER_NONE, 0, 0);
176
177
178 if(hash_not_found)
179 {
180 tile_hash = g_new0(tile_hash_t,1);
181 tile_hash->pixbuf = pixbuf;
182 tile_hash->reused = TRUE;
183
184 g_hash_table_insert(hash_table, g_strdup(wanted_filename), tile_hash);
185 }
186 }
187
188
189 drawingarea11 = lookup_widget(window1, "drawingarea1");
190
191 gtk_widget_queue_draw_area (
192 drawingarea11,
193 offset_x,offset_y,
194 TILESIZE,TILESIZE);
195
196 if(overzoom && global_auto_download)
197 {
198 repo = global_curr_repo->data;
199 download_tile(repo,zoom,x/detail_scale,y/detail_scale);
200 }
201 }
202
203
204
205 void
fill_tiles_pixel(int pixel_x,int pixel_y,int zoom,gboolean force_refresh)206 fill_tiles_pixel( int pixel_x,
207 int pixel_y,
208 int zoom,
209 gboolean force_refresh)
210 {
211 GtkWidget *widget;
212 int i,j, i_corrected, width, height, tile_x0, tile_y0, tiles_nx, tiles_ny;
213 int max_pixel;
214 int offset_xn = 0;
215 int offset_yn = 0;
216 int offset_x;
217 int offset_y;
218 gboolean success = FALSE;
219 repo_t *repo = global_curr_repo->data;
220
221
222 if (!hash_table)
223 {
224 hash_table = g_hash_table_new_full (g_str_hash,
225 g_str_equal,
226 hash_destroy_key_func,
227 hash_destroy_value_func);
228 }
229
230 if(force_refresh)
231 {
232 g_hash_table_remove_all(hash_table);
233 }
234
235 widget = lookup_widget(window1,"drawingarea1");
236
237
238
239 max_pixel = (int) exp2(zoom) * TILESIZE;
240
241 if(pixel_x < 0)
242 pixel_x += max_pixel;
243
244 else if (pixel_x > max_pixel)
245 pixel_x -= max_pixel;
246
247
248 offset_x = - pixel_x % TILESIZE;
249 offset_y = - pixel_y % TILESIZE;
250 if (offset_x > 0) offset_x -= 256;
251 if (offset_y > 0) offset_y -= 256;
252
253 global_x = pixel_x;
254 global_y = pixel_y;
255 global_zoom = zoom;
256
257 offset_xn = offset_x;
258 offset_yn = offset_y;
259
260 width = map_drawable->allocation.width;
261 height = map_drawable->allocation.height;
262
263 tiles_nx = floor((width - offset_x) / TILESIZE) + 1;
264 tiles_ny = floor((height - offset_y) / TILESIZE) + 1;
265
266 tile_x0 = floor((float)pixel_x / (float)TILESIZE);
267 tile_y0 = floor((float)pixel_y / (float)TILESIZE);
268
269
270
271 for (i=tile_x0; i<(tile_x0+tiles_nx); i++)
272 {
273 for (j=tile_y0; j<(tile_y0+tiles_ny); j++)
274 {
275
276
277
278
279 if(j<0 || j>=exp2(zoom))
280 {
281 gdk_draw_rectangle (
282 pixmap,
283 widget->style->white_gc,
284 TRUE,
285 offset_xn, offset_yn,
286 TILESIZE,
287 TILESIZE);
288
289 gtk_widget_queue_draw_area (
290 widget,
291 offset_xn,offset_yn,
292 TILESIZE,TILESIZE);
293 }
294 else
295 {
296 i_corrected = (i>=exp2(zoom)) ? i-exp2(zoom) : i;
297
298 load_tile(
299 repo->dir,
300 zoom,
301 i_corrected,j,
302 offset_xn,offset_yn);
303 }
304 offset_yn += TILESIZE;
305 }
306 offset_xn += TILESIZE;
307 offset_yn = offset_y;
308 }
309
310
311 g_hash_table_foreach_remove (hash_table, hash_sieve_func, NULL);
312
313
314 success = g_settings_set_int(
315 global_settings,
316 "global-x",
317 global_x);
318 success = g_settings_set_int(
319 global_settings,
320 "global-y",
321 global_y);
322 success = g_settings_set_int(
323 global_settings,
324 "global-zoom",
325 global_zoom);
326 }
327
328 void
fill_tiles_latlon(float lat,float lon,int zoom)329 fill_tiles_latlon( float lat,
330 float lon,
331 int zoom)
332 {
333 int pixel_x, pixel_y;
334
335
336 pixel_x = lon2pixel(zoom, lon);
337
338 pixel_y = lat2pixel(zoom, lat);
339
340 fill_tiles_pixel (pixel_x, pixel_y, zoom, FALSE);
341 }
342
343 void
set_mapcenter(float lat,float lon,int zoom)344 set_mapcenter( float lat,
345 float lon,
346 int zoom)
347 {
348 int pixel_x, pixel_y;
349
350 lat = deg2rad(lat);
351 lon = deg2rad(lon);
352
353
354 pixel_x = lon2pixel(zoom, lon);
355 pixel_y = lat2pixel(zoom, lat);
356
357
358 osd_speed(TRUE);
359 fill_tiles_pixel ( pixel_x - global_drawingarea_width/2,
360 pixel_y - global_drawingarea_height/2,
361 zoom, FALSE);
362 paint_track();
363 paint_loaded_track();
364 paint_friends();
365 paint_photos();
366 paint_pois();
367 paint_wp();
368 paint_route();
369 }
370