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