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