Fix:gui_internal:Next round of improvements
[navit-package] / navit / graphics.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 //##############################################################################################################
21 //#
22 //# File: graphics.c
23 //# Description: 
24 //# Comment: 
25 //# Authors: Martin Schaller (04/2008)
26 //#
27 //##############################################################################################################
28
29 #include <glib.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 #include "debug.h"
34 #include "string.h"
35 #include "draw_info.h"
36 #include "point.h"
37 #include "graphics.h"
38 #include "projection.h"
39 #include "map.h"
40 #include "coord.h"
41 #include "transform.h"
42 #include "plugin.h"
43 #include "profile.h"
44 #include "mapset.h"
45 #include "layout.h"
46 #include "route.h"
47 #include "util.h"
48
49 //##############################################################################################################
50 //# Description: 
51 //# Comment: 
52 //# Authors: Martin Schaller (04/2008)
53 //##############################################################################################################
54 struct graphics
55 {
56         struct graphics_priv *priv;
57         struct graphics_methods meth;
58         struct graphics_font *font[16];
59         struct graphics_gc *gc[3];
60         struct attr **attrs;
61         int ready;
62 };
63 //##############################################################################################################
64 //# Description: 
65 //# Comment: 
66 //# Authors: Martin Schaller (04/2008)
67 //##############################################################################################################
68 struct displaylist {
69         GHashTable *dl;
70 };
71 //##############################################################################################################
72 //# Description: Creates a new graphics object
73 //# Comment: attr type required
74 //# Authors: Martin Schaller (04/2008)
75 //##############################################################################################################
76 struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
77 {
78         struct graphics *this_;
79         struct attr *type_attr;
80         struct graphics_priv * (*graphicstype_new)(struct graphics_methods *meth, struct attr **attrs);
81
82         if (! (type_attr=attr_search(attrs, NULL, attr_type))) {
83                 return NULL;
84         }
85
86         graphicstype_new=plugin_get_graphics_type(type_attr->u.str);
87         if (! graphicstype_new)
88                 return NULL;
89         this_=g_new0(struct graphics, 1);
90         this_->priv=(*graphicstype_new)(&this_->meth, attrs);
91         this_->attrs=attr_list_dup(attrs);
92         return this_;
93 }
94
95 //##############################################################################################################
96 //# Description: 
97 //# Comment: 
98 //# Authors: Martin Schaller (04/2008)
99 //##############################################################################################################
100 int graphics_get_attr(struct graphics *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
101 {
102         return attr_generic_get_attr(this_->attrs, type, attr, iter);
103 }
104
105 //##############################################################################################################
106 //# Description: 
107 //# Comment: 
108 //# Authors: Martin Schaller (04/2008)
109 //##############################################################################################################
110 struct graphics * graphics_overlay_new(struct graphics *parent, struct point *p, int w, int h)
111 {
112         struct graphics *this_;
113         this_=g_new0(struct graphics, 1);
114         this_->priv=parent->meth.overlay_new(parent->priv, &this_->meth, p, w, h);
115         return this_;
116 }
117
118 //##############################################################################################################
119 //# Description: 
120 //# Comment: 
121 //# Authors: Martin Schaller (04/2008)
122 //##############################################################################################################
123 void graphics_init(struct graphics *this_)
124 {
125         this_->gc[0]=graphics_gc_new(this_);
126         graphics_gc_set_background(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 });
127         graphics_gc_set_foreground(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 });
128         this_->gc[1]=graphics_gc_new(this_);
129         graphics_gc_set_background(this_->gc[1], &(struct color) { 0x0000, 0x0000, 0x0000 });
130         graphics_gc_set_foreground(this_->gc[1], &(struct color) { 0xffff, 0xffff, 0xffff });
131         this_->gc[2]=graphics_gc_new(this_);
132         graphics_gc_set_background(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff });
133         graphics_gc_set_foreground(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff });
134         this_->meth.background_gc(this_->priv, this_->gc[0]->priv);
135 }
136
137 //##############################################################################################################
138 //# Description: 
139 //# Comment: 
140 //# Authors: Martin Schaller (04/2008)
141 //##############################################################################################################
142 void * graphics_get_data(struct graphics *this_, char *type)
143 {
144         return (this_->meth.get_data(this_->priv, type));
145 }
146
147 //##############################################################################################################
148 //# Description: 
149 //# Comment: 
150 //# Authors: Martin Schaller (04/2008)
151 //##############################################################################################################
152 void graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data)
153 {
154         this_->meth.register_resize_callback(this_->priv, callback, data);
155 }
156
157 //##############################################################################################################
158 //# Description: 
159 //# Comment: Called in navit.c
160 //# Authors: Martin Schaller (04/2008)
161 //##############################################################################################################
162 void graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data)
163 {
164         this_->meth.register_button_callback(this_->priv, callback, data);
165 }
166
167 //##############################################################################################################
168 //# Description: 
169 //# Comment: 
170 //# Authors: Martin Schaller (04/2008)
171 //##############################################################################################################
172 void graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data)
173 {
174         this_->meth.register_motion_callback(this_->priv, callback, data);
175 }
176
177 //##############################################################################################################
178 //# Description: 
179 //# Comment: 
180 //# Authors: Martin Schaller (04/2008)
181 //##############################################################################################################
182 struct graphics_font * graphics_font_new(struct graphics *gra, int size, int flags)
183 {
184         struct graphics_font *this_;
185
186         this_=g_new0(struct graphics_font,1);
187         this_->priv=gra->meth.font_new(gra->priv, &this_->meth, size, flags);
188         return this_;
189 }
190
191 //##############################################################################################################
192 //# Description: 
193 //# Comment: 
194 //# Authors: Martin Schaller (04/2008)
195 //##############################################################################################################
196 struct graphics_gc * graphics_gc_new(struct graphics *gra)
197 {
198         struct graphics_gc *this_;
199
200         this_=g_new0(struct graphics_gc,1);
201         this_->priv=gra->meth.gc_new(gra->priv, &this_->meth);
202         return this_;
203 }
204
205 //##############################################################################################################
206 //# Description: 
207 //# Comment: 
208 //# Authors: Martin Schaller (04/2008)
209 //##############################################################################################################
210 void graphics_gc_destroy(struct graphics_gc *gc)
211 {
212         gc->meth.gc_destroy(gc->priv);
213         g_free(gc);
214 }
215
216 //##############################################################################################################
217 //# Description: 
218 //# Comment: 
219 //# Authors: Martin Schaller (04/2008)
220 //##############################################################################################################
221 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
222 {
223         gc->meth.gc_set_foreground(gc->priv, c);
224 }
225
226 //##############################################################################################################
227 //# Description: 
228 //# Comment: 
229 //# Authors: Martin Schaller (04/2008)
230 //##############################################################################################################
231 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
232 {
233         gc->meth.gc_set_background(gc->priv, c);
234 }
235
236 //##############################################################################################################
237 //# Description: 
238 //# Comment: 
239 //# Authors: Martin Schaller (04/2008)
240 //##############################################################################################################
241 void graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
242 {
243         gc->meth.gc_set_linewidth(gc->priv, width);
244 }
245
246 //##############################################################################################################
247 //# Description: 
248 //# Comment: 
249 //# Authors: Martin Schaller (04/2008)
250 //##############################################################################################################
251 void graphics_gc_set_dashes(struct graphics_gc *gc, int width, int offset, unsigned char dash_list[], int n)
252 {
253         if (gc->meth.gc_set_dashes)
254                 gc->meth.gc_set_dashes(gc->priv, width, offset, dash_list, n);
255 }
256
257 //##############################################################################################################
258 //# Description: Create a new image from file path scaled to w and h pixels
259 //# Comment: 
260 //# Authors: Martin Schaller (04/2008)
261 //##############################################################################################################
262 struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *path, int w, int h)
263 {
264         struct graphics_image *this_;
265
266         this_=g_new0(struct graphics_image,1);
267         this_->height=h;
268         this_->width=w;
269         this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot);
270         if (! this_->priv) {
271                 g_free(this_);
272                 this_=NULL;
273         }
274         return this_;
275 }
276
277 //##############################################################################################################
278 //# Description: Create a new image from file path
279 //# Comment: 
280 //# Authors: Martin Schaller (04/2008)
281 //##############################################################################################################
282 struct graphics_image * graphics_image_new(struct graphics *gra, char *path)
283 {
284         return graphics_image_new_scaled(gra, path, -1, -1);
285 }
286
287 //##############################################################################################################
288 //# Description: 
289 //# Comment: 
290 //# Authors: Martin Schaller (04/2008)
291 //##############################################################################################################
292 void graphics_image_free(struct graphics *gra, struct graphics_image *img)
293 {
294         if (gra->meth.image_free)
295                 gra->meth.image_free(gra->priv, img->priv);
296         g_free(img);
297 }
298
299 //##############################################################################################################
300 //# Description: 
301 //# Comment: 
302 //# Authors: Martin Schaller (04/2008)
303 //##############################################################################################################
304 void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
305 {
306         this_->meth.draw_restore(this_->priv, p, w, h);
307 }
308
309 //##############################################################################################################
310 //# Description: 
311 //# Comment: 
312 //# Authors: Martin Schaller (04/2008)
313 //##############################################################################################################
314 void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
315 {
316         this_->meth.draw_mode(this_->priv, mode);
317 }
318
319 //##############################################################################################################
320 //# Description: 
321 //# Comment: 
322 //# Authors: Martin Schaller (04/2008)
323 //##############################################################################################################
324 void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
325 {
326         this_->meth.draw_lines(this_->priv, gc->priv, p, count);
327 }
328
329 //##############################################################################################################
330 //# Description: 
331 //# Comment: 
332 //# Authors: Martin Schaller (04/2008)
333 //##############################################################################################################
334 void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
335 {
336         this_->meth.draw_circle(this_->priv, gc->priv, p, r);
337 }
338
339 //##############################################################################################################
340 //# Description: 
341 //# Comment: 
342 //# Authors: Martin Schaller (04/2008)
343 //##############################################################################################################
344 void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
345 {
346         this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
347 }
348
349 //##############################################################################################################
350 //# Description: 
351 //# Comment: 
352 //# Authors: Martin Schaller (04/2008)
353 //##############################################################################################################
354 void graphics_draw_text(struct graphics *this_, struct graphics_gc *gc1, struct graphics_gc *gc2, struct graphics_font *font, char *text, struct point *p, int dx, int dy)
355 {
356         this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy);
357 }
358
359 //##############################################################################################################
360 //# Description: 
361 //# Comment: 
362 //# Authors: Martin Schaller (04/2008)
363 //##############################################################################################################
364 void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret)
365 {
366         this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret);
367 }
368
369 //##############################################################################################################
370 //# Description: 
371 //# Comment: 
372 //# Authors: Martin Schaller (04/2008)
373 //##############################################################################################################
374 void graphics_overlay_disable(struct graphics *this_, int disable)
375 {
376         if (this_->meth.overlay_disable)
377                 this_->meth.overlay_disable(this_->priv, disable);
378 }
379
380 //##############################################################################################################
381 //# Description: 
382 //# Comment: 
383 //# Authors: Martin Schaller (04/2008)
384 //##############################################################################################################
385 void graphics_draw_image(struct graphics *this_, struct graphics_gc *gc, struct point *p, struct graphics_image *img)
386 {
387         this_->meth.draw_image(this_->priv, gc->priv, p, img->priv);
388 }
389
390 #include "attr.h"
391 #include "popup.h"
392 #include <stdio.h>
393
394
395 #if 0
396 //##############################################################################################################
397 //# Description: 
398 //# Comment: 
399 //# Authors: Martin Schaller (04/2008)
400 //##############################################################################################################
401 static void popup_view_html(struct popup_item *item, char *file)
402 {
403         char command[1024];
404         sprintf(command,"firefox %s", file);
405         system(command);
406 }
407
408 //##############################################################################################################
409 //# Description: 
410 //# Comment: 
411 //# Authors: Martin Schaller (04/2008)
412 //##############################################################################################################
413 static void graphics_popup(struct display_list *list, struct popup_item **popup)
414 {
415         struct item *item;
416         struct attr attr;
417         struct map_rect *mr;
418         struct coord c;
419         struct popup_item *curr_item,*last=NULL;
420         item=list->data;
421         mr=map_rect_new(item->map, NULL, NULL, 0);
422         printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
423         item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
424         if (item) {
425                 if (item_attr_get(item, attr_name, &attr)) {
426                         curr_item=popup_item_new_text(popup,attr.u.str,1);
427                         if (item_attr_get(item, attr_info_html, &attr)) {
428                                 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
429                         }
430                         if (item_attr_get(item, attr_price_html, &attr)) {
431                                 popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
432                         }
433                         curr_item->submenu=last;
434                 }
435         }
436         map_rect_destroy(mr);
437 }
438 #endif
439
440 //##############################################################################################################
441 //# Description: 
442 //# Comment: 
443 //# Authors: Martin Schaller (04/2008)
444 //##############################################################################################################
445 struct displayitem {
446         struct item item;
447         char *label;
448         int displayed;
449         int count;
450         struct point pnt[0];
451 };
452
453 //##############################################################################################################
454 //# Description: 
455 //# Comment: 
456 //# Authors: Martin Schaller (04/2008)
457 //##############################################################################################################
458 static int xdisplay_free_list(gpointer key, gpointer value, gpointer user_data)
459 {
460         GList *h, *l;
461         h=value;
462         l=h;
463         while (l) {
464                 struct displayitem *di=l->data;
465                 if (! di->displayed && di->item.type < type_line) 
466                         dbg(1,"warning: item '%s' not displayed\n", item_to_name(di->item.type));
467                 g_free(l->data);
468                 l=g_list_next(l);
469         }
470         g_list_free(h);
471         return TRUE;
472 }
473
474 //##############################################################################################################
475 //# Description: 
476 //# Comment: 
477 //# Authors: Martin Schaller (04/2008)
478 //##############################################################################################################
479 static void xdisplay_free(GHashTable *display_list)
480 {
481         g_hash_table_foreach_remove(display_list, xdisplay_free_list, NULL);
482 }
483
484 //##############################################################################################################
485 //# Description: 
486 //# Comment: 
487 //# Authors: Martin Schaller (04/2008)
488 //##############################################################################################################
489 void display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label)
490 {
491         struct displayitem *di;
492         int len;
493         GList *l;
494         char *p;
495
496         len=sizeof(*di)+count*sizeof(*pnt);
497         if (label)
498                 len+=strlen(label)+1;
499
500         p=g_malloc(len);
501
502         di=(struct displayitem *)p;
503         di->displayed=0;
504         p+=sizeof(*di)+count*sizeof(*pnt);
505         di->item=*item;
506         if (label) {
507                 di->label=p;
508                 strcpy(di->label, label);
509         } else 
510                 di->label=NULL;
511         di->count=count;
512         memcpy(di->pnt, pnt, count*sizeof(*pnt));
513
514         l=g_hash_table_lookup(displaylist->dl, GINT_TO_POINTER(item->type));
515         l=g_list_prepend(l, di);
516         g_hash_table_insert(displaylist->dl, GINT_TO_POINTER(item->type), l);
517 }
518
519
520 //##############################################################################################################
521 //# Description: 
522 //# Comment: 
523 //# Authors: Martin Schaller (04/2008)
524 //##############################################################################################################
525 static void label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label)
526 {
527         int i,x,y,tl;
528         double dx,dy,l;
529         struct point p_t;
530
531         tl=strlen(label)*400;
532         for (i = 0 ; i < count-1 ; i++) {
533                 dx=p[i+1].x-p[i].x;
534                 dx*=100;
535                 dy=p[i+1].y-p[i].y;
536                 dy*=100;
537                 l=(int)sqrt((float)(dx*dx+dy*dy));
538                 if (l > tl) {
539                         x=p[i].x;
540                         y=p[i].y;
541                         if (dx < 0) {
542                                 dx=-dx;
543                                 dy=-dy;
544                                 x=p[i+1].x;
545                                 y=p[i+1].y;
546                         }
547                         x+=(l-tl)*dx/l/200;
548                         y+=(l-tl)*dy/l/200;
549                         x-=dy*45/l/10;
550                         y+=dx*45/l/10;
551                         p_t.x=x;
552                         p_t.y=y;
553         #if 0
554                         printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
555         #endif
556                         gra->meth.draw_text(gra->priv, fg->priv, bg->priv, font->priv, label, &p_t, dx*0x10000/l, dy*0x10000/l);
557                 }
558         }
559 }
560
561 //##############################################################################################################
562 //# Description: 
563 //# Comment: 
564 //# Authors: Martin Schaller (04/2008)
565 //##############################################################################################################
566 static void xdisplay_draw_elements(struct graphics *gra, GHashTable *display_list, struct itemtype *itm)
567 {
568         struct element *e;
569         GList *l,*ls,*es,*types;
570         enum item_type type;
571         struct graphics_gc *gc = NULL;
572         struct graphics_image *img;
573         struct point p;
574
575         es=itm->elements;
576         while (es) {
577                 e=es->data;
578                 types=itm->type;
579                 while (types) {
580                         type=GPOINTER_TO_INT(types->data);
581                         ls=g_hash_table_lookup(display_list, GINT_TO_POINTER(type));
582                         l=ls;
583                         if (gc)
584                                 graphics_gc_destroy(gc);
585                         gc=NULL;
586                         img=NULL;
587                         while (l) {
588                                 struct displayitem *di;
589                                 di=l->data;
590                                 di->displayed=1;
591                                 if (! gc) {
592                                         gc=graphics_gc_new(gra);
593                                         gc->meth.gc_set_foreground(gc->priv, &e->color);
594                                 }
595                                 switch (e->type) {
596                                 case element_polygon:
597                                         gra->meth.draw_polygon(gra->priv, gc->priv, di->pnt, di->count);
598                                         break;
599                                 case element_polyline:
600                                         if (e->u.polyline.width > 1) 
601                                                 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
602                                         if (e->u.polyline.width > 0 && e->u.polyline.dash_num > 0)
603                                                 graphics_gc_set_dashes(gc, e->u.polyline.width, 0,
604                                                                        e->u.polyline.dash_table,
605                                                                        e->u.polyline.dash_num);
606                                         gra->meth.draw_lines(gra->priv, gc->priv, di->pnt, di->count);
607                                         break;
608                                 case element_circle:
609                                         if (e->u.circle.width > 1) 
610                                                 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
611                                         gra->meth.draw_circle(gra->priv, gc->priv, &di->pnt[0], e->u.circle.radius);
612                                         if (di->label && e->label_size) {
613                                                 p.x=di->pnt[0].x+3;
614                                                 p.y=di->pnt[0].y+10;
615                                                 if (! gra->font[e->label_size])
616                                                         gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20, 0);
617                                                 gra->meth.draw_text(gra->priv, gra->gc[2]->priv, gra->gc[1]->priv, gra->font[e->label_size]->priv, di->label, &p, 0x10000, 0);
618                                         }
619                                         break;
620                                 case element_label:
621                                         if (di->label) {
622                                                 if (! gra->font[e->label_size])
623                                                         gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20, 0);
624                                                 label_line(gra, gra->gc[2], gra->gc[1], gra->font[e->label_size], di->pnt, di->count, di->label);
625                                         }
626                                         break;
627                                 case element_icon:
628                                         if (!img) {
629                                                 char *icon=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"), "/xpm/", e->u.icon.src, NULL);
630                                                 img=graphics_image_new(gra, icon);
631                                                 g_free(icon);
632                                                 if (! img)
633                                                         g_warning("failed to load icon '%s'\n", e->u.icon.src);
634                                         }
635                                         if (img) {
636                                                 p.x=di->pnt[0].x - img->hot.x;
637                                                 p.y=di->pnt[0].y - img->hot.y;
638                                                 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
639                                                 graphics_image_free(gra, img);
640                                                 img = NULL;
641                                         }
642                                         break;
643                                 case element_image:
644                                         dbg(1,"image: '%s'\n", di->label);
645                                         if (gra->meth.draw_image_warp)
646                                                 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, di->pnt, di->count, di->label);
647                                         else
648                                                 dbg(0,"draw_image_warp not supported by graphics driver drawing '%s'\n", di->label);
649                                         break;
650                                 default:
651                                         printf("Unhandled element type %d\n", e->type);
652                                 
653                                 }
654                                 l=g_list_next(l);
655                         }
656                         types=g_list_next(types);
657                 }
658                 es=g_list_next(es);
659         }
660         if (gc)
661                 graphics_gc_destroy(gc);
662 }
663
664 //##############################################################################################################
665 //# Description: 
666 //# Comment: 
667 //# Authors: Martin Schaller (04/2008)
668 //##############################################################################################################
669 static void xdisplay_draw_layer(GHashTable *display_list, struct graphics *gra, struct layer *lay, int order)
670 {
671         GList *itms;
672         struct itemtype *itm;
673
674         itms=lay->itemtypes;
675         while (itms) {
676                 itm=itms->data;
677                 if (order >= itm->order_min && order <= itm->order_max) 
678                         xdisplay_draw_elements(gra, display_list, itm);
679                 itms=g_list_next(itms);
680         }
681 }
682
683 //##############################################################################################################
684 //# Description: 
685 //# Comment: 
686 //# Authors: Martin Schaller (04/2008)
687 //##############################################################################################################
688 static void xdisplay_draw(GHashTable *display_list, struct graphics *gra, struct layout *l, int order)
689 {
690         GList *lays;
691         struct layer *lay;
692         
693         lays=l->layers;
694         while (lays) {
695                 lay=lays->data;
696                 xdisplay_draw_layer(display_list, gra, lay, order);
697                 lays=g_list_next(lays);
698         }
699 }
700
701 //##############################################################################################################
702 //# Description: 
703 //# Comment: 
704 //# Authors: Martin Schaller (04/2008)
705 //##############################################################################################################
706 extern void *route_selection;
707
708 //##############################################################################################################
709 //# Description: 
710 //# Comment: 
711 //# Authors: Martin Schaller (04/2008)
712 //##############################################################################################################
713 static void do_draw_map(struct displaylist *displaylist, struct transformation *t, struct map *m, int order)
714 {
715         enum projection pro;
716         struct map_rect *mr;
717         struct item *item;
718         int conv,count,max=16384;
719         struct point pnt[max];
720         struct coord ca[max];
721         struct attr attr;
722         struct map_selection *sel;
723
724         pro=map_projection(m);
725         conv=map_requires_conversion(m);
726         sel=transform_get_selection(t, pro, order);
727         if (route_selection)
728                 mr=map_rect_new(m, route_selection);
729         else
730                 mr=map_rect_new(m, sel);
731         if (! mr) {
732                 map_selection_destroy(sel);
733                 return;
734         }
735         while ((item=map_rect_get_item(mr))) {
736                 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
737                 if (item->type >= type_line && count < 2) {
738                         dbg(1,"poly from map has only %d points\n", count);
739                         continue;
740                 }
741                 if (item->type < type_line) {
742                         if (! map_selection_contains_point(sel, &ca[0])) {
743                                 dbg(1,"point not visible\n");
744                                 continue;
745                         }
746                 } else if (item->type < type_area) {
747                         if (! map_selection_contains_polyline(sel, ca, count)) {
748                                 dbg(1,"polyline not visible\n");
749                                 continue;
750                         }
751                 } else {
752                         if (! map_selection_contains_polygon(sel, ca, count)) {
753                                 dbg(1,"polygon not visible\n");
754                                 continue;
755                         }
756                 }
757                 if (count == max) 
758                         dbg(0,"point count overflow\n", count);
759                 count=transform(t, pro, ca, pnt, count, 1);
760                 if (item->type >= type_line && count < 2) {
761                         dbg(1,"poly from transform has only %d points\n", count);
762                         continue;
763                 }
764                 if (!item_attr_get(item, attr_label, &attr))
765                         attr.u.str=NULL;
766                 if (conv && attr.u.str && attr.u.str[0]) {
767                         char *str=map_convert_string(m, attr.u.str);
768                         display_add(displaylist, item, count, pnt, str);
769                         map_convert_free(str);
770                 } else
771                         display_add(displaylist, item, count, pnt, attr.u.str);
772         }
773         map_rect_destroy(mr);
774         map_selection_destroy(sel);
775 }
776
777 //##############################################################################################################
778 //# Description: 
779 //# Comment: 
780 //# Authors: Martin Schaller (04/2008)
781 //##############################################################################################################
782 static void do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapsets, int order)
783 {
784         struct mapset *ms;
785         struct map *m;
786         struct mapset_handle *h;
787
788         if (! mapsets)
789                 return;
790         ms=mapsets->data;
791         h=mapset_open(ms);
792         while ((m=mapset_next(h, 1))) {
793                 do_draw_map(displaylist, t, m, order);
794         }
795         mapset_close(h);
796 }
797
798 //##############################################################################################################
799 //# Description: 
800 //# Comment: 
801 //# Authors: Martin Schaller (04/2008)
802 //##############################################################################################################
803 int graphics_ready(struct graphics *this_)
804 {
805         return this_->ready;
806 }
807
808 //##############################################################################################################
809 //# Description: 
810 //# Comment: 
811 //# Authors: Martin Schaller (04/2008)
812 //##############################################################################################################
813 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l)
814 {
815         int order=transform_get_order(trans);
816         struct point p;
817         p.x=0;
818         p.y=0;
819         // FIXME find a better place to set the background color
820         graphics_gc_set_background(gra->gc[0], l->color);
821         graphics_gc_set_foreground(gra->gc[0], l->color);
822         gra->meth.background_gc(gra->priv, gra->gc[0]->priv);
823         gra->meth.draw_mode(gra->priv, draw_mode_begin);
824         gra->meth.draw_rectangle(gra->priv, gra->gc[0]->priv, &p, 32767, 32767);
825         xdisplay_draw(displaylist->dl, gra, l, order);
826         gra->meth.draw_mode(gra->priv, draw_mode_end);
827 }
828
829 //##############################################################################################################
830 //# Description: 
831 //# Comment: 
832 //# Authors: Martin Schaller (04/2008)
833 //##############################################################################################################
834 void graphics_displaylist_move(struct displaylist *displaylist, int dx, int dy)
835 {
836         struct displaylist_handle *dlh;
837         struct displayitem *di;
838         int i;
839
840         dlh=graphics_displaylist_open(displaylist);
841         while ((di=graphics_displaylist_next(dlh))) {
842                 for (i = 0 ; i < di->count ; i++) {
843                         di->pnt[i].x+=dx;
844                         di->pnt[i].y+=dy;
845                 }
846         }
847         graphics_displaylist_close(dlh);
848 }
849
850 //##############################################################################################################
851 //# Description: 
852 //# Comment: 
853 //# Authors: Martin Schaller (04/2008)
854 //##############################################################################################################
855 void graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, struct layout *l)
856 {
857         int order=transform_get_order(trans);
858
859         dbg(1,"enter");
860
861 #if 0
862         printf("scale=%d center=0x%x,0x%x mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y));
863 #endif
864         
865         xdisplay_free(displaylist->dl);
866         dbg(1,"order=%d\n", order);
867
868
869 #if 0
870         for (i = 0 ; i < data_window_type_end; i++) {
871                 data_window_begin(co->data_window[i]);  
872         }
873 #endif
874         profile(0,NULL);
875         do_draw(displaylist, trans, mapsets, order);
876 //      profile(1,"do_draw");
877         graphics_displaylist_draw(gra, displaylist, trans, l);
878         profile(1,"xdisplay_draw");
879         profile(0,"end");
880   
881 #if 0
882         for (i = 0 ; i < data_window_type_end; i++) {
883                 data_window_end(co->data_window[i]);    
884         }
885 #endif
886         gra->ready=1;
887 }
888
889 //##############################################################################################################
890 //# Description: 
891 //# Comment: 
892 //# Authors: Martin Schaller (04/2008)
893 //##############################################################################################################
894 struct displaylist_handle {
895         GList *hl_head,*hl,*l;
896 };
897
898 //##############################################################################################################
899 //# Description: 
900 //# Comment: 
901 //# Authors: Martin Schaller (04/2008)
902 //##############################################################################################################
903 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
904 {
905         struct displaylist_handle *ret;
906
907         ret=g_new0(struct displaylist_handle, 1);
908         ret->hl_head=ret->hl=g_hash_to_list(displaylist->dl);
909
910         return ret;
911 }
912
913 //##############################################################################################################
914 //# Description: 
915 //# Comment: 
916 //# Authors: Martin Schaller (04/2008)
917 //##############################################################################################################
918 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
919 {
920         struct displayitem *ret;
921         if (! dlh->l) {
922                 if (!dlh->hl)
923                         return NULL;
924                 dlh->l=dlh->hl->data;
925                 dlh->hl=g_list_next(dlh->hl);
926         }
927         ret=dlh->l->data;
928         dlh->l=g_list_next(dlh->l);
929         return ret;
930 }
931
932 //##############################################################################################################
933 //# Description: 
934 //# Comment: 
935 //# Authors: Martin Schaller (04/2008)
936 //##############################################################################################################
937 void graphics_displaylist_close(struct displaylist_handle *dlh)
938 {
939         g_list_free(dlh->hl_head);
940         g_free(dlh);
941 }
942
943 //##############################################################################################################
944 //# Description: 
945 //# Comment: 
946 //# Authors: Martin Schaller (04/2008)
947 //##############################################################################################################
948 struct displaylist * graphics_displaylist_new(void)
949 {
950         struct displaylist *ret=g_new(struct displaylist, 1);
951
952         ret->dl=g_hash_table_new(NULL,NULL);
953
954         return ret;
955 }
956
957 //##############################################################################################################
958 //# Description: 
959 //# Comment: 
960 //# Authors: Martin Schaller (04/2008)
961 //##############################################################################################################
962 struct item * graphics_displayitem_get_item(struct displayitem *di)
963 {
964         return &di->item;       
965 }
966
967 //##############################################################################################################
968 //# Description: 
969 //# Comment: 
970 //# Authors: Martin Schaller (04/2008)
971 //##############################################################################################################
972 char * graphics_displayitem_get_label(struct displayitem *di)
973 {
974         return di->label;
975 }
976
977 //##############################################################################################################
978 //# Description: 
979 //# Comment: 
980 //# Authors: Martin Schaller (04/2008)
981 //##############################################################################################################
982 static int within_dist_point(struct point *p0, struct point *p1, int dist)
983 {
984         if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
985                 return 0;
986         if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
987                 return 0;
988         if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) {
989                 return 1;
990         }
991         return 0;
992 }
993
994 //##############################################################################################################
995 //# Description: 
996 //# Comment: 
997 //# Authors: Martin Schaller (04/2008)
998 //##############################################################################################################
999 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
1000 {
1001         int vx,vy,wx,wy;
1002         int c1,c2;
1003         struct point line_p;
1004
1005         vx=line_p1->x-line_p0->x;
1006         vy=line_p1->y-line_p0->y;
1007         wx=p->x-line_p0->x;
1008         wy=p->y-line_p0->y;
1009
1010         c1=vx*wx+vy*wy;
1011         if ( c1 <= 0 )
1012                 return within_dist_point(p, line_p0, dist);
1013         c2=vx*vx+vy*vy;
1014         if ( c2 <= c1 )
1015                 return within_dist_point(p, line_p1, dist);
1016
1017         line_p.x=line_p0->x+vx*c1/c2;
1018         line_p.y=line_p0->y+vy*c1/c2;
1019         return within_dist_point(p, &line_p, dist);
1020 }
1021
1022 //##############################################################################################################
1023 //# Description: 
1024 //# Comment: 
1025 //# Authors: Martin Schaller (04/2008)
1026 //##############################################################################################################
1027 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
1028 {
1029         int i;
1030         for (i = 0 ; i < count-1 ; i++) {
1031                 if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) {
1032                         return 1;
1033                 }
1034         }
1035         if (close)
1036                 return (within_dist_line(p,line_pnt,line_pnt+count-1,dist));
1037         return 0;
1038 }
1039
1040 //##############################################################################################################
1041 //# Description: 
1042 //# Comment: 
1043 //# Authors: Martin Schaller (04/2008)
1044 //##############################################################################################################
1045 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
1046 {
1047         int i, j, c = 0;
1048         for (i = 0, j = count-1; i < count; j = i++) {
1049                 if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) ||
1050                 ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) &&
1051                 (p->x < (poly_pnt[j].x - poly_pnt[i].x) * (p->y - poly_pnt[i].y) / (poly_pnt[j].y - poly_pnt[i].y) + poly_pnt[i].x)) 
1052                         c = !c;
1053         }
1054         if (! c)
1055                 return within_dist_polyline(p, poly_pnt, count, dist, 1);
1056         return c;
1057 }
1058
1059 //##############################################################################################################
1060 //# Description: 
1061 //# Comment: 
1062 //# Authors: Martin Schaller (04/2008)
1063 //##############################################################################################################
1064 int graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist)
1065 {
1066         if (di->item.type < type_line) {
1067                 return within_dist_point(p, &di->pnt[0], dist);
1068         }
1069         if (di->item.type < type_area) {
1070                 return within_dist_polyline(p, di->pnt, di->count, dist, 0);
1071         }
1072         return within_dist_polygon(p, di->pnt, di->count, dist);
1073 }