/[zanavi_public1]/navit/navit/graphics.c
ZANavi

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 75886 byte(s)
import files
1 zoff99 2 /**
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 <stdlib.h>
30     #include <glib.h>
31     #include <stdio.h>
32     #include <math.h>
33     #include "config.h"
34     #include "debug.h"
35     #include "string.h"
36     #include "draw_info.h"
37     #include "point.h"
38     #include "graphics.h"
39     #include "projection.h"
40     #include "item.h"
41     #include "map.h"
42     #include "coord.h"
43     #include "transform.h"
44     #include "plugin.h"
45     #include "profile.h"
46     #include "mapset.h"
47     #include "layout.h"
48     #include "route.h"
49     #include "util.h"
50     #include "callback.h"
51     #include "file.h"
52     #include "event.h"
53     //
54     #include "attr.h"
55     #include "navit.h"
56    
57    
58     // bad thing
59     struct navit *global_navit;
60     // bad thing
61    
62    
63     //##############################################################################################################
64     //# Description:
65     //# Comment:
66     //# Authors: Martin Schaller (04/2008)
67     //##############################################################################################################
68    
69     // above what "order" level to show only prerendered map
70     #define ORDER_USE_PRERENDERED_MAP 0
71    
72     struct graphics
73     {
74     struct graphics_priv *priv;
75     struct graphics_methods meth;
76     char *default_font;
77     int font_len;
78     struct graphics_font **font;
79     struct graphics_gc *gc[3];
80     struct attr **attrs;
81     struct callback_list *cbl;
82     struct point_rect r;
83     int gamma,brightness,contrast;
84     int colormgmt;
85     int font_size;
86     GList *selection;
87     };
88    
89     struct display_context
90     {
91     struct graphics *gra;
92     struct element *e;
93     struct graphics_gc *gc;
94     struct graphics_gc *gc_background;
95     struct graphics_image *img;
96     enum projection pro;
97     int mindist;
98     struct transformation *trans;
99     enum item_type type;
100     int maxlen;
101     };
102    
103     #define HASH_SIZE 1024
104     struct hash_entry
105     {
106     enum item_type type;
107     struct displayitem *di;
108     };
109    
110    
111     struct displaylist {
112     int busy;
113     int workload;
114     struct callback *cb;
115     struct layout *layout, *layout_hashed;
116     struct display_context dc;
117     int order, order_hashed, max_offset;
118     struct mapset *ms;
119     struct mapset_handle *msh;
120     struct map *m;
121     int conv;
122     struct map_selection *sel;
123     struct map_rect *mr;
124     struct callback *idle_cb;
125     struct event_idle *idle_ev;
126     unsigned int seq;
127     struct hash_entry hash_entries[HASH_SIZE];
128     };
129    
130    
131     struct displaylist_icon_cache {
132     unsigned int seq;
133    
134     };
135    
136    
137     /**
138     * FIXME
139     * @param <>
140     * @returns <>
141     * @author Martin Schaller (04/2008)
142     */
143     struct displayitem {
144     struct displayitem *next;
145     struct item item;
146     char *label;
147     int count;
148     struct coord c[0];
149     };
150    
151     static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir);
152     static void graphics_process_selection(struct graphics *gra, struct displaylist *dl);
153     static void graphics_gc_init(struct graphics *this_);
154    
155     static void
156     clear_hash(struct displaylist *dl)
157     {
158     int i;
159     for (i = 0 ; i < HASH_SIZE ; i++)
160     dl->hash_entries[i].type=type_none;
161     }
162    
163     static struct hash_entry *
164     get_hash_entry(struct displaylist *dl, enum item_type type)
165     {
166     int hashidx=(type*2654435761UL) & (HASH_SIZE-1);
167     int offset=dl->max_offset;
168     do {
169     if (!dl->hash_entries[hashidx].type)
170     return NULL;
171     if (dl->hash_entries[hashidx].type == type)
172     return &dl->hash_entries[hashidx];
173     hashidx=(hashidx+1)&(HASH_SIZE-1);
174     } while (offset-- > 0);
175     return NULL;
176     }
177    
178     static struct hash_entry *
179     set_hash_entry(struct displaylist *dl, enum item_type type)
180     {
181     int hashidx=(type*2654435761UL) & (HASH_SIZE-1);
182     int offset=0;
183     for (;;) {
184     if (!dl->hash_entries[hashidx].type) {
185     dl->hash_entries[hashidx].type=type;
186     if (dl->max_offset < offset)
187     dl->max_offset=offset;
188     return &dl->hash_entries[hashidx];
189     }
190     if (dl->hash_entries[hashidx].type == type)
191     return &dl->hash_entries[hashidx];
192     hashidx=(hashidx+1)&(HASH_SIZE-1);
193     offset++;
194     }
195     return NULL;
196     }
197    
198     static int
199     graphics_set_attr_do(struct graphics *gra, struct attr *attr)
200     {
201     switch (attr->type) {
202     case attr_gamma:
203     gra->gamma=attr->u.num;
204     break;
205     case attr_brightness:
206     gra->brightness=attr->u.num;
207     break;
208     case attr_contrast:
209     gra->contrast=attr->u.num;
210     break;
211     case attr_font_size:
212     gra->font_size=attr->u.num;
213     return 1;
214     default:
215     return 0;
216     }
217     gra->colormgmt=(gra->gamma != 65536 || gra->brightness != 0 || gra->contrast != 65536);
218     graphics_gc_init(gra);
219     return 1;
220     }
221    
222     int
223     graphics_set_attr(struct graphics *gra, struct attr *attr)
224     {
225     int ret=1;
226     // dbg(0,"enter\n");
227     if (gra->meth.set_attr)
228     ret=gra->meth.set_attr(gra->priv, attr);
229     if (!ret)
230     ret=graphics_set_attr_do(gra, attr);
231     return ret != 0;
232     }
233    
234     void
235     graphics_set_rect(struct graphics *gra, struct point_rect *pr)
236     {
237     gra->r=*pr;
238     }
239    
240     /**
241     * Creates a new graphics object
242     * attr type required
243     * @param <>
244     * @returns <>
245     * @author Martin Schaller (04/2008)
246     */
247     struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
248     {
249     struct graphics *this_;
250     struct attr *type_attr;
251     struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl);
252    
253     if (! (type_attr=attr_search(attrs, NULL, attr_type))) {
254     return NULL;
255     }
256    
257     graphicstype_new=plugin_get_graphics_type(type_attr->u.str);
258     if (! graphicstype_new)
259     return NULL;
260     this_=g_new0(struct graphics, 1);
261     this_->cbl=callback_list_new();
262     this_->priv=(*graphicstype_new)(parent->u.navit, &this_->meth, attrs, this_->cbl);
263     this_->attrs=attr_list_dup(attrs);
264     this_->brightness=0;
265     this_->contrast=65536;
266     this_->gamma=65536;
267     this_->font_size=20;
268     while (*attrs) {
269     graphics_set_attr_do(this_,*attrs);
270     attrs++;
271     }
272     return this_;
273     }
274    
275     /**
276     * FIXME
277     * @param <>
278     * @returns <>
279     * @author Martin Schaller (04/2008)
280     */
281     int graphics_get_attr(struct graphics *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
282     {
283     return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
284     }
285    
286     /**
287     * FIXME
288     * @param <>
289     * @returns <>
290     * @author Martin Schaller (04/2008)
291     */
292     struct graphics * graphics_overlay_new(struct graphics *parent, struct point *p, int w, int h, int alpha, int wraparound)
293     {
294     struct graphics *this_;
295     struct point_rect pr;
296     if (!parent->meth.overlay_new)
297     return NULL;
298     this_=g_new0(struct graphics, 1);
299     this_->priv=parent->meth.overlay_new(parent->priv, &this_->meth, p, w, h, alpha, wraparound);
300     pr.lu.x=0;
301     pr.lu.y=0;
302     pr.rl.x=w;
303     pr.rl.y=h;
304     this_->font_size=20;
305     graphics_set_rect(this_, &pr);
306     if (!this_->priv) {
307     g_free(this_);
308     this_=NULL;
309     }
310     return this_;
311     }
312    
313     /**
314     * @brief Alters the size, position, alpha and wraparound for an overlay
315     *
316     * @param this_ The overlay's graphics struct
317     * @param p The new position of the overlay
318     * @param w The new width of the overlay
319     * @param h The new height of the overlay
320     * @param alpha The new alpha of the overlay
321     * @param wraparound The new wraparound of the overlay
322     */
323     void
324     graphics_overlay_resize(struct graphics *this_, struct point *p, int w, int h, int alpha, int wraparound)
325     {
326     if (! this_->meth.overlay_resize) {
327     return;
328     }
329    
330     this_->meth.overlay_resize(this_->priv, p, w, h, alpha, wraparound);
331     }
332    
333     static void
334     graphics_gc_init(struct graphics *this_)
335     {
336     struct color background={ COLOR_BACKGROUND_ };
337     struct color black={ COLOR_BLACK_ };
338     struct color white={ COLOR_WHITE_ };
339     if (!this_->gc[0] || !this_->gc[1] || !this_->gc[2])
340     return;
341     graphics_gc_set_background(this_->gc[0], &background );
342     graphics_gc_set_foreground(this_->gc[0], &background );
343     graphics_gc_set_background(this_->gc[1], &black );
344     graphics_gc_set_foreground(this_->gc[1], &white );
345     graphics_gc_set_background(this_->gc[2], &white );
346     graphics_gc_set_foreground(this_->gc[2], &black );
347     }
348    
349    
350    
351     /**
352     * FIXME
353     * @param <>
354     * @returns <>
355     * @author Martin Schaller (04/2008)
356     */
357     void graphics_init(struct graphics *this_)
358     {
359     if (this_->gc[0])
360     return;
361     this_->gc[0]=graphics_gc_new(this_);
362     this_->gc[1]=graphics_gc_new(this_);
363     this_->gc[2]=graphics_gc_new(this_);
364     graphics_gc_init(this_);
365     graphics_background_gc(this_, this_->gc[0]);
366     }
367    
368     /**
369     * FIXME
370     * @param <>
371     * @returns <>
372     * @author Martin Schaller (04/2008)
373     */
374     void * graphics_get_data(struct graphics *this_, const char *type)
375     {
376     return (this_->meth.get_data(this_->priv, type));
377     }
378    
379     void graphics_add_callback(struct graphics *this_, struct callback *cb)
380     {
381     callback_list_add(this_->cbl, cb);
382     }
383    
384     void graphics_remove_callback(struct graphics *this_, struct callback *cb)
385     {
386     callback_list_remove(this_->cbl, cb);
387     }
388    
389     /**
390     * FIXME
391     * @param <>
392     * @returns <>
393     * @author Martin Schaller (04/2008)
394     */
395     struct graphics_font * graphics_font_new(struct graphics *gra, int size, int flags)
396     {
397     struct graphics_font *this_;
398    
399     this_=g_new0(struct graphics_font,1);
400     this_->priv=gra->meth.font_new(gra->priv, &this_->meth, gra->default_font, size, flags);
401     return this_;
402     }
403    
404     struct graphics_font * graphics_named_font_new(struct graphics *gra, char *font, int size, int flags)
405     {
406     struct graphics_font *this_;
407    
408     this_=g_new0(struct graphics_font,1);
409     this_->priv=gra->meth.font_new(gra->priv, &this_->meth, font, size, flags);
410     return this_;
411     }
412    
413    
414     /**
415     * Destroy graphics
416     * Called when navit exits
417     * @param gra The graphics instance
418     * @returns nothing
419     * @author David Tegze (02/2011)
420     */
421     void graphics_free(struct graphics *gra)
422     {
423     if (!gra)
424     return;
425     gra->meth.graphics_destroy(gra->priv);
426     g_free(gra->default_font);
427     graphics_font_destroy_all(gra);
428     g_free(gra);
429     }
430    
431     /**
432     * Free all loaded fonts.
433     * Used when switching layouts.
434     * @param gra The graphics instance
435     * @returns nothing
436     * @author Sarah Nordstrom (05/2008)
437     */
438     void graphics_font_destroy_all(struct graphics *gra)
439     {
440     int i;
441     for(i = 0 ; i < gra->font_len; i++) {
442     if(!gra->font[i]) continue;
443     gra->font[i]->meth.font_destroy(gra->font[i]->priv);
444     gra->font[i] = NULL;
445     }
446     }
447    
448     /**
449     * FIXME
450     * @param <>
451     * @returns <>
452     * @author Martin Schaller (04/2008)
453     */
454     struct graphics_gc * graphics_gc_new(struct graphics *gra)
455     {
456     struct graphics_gc *this_;
457    
458     this_=g_new0(struct graphics_gc,1);
459     this_->priv=gra->meth.gc_new(gra->priv, &this_->meth);
460     this_->gra=gra;
461     return this_;
462     }
463    
464     /**
465     * FIXME
466     * @param <>
467     * @returns <>
468     * @author Martin Schaller (04/2008)
469     */
470     void graphics_gc_destroy(struct graphics_gc *gc)
471     {
472     gc->meth.gc_destroy(gc->priv);
473     g_free(gc);
474     }
475    
476     static void
477     graphics_convert_color(struct graphics *gra, struct color *in, struct color *out)
478     {
479     *out=*in;
480     if (gra->brightness) {
481     out->r+=gra->brightness;
482     out->g+=gra->brightness;
483     out->b+=gra->brightness;
484     }
485     if (gra->contrast != 65536) {
486     out->r=out->r*gra->contrast/65536;
487     out->g=out->g*gra->contrast/65536;
488     out->b=out->b*gra->contrast/65536;
489     }
490     if (out->r < 0)
491     out->r=0;
492     if (out->r > 65535)
493     out->r=65535;
494     if (out->g < 0)
495     out->g=0;
496     if (out->g > 65535)
497     out->g=65535;
498     if (out->b < 0)
499     out->b=0;
500     if (out->b > 65535)
501     out->b=65535;
502     if (gra->gamma != 65536) {
503     out->r=pow(out->r/65535.0,gra->gamma/65536.0)*65535.0;
504     out->g=pow(out->g/65535.0,gra->gamma/65536.0)*65535.0;
505     out->b=pow(out->b/65535.0,gra->gamma/65536.0)*65535.0;
506     }
507     }
508    
509     /**
510     * FIXME
511     * @param <>
512     * @returns <>
513     * @author Martin Schaller (04/2008)
514     */
515     void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
516     {
517     struct color cn;
518     if (gc->gra->colormgmt) {
519     graphics_convert_color(gc->gra, c, &cn);
520     c=&cn;
521     }
522     gc->meth.gc_set_foreground(gc->priv, c);
523     }
524    
525     /**
526     * FIXME
527     * @param <>
528     * @returns <>
529     * @author Martin Schaller (04/2008)
530     */
531     void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
532     {
533     struct color cn;
534     if (gc->gra->colormgmt) {
535     graphics_convert_color(gc->gra, c, &cn);
536     c=&cn;
537     }
538     gc->meth.gc_set_background(gc->priv, c);
539     }
540    
541    
542     /**
543     * FIXME
544     * @param <>
545     * @returns <>
546     * @author Martin Schaller (04/2008)
547     */
548     void graphics_gc_set_stipple(struct graphics_gc *gc, struct graphics_image *img)
549     {
550     gc->meth.gc_set_stipple(gc->priv, img ? img->priv : NULL);
551     }
552    
553    
554     /**
555     * FIXME
556     * @param <>
557     * @returns <>
558     * @author Martin Schaller (04/2008)
559     */
560     void graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
561     {
562     gc->meth.gc_set_linewidth(gc->priv, width);
563     }
564    
565     /**
566     * FIXME
567     * @param <>
568     * @returns <>
569     * @author Martin Schaller (04/2008)
570     */
571     void graphics_gc_set_dashes(struct graphics_gc *gc, int width, int offset, unsigned char dash_list[], int n)
572     {
573     if (gc->meth.gc_set_dashes)
574     gc->meth.gc_set_dashes(gc->priv, width, offset, dash_list, n);
575     }
576    
577     /**
578     * Create a new image from file path scaled to w and h pixels
579     * @param gra the graphics instance
580     * @param path path of the image to load
581     * @param w width to rescale to
582     * @param h height to rescale to
583     * @returns <>
584     * @author Martin Schaller (04/2008)
585     */
586     struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *path, int w, int h)
587     {
588     struct graphics_image *this_;
589    
590     this_=g_new0(struct graphics_image,1);
591     this_->height=h;
592     this_->width=w;
593     this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, 0);
594     if (! this_->priv) {
595     g_free(this_);
596     this_=NULL;
597     }
598     return this_;
599     }
600    
601     /**
602     * Create a new image from file path scaled to w and h pixels and possibly rotated
603     * @param gra the graphics instance
604     * @param path path of the image to load
605     * @param w width to rescale to
606     * @param h height to rescale to
607     * @param rotate angle to rotate the image. Warning, graphics might only support 90 degree steps here
608     * @returns <>
609     * @author Martin Schaller (04/2008)
610     */
611     struct graphics_image * graphics_image_new_scaled_rotated(struct graphics *gra, char *path, int w, int h, int rotate)
612     {
613     struct graphics_image *this_;
614    
615     this_=g_new0(struct graphics_image,1);
616     this_->height=h;
617     this_->width=w;
618     this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, rotate);
619     if (! this_->priv) {
620     g_free(this_);
621     this_=NULL;
622     }
623     return this_;
624     }
625    
626     /**
627     * Create a new image from file path
628     * @param gra the graphics instance
629     * @param path path of the image to load
630     * @returns <>
631     * @author Martin Schaller (04/2008)
632     */
633     struct graphics_image * graphics_image_new(struct graphics *gra, char *path)
634     {
635     return graphics_image_new_scaled(gra, path, -1, -1);
636     }
637    
638     /**
639     * FIXME
640     * @param <>
641     * @returns <>
642     * @author Martin Schaller (04/2008)
643     */
644     void graphics_image_free(struct graphics *gra, struct graphics_image *img)
645     {
646     if (gra->meth.image_free)
647     gra->meth.image_free(gra->priv, img->priv);
648     g_free(img);
649     }
650    
651     /**
652     * FIXME
653     * @param <>
654     * @returns <>
655     * @author Martin Schaller (04/2008)
656     */
657     void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
658     {
659     //dbg(0,"ooo enter ooo\n");
660    
661     this_->meth.draw_restore(this_->priv, p, w, h);
662     }
663    
664     /**
665     * FIXME
666     * @param <>
667     * @returns <>
668     * @author Martin Schaller (04/2008)
669     */
670     void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
671     {
672     //dbg(0,"ooo enter ooo\n");
673    
674     this_->meth.draw_mode(this_->priv, mode);
675     }
676    
677     /**
678     * FIXME
679     * @param <>
680     * @returns <>
681     * @author Martin Schaller (04/2008)
682     */
683     void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
684     {
685     this_->meth.draw_lines(this_->priv, gc->priv, p, count);
686     }
687    
688     void graphics_draw_lines_dashed(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count, int order, int oneway)
689     {
690     this_->meth.draw_lines_dashed(this_->priv, gc->priv, p, count, order, oneway);
691     }
692    
693     /**
694     * FIXME
695     * @param <>
696     * @returns <>
697     * @author Martin Schaller (04/2008)
698     */
699     void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
700     {
701     struct point *pnt=g_alloca(sizeof(struct point)*(r*4+64));
702     int i=0;
703    
704     if(this_->meth.draw_circle)
705     this_->meth.draw_circle(this_->priv, gc->priv, p, r);
706     else
707     {
708     draw_circle(p, r, 0, -1, 1026, pnt, &i, 1);
709     pnt[i] = pnt[0];
710     i++;
711     this_->meth.draw_lines(this_->priv, gc->priv, pnt, i);
712     }
713     }
714    
715     /**
716     * FIXME
717     * @param <>
718     * @returns <>
719     * @author Martin Schaller (04/2008)
720     */
721     void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
722     {
723     this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
724     }
725    
726     void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, int r, int fill)
727     {
728     struct point *p=g_alloca(sizeof(struct point)*(r*4+32));
729     struct point pi0={plu->x+r,plu->y+r};
730     struct point pi1={plu->x+w-r,plu->y+r};
731     struct point pi2={plu->x+w-r,plu->y+h-r};
732     struct point pi3={plu->x+r,plu->y+h-r};
733     int i=0;
734    
735     draw_circle(&pi2, r*2, 0, -1, 258, p, &i, 1);
736     draw_circle(&pi1, r*2, 0, 255, 258, p, &i, 1);
737     draw_circle(&pi0, r*2, 0, 511, 258, p, &i, 1);
738     draw_circle(&pi3, r*2, 0, 767, 258, p, &i, 1);
739     p[i]=p[0];
740     i++;
741     if (fill)
742     this_->meth.draw_polygon(this_->priv, gc->priv, p, i);
743     else
744     this_->meth.draw_lines(this_->priv, gc->priv, p, i);
745     }
746    
747    
748     /**
749     * FIXME
750     * @param <>
751     * @returns <>
752     * @author Martin Schaller (04/2008)
753     */
754     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)
755     {
756     this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy);
757     }
758    
759    
760     /**
761     * FIXME
762     * @param <>
763     * @returns <>
764     * @author Martin Schaller (04/2008)
765     */
766     void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret, int estimate)
767     {
768     this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret, estimate);
769     }
770    
771     /**
772     * FIXME
773     * @param <>
774     * @returns <>
775     * @author Martin Schaller (04/2008)
776     */
777     void graphics_overlay_disable(struct graphics *this_, int disable)
778     {
779     if (this_->meth.overlay_disable)
780     this_->meth.overlay_disable(this_->priv, disable);
781     }
782    
783     /**
784     * FIXME
785     * @param <>
786     * @returns <>
787     * @author Martin Schaller (04/2008)
788     */
789     void graphics_draw_image(struct graphics *this_, struct graphics_gc *gc, struct point *p, struct graphics_image *img)
790     {
791     this_->meth.draw_image(this_->priv, gc->priv, p, img->priv);
792     }
793    
794    
795     /**
796     *
797     *
798     * @author Zoff (2011)
799     */
800     void graphics_draw_bigmap(struct graphics *this_, struct graphics_gc *gc, int yaw, int order, float clat, float clng, int x, int y, int scx, int scy, int px, int py, int valid)
801     {
802     this_->meth.draw_bigmap(this_->priv, gc->priv, yaw, order, clat, clng, x, y, scx, scy, px, py, valid);
803     }
804    
805     void graphics_send_osd_values(struct graphics *this_, struct graphics_gc *gc, char *id, char *text1, char *text2, char *text3, int i1, int i2, int i3, int i4, float f1, float f2, float f3)
806     {
807     this_->meth.send_osd_values(this_->priv, gc->priv, id, text1, text2, text3, i1, i2, i3, i4, f1, f2, f3);
808     }
809    
810    
811     //##############################################################################################################
812     //# Description:
813     //# Comment:
814     //# Authors: Martin Schaller (04/2008)
815     //##############################################################################################################
816     int
817     graphics_draw_drag(struct graphics *this_, struct point *p)
818     {
819     //dbg(0,"ooo enter ooo\n");
820    
821     if (!this_->meth.draw_drag)
822     {
823     return 0;
824     }
825     //dbg(0,"draw DRAG start ...\n");
826     this_->meth.draw_drag(this_->priv, p);
827     //dbg(0,"draw DRAG end ...\n");
828     return 1;
829     }
830    
831     void
832     graphics_background_gc(struct graphics *this_, struct graphics_gc *gc)
833     {
834     //dbg(0,"ooo enter ooo\n");
835    
836     this_->meth.background_gc(this_->priv, gc ? gc->priv : NULL);
837     }
838    
839     #include "attr.h"
840     #include "popup.h"
841     #include <stdio.h>
842    
843    
844     #if 0
845     //##############################################################################################################
846     //# Description:
847     //# Comment:
848     //# Authors: Martin Schaller (04/2008)
849     //##############################################################################################################
850     static void popup_view_html(struct popup_item *item, char *file)
851     {
852     char command[1024];
853     sprintf(command,"firefox %s", file);
854     system(command);
855     }
856    
857     struct transformatin *tg;
858     enum projection pg;
859    
860     //##############################################################################################################
861     //# Description:
862     //# Comment:
863     //# Authors: Martin Schaller (04/2008)
864     //##############################################################################################################
865     static void graphics_popup(struct display_list *list, struct popup_item **popup)
866     {
867     struct item *item;
868     struct attr attr;
869     struct map_rect *mr;
870     struct coord c;
871     struct popup_item *curr_item,*last=NULL;
872     item=list->data;
873     mr=map_rect_new(item->map, NULL, NULL, 0);
874     printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
875     item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
876     if (item) {
877     if (item_attr_get(item, attr_name, &attr)) {
878     curr_item=popup_item_new_text(popup,attr.u.str,1);
879     if (item_attr_get(item, attr_info_html, &attr)) {
880     popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
881     }
882     if (item_attr_get(item, attr_price_html, &attr)) {
883     popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
884     }
885     curr_item->submenu=last;
886     }
887     }
888     map_rect_destroy(mr);
889     }
890     #endif
891    
892    
893     /**
894     * FIXME
895     * @param <>
896     * @returns <>
897     * @author Martin Schaller (04/2008)
898     */
899     static void xdisplay_free(struct displaylist *dl)
900     {
901     int i;
902     for (i = 0 ; i < HASH_SIZE ; i++) {
903     struct displayitem *di=dl->hash_entries[i].di;
904     while (di) {
905     struct displayitem *next=di->next;
906     g_free(di);
907     di=next;
908     }
909     dl->hash_entries[i].di=NULL;
910     }
911     }
912    
913     /**
914     * FIXME
915     * @param <>
916     * @returns <>
917     * @author Martin Schaller (04/2008)
918     */
919     static void display_add(struct hash_entry *entry, struct item *item, int count, struct coord *c, char **label, int label_count)
920     {
921     struct displayitem *di;
922     int len,i;
923     char *p;
924    
925     len=sizeof(*di)+count*sizeof(*c);
926     if (label && label_count) {
927     for (i = 0 ; i < label_count ; i++) {
928     if (label[i])
929     len+=strlen(label[i])+1;
930     else
931     len++;
932     }
933     }
934     p=g_malloc(len);
935    
936     di=(struct displayitem *)p;
937     p+=sizeof(*di)+count*sizeof(*c);
938     di->item=*item;
939     if (label && label_count) {
940     di->label=p;
941     for (i = 0 ; i < label_count ; i++) {
942     if (label[i]) {
943     strcpy(p, label[i]);
944     p+=strlen(label[i])+1;
945     } else
946     *p++='\0';
947     }
948     } else
949     di->label=NULL;
950     di->count=count;
951     memcpy(di->c, c, count*sizeof(*c));
952     di->next=entry->di;
953     entry->di=di;
954     }
955    
956    
957     /**
958     * FIXME
959     * @param <>
960     * @returns <>
961     * @author Martin Schaller (04/2008)
962     */
963     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)
964     {
965     int i,x,y,tl,tlm,th,thm,tlsq,l;
966     float lsq;
967     double dx,dy;
968     struct point p_t;
969     struct point pb[5];
970    
971     if (gra->meth.get_text_bbox) {
972     gra->meth.get_text_bbox(gra->priv, font->priv, label, 0x10000, 0x0, pb, 1);
973     tl=(pb[2].x-pb[0].x);
974     th=(pb[0].y-pb[1].y);
975     } else {
976     tl=strlen(label)*4;
977     th=8;
978     }
979     tlm=tl*32;
980     thm=th*36;
981     tlsq = tlm*tlm;
982     for (i = 0 ; i < count-1 ; i++) {
983     dx=p[i+1].x-p[i].x;
984     dx*=32;
985     dy=p[i+1].y-p[i].y;
986     dy*=32;
987     lsq = dx*dx+dy*dy;
988     if (lsq > tlsq) {
989     l=(int)sqrtf(lsq);
990     x=p[i].x;
991     y=p[i].y;
992     if (dx < 0) {
993     dx=-dx;
994     dy=-dy;
995     x=p[i+1].x;
996     y=p[i+1].y;
997     }
998     x+=(l-tlm)*dx/l/64;
999     y+=(l-tlm)*dy/l/64;
1000     x-=dy*thm/l/64;
1001     y+=dx*thm/l/64;
1002     p_t.x=x;
1003     p_t.y=y;
1004     #if 0
1005     dbg(0,"display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
1006     #endif
1007     if (x < gra->r.rl.x && x + tl > gra->r.lu.x && y + tl > gra->r.lu.y && y - tl < gra->r.rl.y)
1008     gra->meth.draw_text(gra->priv, fg->priv, bg?bg->priv:NULL, font->priv, label, &p_t, dx*0x10000/l, dy*0x10000/l);
1009     }
1010     }
1011     }
1012    
1013     static void display_draw_arrow(struct point *p, int dx, int dy, int l, struct graphics_gc *gc, struct graphics *gra)
1014     {
1015     struct point pnt[3];
1016     pnt[0]=pnt[1]=pnt[2]=*p;
1017     pnt[0].x+=-dx*l/65536+dy*l/65536;
1018     pnt[0].y+=-dy*l/65536-dx*l/65536;
1019     pnt[2].x+=-dx*l/65536-dy*l/65536;
1020     pnt[2].y+=-dy*l/65536+dx*l/65536;
1021     gra->meth.draw_lines(gra->priv, gc->priv, pnt, 3);
1022     }
1023    
1024     static void display_draw_arrows(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count)
1025     {
1026     int i,dx,dy,l;
1027     struct point p;
1028     for (i = 0 ; i < count-1 ; i++) {
1029     dx=pnt[i+1].x-pnt[i].x;
1030     dy=pnt[i+1].y-pnt[i].y;
1031     l=sqrt(dx*dx+dy*dy);
1032     if (l) {
1033     dx=dx*65536/l;
1034     dy=dy*65536/l;
1035     p=pnt[i];
1036     p.x+=dx*15/65536;
1037     p.y+=dy*15/65536;
1038     display_draw_arrow(&p, dx, dy, 10, gc, gra);
1039     p=pnt[i+1];
1040     p.x-=dx*15/65536;
1041     p.y-=dy*15/65536;
1042     display_draw_arrow(&p, dx, dy, 10, gc, gra);
1043     }
1044     }
1045     }
1046    
1047     static int
1048     intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy,
1049     struct point * res)
1050     {
1051     int n, a, b;
1052     n = bdy * adx - bdx * ady;
1053     a = bdx * (a1->y - b1->y) - bdy * (a1->x - b1->x);
1054     b = adx * (a1->y - b1->y) - ady * (a1->x - b1->x);
1055     if (n < 0) {
1056     n = -n;
1057     a = -a;
1058     b = -b;
1059     }
1060     #if 0
1061     if (a < 0 || b < 0)
1062     return 0;
1063     if (a > n || b > n)
1064     return 0;
1065     #endif
1066     if (n == 0)
1067     return 0;
1068     res->x = a1->x + a * adx / n;
1069     res->y = a1->y + a * ady / n;
1070     return 1;
1071     }
1072    
1073     struct circle {
1074     short x,y,fowler;
1075     } circle64[]={
1076     {0,128,0},
1077     {13,127,13},
1078     {25,126,25},
1079     {37,122,38},
1080     {49,118,53},
1081     {60,113,67},
1082     {71,106,85},
1083     {81,99,104},
1084     {91,91,128},
1085     {99,81,152},
1086     {106,71,171},
1087     {113,60,189},
1088     {118,49,203},
1089     {122,37,218},
1090     {126,25,231},
1091     {127,13,243},
1092     {128,0,256},
1093     {127,-13,269},
1094     {126,-25,281},
1095     {122,-37,294},
1096     {118,-49,309},
1097     {113,-60,323},
1098     {106,-71,341},
1099     {99,-81,360},
1100     {91,-91,384},
1101     {81,-99,408},
1102     {71,-106,427},
1103     {60,-113,445},
1104     {49,-118,459},
1105     {37,-122,474},
1106     {25,-126,487},
1107     {13,-127,499},
1108     {0,-128,512},
1109     {-13,-127,525},
1110     {-25,-126,537},
1111     {-37,-122,550},
1112     {-49,-118,565},
1113     {-60,-113,579},
1114     {-71,-106,597},
1115     {-81,-99,616},
1116     {-91,-91,640},
1117     {-99,-81,664},
1118     {-106,-71,683},
1119     {-113,-60,701},
1120     {-118,-49,715},
1121     {-122,-37,730},
1122     {-126,-25,743},
1123     {-127,-13,755},
1124     {-128,0,768},
1125     {-127,13,781},
1126     {-126,25,793},
1127     {-122,37,806},
1128     {-118,49,821},
1129     {-113,60,835},
1130     {-106,71,853},
1131     {-99,81,872},
1132     {-91,91,896},
1133     {-81,99,920},
1134     {-71,106,939},
1135     {-60,113,957},
1136     {-49,118,971},
1137     {-37,122,986},
1138     {-25,126,999},
1139     {-13,127,1011},
1140     };
1141    
1142     static void
1143     draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir)
1144     {
1145     struct circle *c;
1146    
1147     #if 0
1148     dbg(0,"diameter=%d start=%d len=%d pos=%d dir=%d\n", diameter, start, len, *pos, dir);
1149     #endif
1150     int count=64;
1151     int end=start+len;
1152     int i,step;
1153     c=circle64;
1154     if (diameter > 128)
1155     step=1;
1156     else if (diameter > 64)
1157     step=2;
1158     else if (diameter > 24)
1159     step=4;
1160     else if (diameter > 8)
1161     step=8;
1162     else
1163     step=16;
1164     if (len > 0) {
1165     while (start < 0) {
1166     start+=1024;
1167     end+=1024;
1168     }
1169     while (end > 0) {
1170     i=0;
1171     while (i < count && c[i].fowler <= start)
1172     i+=step;
1173     while (i < count && c[i].fowler < end) {
1174     if (1< *pos || 0<dir) {
1175     res[*pos].x=pnt->x+((c[i].x*diameter+128)>>8);
1176     res[*pos].y=pnt->y+((c[i].y*diameter+128)>>8);
1177     (*pos)+=dir;
1178     }
1179     i+=step;
1180     }
1181     end-=1024;
1182     start-=1024;
1183     }
1184     } else {
1185     while (start > 1024) {
1186     start-=1024;
1187     end-=1024;
1188     }
1189     while (end < 1024) {
1190     i=count-1;
1191     while (i >= 0 && c[i].fowler >= start)
1192     i-=step;
1193     while (i >= 0 && c[i].fowler > end) {
1194     if (1< *pos || 0<dir) {
1195     res[*pos].x=pnt->x+((c[i].x*diameter+128)>>8);
1196     res[*pos].y=pnt->y+((c[i].y*diameter+128)>>8);
1197     (*pos)+=dir;
1198     }
1199     i-=step;
1200     }
1201     start+=1024;
1202     end+=1024;
1203     }
1204     }
1205     }
1206    
1207    
1208     static int
1209     fowler(int dy, int dx)
1210     {
1211     int adx, ady; /* Absolute Values of Dx and Dy */
1212     int code; /* Angular Region Classification Code */
1213    
1214     adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
1215     ady = (dy < 0) ? -dy : dy;
1216    
1217     code = (adx < ady) ? 1 : 0;
1218     if (dx < 0)
1219     code += 2;
1220     if (dy < 0)
1221     code += 4;
1222    
1223     switch (code) {
1224     case 0:
1225     return (dx == 0) ? 0 : 128*ady / adx; /* [ 0, 45] */
1226     case 1:
1227     return (256 - (128*adx / ady)); /* ( 45, 90] */
1228     case 3:
1229     return (256 + (128*adx / ady)); /* ( 90,135) */
1230     case 2:
1231     return (512 - (128*ady / adx)); /* [135,180] */
1232     case 6:
1233     return (512 + (128*ady / adx)); /* (180,225] */
1234     case 7:
1235     return (768 - (128*adx / ady)); /* (225,270) */
1236     case 5:
1237     return (768 + (128*adx / ady)); /* [270,315) */
1238     case 4:
1239     return (1024 - (128*ady / adx));/* [315,360) */
1240     }
1241     return 0;
1242     }
1243     static int
1244     int_sqrt(unsigned int n)
1245     {
1246     unsigned int h, p= 0, q= 1, r= n;
1247    
1248     /* avoid q rollover */
1249     if(n >= (1<<(sizeof(n)*8-2))) {
1250     q = 1<<(sizeof(n)*8-2);
1251     } else {
1252     while ( q <= n ) {
1253     q <<= 2;
1254     }
1255     q >>= 2;
1256     }
1257    
1258     while ( q != 0 ) {
1259     h = p + q;
1260     p >>= 1;
1261     if ( r >= h ) {
1262     p += q;
1263     r -= h;
1264     }
1265     q >>= 2;
1266     }
1267     return p;
1268     }
1269    
1270     struct offset {
1271     int px,py,nx,ny;
1272     };
1273    
1274     static void
1275     calc_offsets(int wi, int l, int dx, int dy, struct offset *res)
1276     {
1277     int x,y;
1278    
1279     x = (dx * wi) / l;
1280     y = (dy * wi) / l;
1281     if (x < 0) {
1282     res->nx = -x/2;
1283     res->px = (x-1)/2;
1284     } else {
1285     res->nx = -(x+1)/2;
1286     res->px = x/2;
1287     }
1288     if (y < 0) {
1289     res->ny = -y/2;
1290     res->py = (y-1)/2;
1291     } else {
1292     res->ny = -(y+1)/2;
1293     res->py = y/2;
1294     }
1295     }
1296    
1297     static void
1298     graphics_draw_polyline_as_polygon(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count, int *width, int step, int fill, int order, int oneway)
1299     {
1300     int maxpoints=200;
1301     struct point *res=g_alloca(sizeof(struct point)*maxpoints);
1302     struct point pos, poso, neg, nego;
1303     int i, dx=0, dy=0, l=0, dxo=0, dyo=0;
1304     struct offset o,oo={0,0,0,0};
1305     int fow=0, fowo=0, delta;
1306     int wi, ppos = maxpoints/2, npos = maxpoints/2;
1307     int state,prec=5;
1308     int max_circle_points=20;
1309     int lscale=16;
1310     i=0;
1311     for (;;) {
1312     wi=*width;
1313     width+=step;
1314     if (i < count - 1) {
1315     int dxs,dys,lscales;
1316    
1317     dx = (pnt[i + 1].x - pnt[i].x);
1318     dy = (pnt[i + 1].y - pnt[i].y);
1319     #if 0
1320     l = int_sqrt(dx * dx * lscale * lscale + dy * dy * lscale * lscale);
1321     #else
1322     dxs=dx*dx;
1323     dys=dy*dy;
1324     lscales=lscale*lscale;
1325     if (dxs + dys > lscales)
1326     l = int_sqrt(dxs+dys)*lscale;
1327     else
1328     l = int_sqrt((dxs+dys)*lscales);
1329     #endif
1330     fow=fowler(-dy, dx);
1331     }
1332     if (! l)
1333     l=1;
1334     if (wi*lscale > 10000)
1335     lscale=10000/wi;
1336     dbg_assert(wi*lscale <= 10000);
1337     calc_offsets(wi*lscale, l, dx, dy, &o);
1338     pos.x = pnt[i].x + o.ny;
1339     pos.y = pnt[i].y + o.px;
1340     neg.x = pnt[i].x + o.py;
1341     neg.y = pnt[i].y + o.nx;
1342     if (! i)
1343     state=0;
1344     else if (i == count-1)
1345     state=2;
1346     else if (npos < max_circle_points || ppos >= maxpoints-max_circle_points)
1347     state=3;
1348     else
1349     state=1;
1350     switch (state) {
1351     case 1:
1352     if (fowo != fow) {
1353     poso.x = pnt[i].x + oo.ny;
1354     poso.y = pnt[i].y + oo.px;
1355     nego.x = pnt[i].x + oo.py;
1356     nego.y = pnt[i].y + oo.nx;
1357     delta=fowo-fow;
1358     if (delta < 0)
1359     delta+=1024;
1360     if (delta < 512) {
1361     if (intersection(&pos, dx, dy, &poso, dxo, dyo, &res[ppos]))
1362     ppos++;
1363     res[--npos] = nego;
1364     --npos;
1365     if (fill==1) draw_circle(&pnt[i], wi, prec, fowo-512, -delta, res, &npos, -1);
1366     res[npos] = neg;
1367     } else {
1368     res[ppos++] = poso;
1369     if (fill==1) draw_circle(&pnt[i], wi, prec, fowo, 1024-delta, res, &ppos, 1);
1370     res[ppos++] = pos;
1371     if (intersection(&neg, dx, dy, &nego, dxo, dyo, &res[npos - 1]))
1372     npos--;
1373     }
1374     }
1375     break;
1376     case 2:
1377     case 3:
1378     res[--npos] = neg;
1379     --npos;
1380     if (fill==1) draw_circle(&pnt[i], wi, prec, fow-512, -512, res, &npos, -1);
1381     res[npos] = pos;
1382     res[ppos++] = pos;
1383     dbg_assert(npos > 0);
1384     dbg_assert(ppos < maxpoints);
1385     if (fill==1)
1386     {
1387     gra->meth.draw_polygon2(gra->priv, gc->priv, res+npos, ppos-npos, order, oneway);
1388     }
1389     else
1390     {
1391     gra->meth.draw_lines_dashed(gra->priv, gc->priv, res+npos, ppos-npos, order, oneway);
1392     }
1393     if (state == 2)
1394     break;
1395     npos=maxpoints/2;
1396     ppos=maxpoints/2;
1397     case 0:
1398     res[ppos++] = neg;
1399     if (fill==1) draw_circle(&pnt[i], wi, prec, fow+512, 512, res, &ppos, 1);
1400     res[ppos++] = pos;
1401     break;
1402     }
1403     i++;
1404     if (i >= count)
1405     break;
1406     if (step) {
1407     wi=*width;
1408     calc_offsets(wi*lscale, l, dx, dy, &oo);
1409     } else
1410     oo=o;
1411     dxo = -dx;
1412     dyo = -dy;
1413     fowo=fow;
1414     }
1415     }
1416    
1417    
1418     struct wpoint {
1419     int x,y,w;
1420     };
1421    
1422     static int
1423     clipcode(struct wpoint *p, struct point_rect *r)
1424     {
1425     int code=0;
1426     if (p->x < r->lu.x)
1427     code=1;
1428     if (p->x > r->rl.x)
1429     code=2;
1430     if (p->y < r->lu.y)
1431     code |=4;
1432     if (p->y > r->rl.y)
1433     code |=8;
1434     return code;
1435     }
1436    
1437    
1438     static int
1439     clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1440     {
1441     int code1,code2,ret=1;
1442     int dx,dy,dw;
1443     code1=clipcode(p1, r);
1444     if (code1)
1445     ret |= 2;
1446     code2=clipcode(p2, r);
1447     if (code2)
1448     ret |= 4;
1449     dx=p2->x-p1->x;
1450     dy=p2->y-p1->y;
1451     dw=p2->w-p1->w;
1452     while (code1 || code2) {
1453     if (code1 & code2)
1454     return 0;
1455     if (code1 & 1) {
1456     p1->y+=(r->lu.x-p1->x)*dy/dx;
1457     p1->w+=(r->lu.x-p1->x)*dw/dx;
1458     p1->x=r->lu.x;
1459     } else if (code1 & 2) {
1460     p1->y+=(r->rl.x-p1->x)*dy/dx;
1461     p1->w+=(r->rl.x-p1->x)*dw/dx;
1462     p1->x=r->rl.x;
1463     } else if (code1 & 4) {
1464     p1->x+=(r->lu.y-p1->y)*dx/dy;
1465     p1->w+=(r->lu.y-p1->y)*dw/dy;
1466     p1->y=r->lu.y;
1467     } else if (code1 & 8) {
1468     p1->x+=(r->rl.y-p1->y)*dx/dy;
1469     p1->w+=(r->rl.y-p1->y)*dw/dy;
1470     p1->y=r->rl.y;
1471     }
1472     code1=clipcode(p1, r);
1473     if (code1 & code2)
1474     return 0;
1475     if (code2 & 1) {
1476     p2->y+=(r->lu.x-p2->x)*dy/dx;
1477     p2->w+=(r->lu.x-p2->x)*dw/dx;
1478     p2->x=r->lu.x;
1479     } else if (code2 & 2) {
1480     p2->y+=(r->rl.x-p2->x)*dy/dx;
1481     p2->w+=(r->rl.x-p2->x)*dw/dx;
1482     p2->x=r->rl.x;
1483     } else if (code2 & 4) {
1484     p2->x+=(r->lu.y-p2->y)*dx/dy;
1485     p2->w+=(r->lu.y-p2->y)*dw/dy;
1486     p2->y=r->lu.y;
1487     } else if (code2 & 8) {
1488     p2->x+=(r->rl.y-p2->y)*dx/dy;
1489     p2->w+=(r->rl.y-p2->y)*dw/dy;
1490     p2->y=r->rl.y;
1491     }
1492     code2=clipcode(p2, r);
1493     }
1494     return ret;
1495     }
1496    
1497     static void
1498     graphics_draw_polyline_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pa, int count, int *width, int step, int poly, int order, int oneway)
1499     {
1500     struct point *p=g_alloca(sizeof(struct point)*(count+1));
1501     int *w=g_alloca(sizeof(int)*(count*step+1));
1502     struct wpoint p1,p2;
1503     int i,code,out=0;
1504     int wmax;
1505     struct point_rect r=gra->r;
1506    
1507     wmax=width[0];
1508     if (step) {
1509     for (i = 1 ; i < count ; i++) {
1510     if (width[i*step] > wmax)
1511     wmax=width[i*step];
1512     }
1513     }
1514     if (wmax <= 0)
1515     return;
1516     r.lu.x-=wmax;
1517     r.lu.y-=wmax;
1518     r.rl.x+=wmax;
1519     r.rl.y+=wmax;
1520     for (i = 0 ; i < count ; i++) {
1521     if (i) {
1522     p1.x=pa[i-1].x;
1523     p1.y=pa[i-1].y;
1524     p1.w=width[(i-1)*step];
1525     p2.x=pa[i].x;
1526     p2.y=pa[i].y;
1527     p2.w=width[i*step];
1528     /* 0 = invisible, 1 = completely visible, 3 = start point clipped, 5 = end point clipped, 7 both points clipped */
1529     code=clip_line(&p1, &p2, &r);
1530     if (((code == 1 || code == 5) && i == 1) || (code & 2)) {
1531     p[out].x=p1.x;
1532     p[out].y=p1.y;
1533     w[out*step]=p1.w;
1534     out++;
1535     }
1536     if (code) {
1537     p[out].x=p2.x;
1538     p[out].y=p2.y;
1539     w[out*step]=p2.w;
1540     out++;
1541     }
1542     if (i == count-1 || (code & 4)) {
1543     if (out > 1) {
1544     if (poly==1)
1545     {
1546     // normal street
1547     graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 1, order, 0);
1548     // one way arrow
1549     if (oneway > 0)
1550     {
1551     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1552     }
1553     }
1554     else if (poly==2)
1555     {
1556     // street is underground
1557     graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 0, order, 0);
1558     // one way arrow
1559     if (oneway > 0)
1560     {
1561     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1562     }
1563     }
1564     else // poly==0 -> street that is only a line (width=1)
1565     {
1566     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, 0);
1567     }
1568     out=0;
1569     }
1570     }
1571     }
1572     }
1573     }
1574    
1575     static int
1576     is_inside(struct point *p, struct point_rect *r, int edge)
1577     {
1578     switch(edge) {
1579     case 0:
1580     return p->x >= r->lu.x;
1581     case 1:
1582     return p->x <= r->rl.x;
1583     case 2:
1584     return p->y >= r->lu.y;
1585     case 3:
1586     return p->y <= r->rl.y;
1587     default:
1588     return 0;
1589     }
1590     }
1591    
1592     static void
1593     poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
1594     {
1595     int dx=p2->x-p1->x;
1596     int dy=p2->y-p1->y;
1597     switch(edge) {
1598     case 0:
1599     ret->y=p1->y+(r->lu.x-p1->x)*dy/dx;
1600     ret->x=r->lu.x;
1601     break;
1602     case 1:
1603     ret->y=p1->y+(r->rl.x-p1->x)*dy/dx;
1604     ret->x=r->rl.x;
1605     break;
1606     case 2:
1607     ret->x=p1->x+(r->lu.y-p1->y)*dx/dy;
1608     ret->y=r->lu.y;
1609     break;
1610     case 3:
1611     ret->x=p1->x+(r->rl.y-p1->y)*dx/dy;
1612     ret->y=r->rl.y;
1613     break;
1614     }
1615     }
1616    
1617     static void
1618     graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
1619     {
1620     struct point_rect r=gra->r;
1621     struct point *pout,*p,*s,pi,*p1,*p2;
1622     int limit=10000;
1623     struct point *pa1=g_alloca(sizeof(struct point) * (count_in < limit ? count_in*8+1:0));
1624     struct point *pa2=g_alloca(sizeof(struct point) * (count_in < limit ? count_in*8+1:0));
1625     int count_out,edge=3;
1626     int i;
1627     #if 0
1628     r.lu.x+=20;
1629     r.lu.y+=20;
1630     r.rl.x-=20;
1631     r.rl.y-=20;
1632     #endif
1633     if (count_in < limit) {
1634     p1=pa1;
1635     p2=pa2;
1636     } else {
1637     p1=g_new(struct point, count_in*8+1);
1638     p2=g_new(struct point, count_in*8+1);
1639     }
1640    
1641     pout=p1;
1642     for (edge = 0 ; edge < 4 ; edge++) {
1643     p=pin;
1644     s=pin+count_in-1;
1645     count_out=0;
1646     for (i = 0 ; i < count_in ; i++) {
1647     if (is_inside(p, &r, edge)) {
1648     if (! is_inside(s, &r, edge)) {
1649     poly_intersection(s,p,&r,edge,&pi);
1650     pout[count_out++]=pi;
1651     }
1652     pout[count_out++]=*p;
1653     } else {
1654     if (is_inside(s, &r, edge)) {
1655     poly_intersection(p,s,&r,edge,&pi);
1656     pout[count_out++]=pi;
1657     }
1658     }
1659     s=p;
1660     p++;
1661     }
1662     count_in=count_out;
1663     if (pin == p1) {
1664     pin=p2;
1665     pout=p1;
1666     } else {
1667     pin=p1;
1668     pout=p2;
1669     }
1670     }
1671     gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
1672     if (count_in >= limit) {
1673     g_free(p1);
1674     g_free(p2);
1675     }
1676     }
1677    
1678    
1679     static void
1680     display_context_free(struct display_context *dc)
1681     {
1682     if (dc->gc)
1683     graphics_gc_destroy(dc->gc);
1684     if (dc->gc_background)
1685     graphics_gc_destroy(dc->gc_background);
1686     if (dc->img)
1687     graphics_image_free(dc->gra, dc->img);
1688     dc->gc=NULL;
1689     dc->gc_background=NULL;
1690     dc->img=NULL;
1691     }
1692    
1693     static struct graphics_font *
1694     get_font(struct graphics *gra, int size)
1695     {
1696     if (size > 64)
1697     size=64;
1698     if (size >= gra->font_len) {
1699     gra->font=g_renew(struct graphics_font *, gra->font, size+1);
1700     while (gra->font_len <= size)
1701     gra->font[gra->font_len++]=NULL;
1702     }
1703     if (! gra->font[size])
1704     gra->font[size]=graphics_font_new(gra, size*gra->font_size, 0);
1705     return gra->font[size];
1706     }
1707    
1708     void graphics_draw_text_std(struct graphics *this_, int text_size, char *text, struct point *p)
1709     {
1710     struct graphics_font *font=get_font(this_, text_size);
1711     struct point bbox[4];
1712     int i;
1713    
1714     graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
1715     for (i = 0 ; i < 4 ; i++) {
1716     bbox[i].x+=p->x;
1717     bbox[i].y+=p->y;
1718     }
1719     graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x-bbox[0].x, bbox[0].y-bbox[1].y+5);
1720     graphics_draw_text(this_, this_->gc[1], this_->gc[2], font, text, p, 0x10000, 0);
1721     }
1722    
1723     char *
1724     graphics_icon_path(char *icon)
1725     {
1726     static char *navit_sharedir;
1727     char *ret=NULL;
1728     struct file_wordexp *wordexp=NULL;
1729     dbg(1,"enter %s\n",icon);
1730     if (strchr(icon, '$')) {
1731     wordexp=file_wordexp_new(icon);
1732     if (file_wordexp_get_count(wordexp))
1733     icon=file_wordexp_get_array(wordexp)[0];
1734     }
1735     if (strchr(icon,'/'))
1736     ret=g_strdup(icon);
1737     else {
1738     #ifdef HAVE_API_ANDROID
1739     // get resources for the correct screen density
1740     //
1741     // this part not needed, android unpacks only the correct version into res/drawable dir!
1742     // dbg(1,"android icon_path %s\n",icon);
1743     // static char *android_density;
1744     // android_density = getenv("ANDROID_DENSITY");
1745     // ret=g_strdup_printf("res/drawable-%s/%s",android_density ,icon);
1746     ret=g_strdup_printf("res/drawable/%s" ,icon);
1747     #else
1748     if (! navit_sharedir)
1749     navit_sharedir = getenv("NAVIT_SHAREDIR");
1750     ret=g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
1751     #endif
1752     }
1753     if (wordexp)
1754     file_wordexp_destroy(wordexp);
1755     return ret;
1756     }
1757    
1758     static int
1759     limit_count(struct coord *c, int count)
1760     {
1761     int i;
1762     for (i = 1 ; i < count ; i++) {
1763     if (c[i].x == c[0].x && c[i].y == c[0].y)
1764     return i+1;
1765     }
1766     return count;
1767     }
1768    
1769    
1770     static void
1771     displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc, int order, int allow_dashed)
1772     {
1773     //dbg(0,"ooo enter ooo\n");
1774    
1775     int *width=g_alloca(sizeof(int)*dc->maxlen);
1776     struct point *pa=g_alloca(sizeof(struct point)*dc->maxlen);
1777     struct graphics *gra=dc->gra;
1778     struct graphics_gc *gc=dc->gc;
1779     struct element *e=dc->e;
1780     struct graphics_image *img=dc->img;
1781     struct point p;
1782     char *path;
1783    
1784     // dbg(0,"enter\n");
1785    
1786     while (di)
1787     {
1788     int i,count=di->count,mindist=dc->mindist;
1789    
1790     if (! gc)
1791     {
1792     gc=graphics_gc_new(gra);
1793     graphics_gc_set_foreground(gc, &e->color);
1794     dc->gc=gc;
1795     }
1796    
1797     if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
1798     count=limit_count(di->c, count);
1799     if (dc->type == type_poly_water_tiled)
1800     mindist=0;
1801     if (dc->e->type == element_polyline)
1802     count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
1803     else
1804     count=transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
1805    
1806    
1807     switch (e->type)
1808     {
1809     case element_polygon:
1810     graphics_draw_polygon_clipped(gra, gc, pa, count);
1811     break;
1812     case element_polyline:
1813     // dbg(0,"draw element_polyline");
1814     {
1815     gc->meth.gc_set_linewidth(gc->priv, 1);
1816    
1817     int poly=e->u.polyline.width > 1;
1818    
1819     // detect underground streets/lines/etc ...
1820     if ((allow_dashed)&&(di->item.flags & AF_UNDERGROUND))
1821     {
1822     // dbg(0,"flags=AF_UNDERGROUND=%d\n",di->item.flags);
1823     poly=2;
1824     }
1825    
1826     int oneway=0;
1827    
1828     if (di->item.flags & AF_ONEWAYREV)
1829     {
1830     oneway=2;
1831     }
1832     else if (di->item.flags & AF_ONEWAY)
1833     {
1834     oneway=1;
1835     }
1836    
1837     if (e->u.polyline.width > 0 && e->u.polyline.dash_num > 0)
1838     {
1839     graphics_gc_set_dashes(gc, e->u.polyline.width,
1840     e->u.polyline.offset,
1841     e->u.polyline.dash_table,
1842     e->u.polyline.dash_num);
1843     }
1844     for (i = 0 ; i < count ; i++)
1845     {
1846     if (width[i] < 2)
1847     width[i]=2;
1848     }
1849     graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway);
1850     }
1851     break;
1852     case element_circle:
1853     if (count)
1854     {
1855     if (e->u.circle.width > 1)
1856     gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
1857    
1858     graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
1859    
1860     if (di->label && e->text_size)
1861     {
1862     struct graphics_font *font=get_font(gra, e->text_size);
1863     struct graphics_gc *gc_background=dc->gc_background;
1864     if (! gc_background && e->u.circle.background_color.a) {
1865     gc_background=graphics_gc_new(gra);
1866     graphics_gc_set_foreground(gc_background, &e->u.circle.background_color);
1867     dc->gc_background=gc_background;
1868     }
1869     p.x=pa[0].x+3;
1870     p.y=pa[0].y+10;
1871    
1872     if (font)
1873     gra->meth.draw_text(gra->priv, gc->priv, gc_background?gc_background->priv:NULL, font->priv, di->label, &p, 0x10000, 0);
1874     else
1875     dbg(0,"Failed to get font with size %d\n",e->text_size);
1876     }
1877     }
1878     break;
1879     case element_text:
1880     if (count && di->label)
1881     {
1882     struct graphics_font *font=get_font(gra, e->text_size);
1883     struct graphics_gc *gc_background=dc->gc_background;
1884    
1885     if (! gc_background && e->u.text.background_color.a)
1886     {
1887     gc_background=graphics_gc_new(gra);
1888     graphics_gc_set_foreground(gc_background, &e->u.text.background_color);
1889     dc->gc_background=gc_background;
1890     }
1891    
1892     if (font)
1893     label_line(gra, gc, gc_background, font, pa, count, di->label);
1894     else
1895     dbg(0,"Failed to get font with size %d\n",e->text_size);
1896     }
1897     break;
1898     case element_icon:
1899     if (count)
1900     {
1901     if (!img || item_is_custom_poi(di->item))
1902     {
1903     if (item_is_custom_poi(di->item))
1904     {
1905     char *icon;
1906     char *src;
1907     if (img)
1908     graphics_image_free(dc->gra, img);
1909     src=e->u.icon.src;
1910     if (!src || !src[0])
1911     src="%s";
1912     icon=g_strdup_printf(src,di->label+strlen(di->label)+1);
1913     path=graphics_icon_path(icon);
1914     g_free(icon);
1915     }
1916     else
1917     {
1918     path=graphics_icon_path(e->u.icon.src);
1919     }
1920     img=graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
1921     if (img)
1922     dc->img=img;
1923     else
1924     dbg(0,"failed to load icon '%s'\n", path);
1925     g_free(path);
1926     }
1927     if (img)
1928     {
1929     p.x=pa[0].x - img->hot.x;
1930     p.y=pa[0].y - img->hot.y;
1931     gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
1932     }
1933     }
1934     break;
1935     case element_image:
1936     dbg(1,"image: '%s'\n", di->label);
1937     if (gra->meth.draw_image_warp)
1938     gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
1939     else
1940     dbg(0,"draw_image_warp not supported by graphics driver drawing '%s'\n", di->label);
1941     break;
1942     case element_arrows:
1943     display_draw_arrows(gra,gc,pa,count);
1944     break;
1945     default:
1946     printf("Unhandled element type %d\n", e->type);
1947    
1948     }
1949     di=di->next;
1950     }
1951     }
1952     /**
1953     * FIXME
1954     * @param <>
1955     * @returns <>
1956     * @author Martin Schaller (04/2008)
1957     */
1958     static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm)
1959     {
1960    
1961     struct element *e;
1962     GList *es,*types;
1963     struct display_context *dc=&display_list->dc;
1964     struct hash_entry *entry;
1965    
1966     es=itm->elements;
1967     while (es)
1968     {
1969     e=es->data;
1970     dc->e=e;
1971     types=itm->type;
1972     while (types)
1973     {
1974     dc->type=GPOINTER_TO_INT(types->data);
1975     entry=get_hash_entry(display_list, dc->type);
1976     if (entry && entry->di)
1977     {
1978     displayitem_draw(entry->di, NULL, dc, display_list->order, 1);
1979     display_context_free(dc);
1980     }
1981     types=g_list_next(types);
1982     }
1983     es=g_list_next(es);
1984     }
1985     }
1986    
1987     void
1988     graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
1989     {
1990     //dbg(0,"ooo enter ooo\n");
1991    
1992     // HINT: seems to only be called from vehicle.c (draw the vehicle on screen)
1993    
1994     GList *es;
1995     struct display_context dc;
1996     int max_coord=32;
1997     char *buffer=g_alloca(sizeof(struct displayitem)+max_coord*sizeof(struct coord));
1998     struct displayitem *di=(struct displayitem *)buffer;
1999     es=itm->elements;
2000     di->item.type=type_none;
2001     di->item.id_hi=0;
2002     di->item.id_lo=0;
2003     di->item.map=NULL;
2004     di->label=label;
2005     dc.gra=gra;
2006     dc.gc=NULL;
2007     dc.gc_background=NULL;
2008     dc.img=NULL;
2009     dc.pro=projection_screen;
2010     dc.mindist=0;
2011     dc.trans=t;
2012     dc.type=type_none;
2013     dc.maxlen=max_coord;
2014     while (es) {
2015     struct element *e=es->data;
2016     if (e->coord_count) {
2017     if (e->coord_count > max_coord) {
2018     dbg(0,"maximum number of coords reached: %d > %d\n",e->coord_count,max_coord);
2019     di->count=max_coord;
2020     } else
2021     di->count=e->coord_count;
2022     memcpy(di->c, e->coord, di->count*sizeof(struct coord));
2023     } else {
2024     di->c[0].x=0;
2025     di->c[0].y=0;
2026     di->count=1;
2027     }
2028     dc.e=e;
2029     di->next=NULL;
2030     displayitem_draw(di, NULL, &dc,transform_get_scale(t), 0);
2031     display_context_free(&dc);
2032     es=g_list_next(es);
2033     }
2034     }
2035    
2036     /**
2037     * FIXME
2038     * @param <>
2039     * @returns <>
2040     * @author Martin Schaller (04/2008)
2041     */
2042     static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order)
2043     {
2044     //dbg(0,"ooo enter ooo\n");
2045    
2046     GList *itms;
2047     struct itemgra *itm;
2048     int order_corrected=order;
2049     if (order_corrected < 0)
2050     {
2051     order_corrected=0;
2052     }
2053    
2054     itms=lay->itemgras;
2055     while (itms)
2056     {
2057     itm=itms->data;
2058     if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2059     {
2060     xdisplay_draw_elements(gra, display_list, itm);
2061     }
2062     itms=g_list_next(itms);
2063     }
2064     }
2065    
2066    
2067    
2068    
2069     /**
2070     * FIXME
2071     * @param <>
2072     * @returns <>
2073     * @author Martin Schaller (04/2008)
2074     */
2075     static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
2076     {
2077     //dbg(0,"ooo enter ooo\n");
2078    
2079     GList *lays;
2080     struct layer *lay;
2081    
2082     //dbg(0,"draw prerender map for drag!!\n");
2083    
2084    
2085     int draw_vector_map=1;
2086    
2087     // if zoomed out too much then use prerendered map tiles
2088     if (display_list->order < ORDER_USE_PRERENDERED_MAP )
2089     {
2090     draw_vector_map=0;
2091     }
2092    
2093     //dbg(0,"ooo %d %d %d\n",display_list->order_hashed,ORDER_USE_PRERENDERED_MAP,draw_vector_map);
2094     //dbg(0,"ooo xxx ooo2\n");
2095    
2096     if (!draw_vector_map)
2097     {
2098     // draw prerendered big mapimage --- HERE ---
2099    
2100     //dbg(0,"###### order=%d\n",display_list->order);
2101     struct transformation *t;
2102     t=display_list->dc.trans;
2103     //dbg(0,"###### screen center x=%d\n",t->screen_center.x);
2104     //dbg(0,"###### screen center y=%d\n",t->screen_center.y);
2105    
2106     struct coord *cp;
2107     cp=transform_get_center(t);
2108     //dbg(0,"###### t center x=%d\n",cp->x);
2109     //dbg(0,"###### t center y=%d\n",cp->y);
2110    
2111     struct attr attr;
2112     struct config {
2113     struct attr **attrs;
2114     struct callback_list *cbl;
2115     } *config;
2116     struct point p;
2117     int valid=0;
2118     // config_get_attr(config, attr_navit, &attr, NULL);
2119     if (global_navit)
2120     {
2121     if ((global_navit->vehicle)&&(global_navit->vehicle->vehicle))
2122     {
2123     //dbg(0,"###### v x=%d\n",p.x);
2124     //dbg(0,"###### v y=%d\n",p.y);
2125    
2126     //dbg(0,"###### v2 x=%d\n",global_vehicle_pos_onscreen.x);
2127     //dbg(0,"###### v2 y=%d\n",global_vehicle_pos_onscreen.y);
2128    
2129     //dbg(0,"### vf x=%d\n",global_navit->vehicle->last.x);
2130     //dbg(0,"### vf y=%d\n",global_navit->vehicle->last.y);
2131    
2132     //dbg(0,"### vff x=%d\n",global_navit->vehicle->coord.x);
2133     //dbg(0,"### vff y=%d\n",global_navit->vehicle->coord.y);
2134    
2135     int a,s;
2136     struct point pnt2;
2137     vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
2138     //dbg(0,"### vf 2 x=%d\n",pnt2.x);
2139     //dbg(0,"### vf 2 y=%d\n",pnt2.y);
2140     //global_vehicle_pos_onscreen.x=pnt2.x;
2141     //global_vehicle_pos_onscreen.y=pnt2.y;
2142    
2143    
2144    
2145     struct attr pos_attr;
2146     if (vehicle_get_attr(global_navit->vehicle->vehicle,attr_position_coord_geo,&pos_attr,NULL))
2147     {
2148     //dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
2149     }
2150    
2151     valid=1;
2152     }
2153     }
2154    
2155     //dbg(0,"###### yaw=%d\n",-t->yaw);
2156     struct coord *c;
2157     c=&(t->map_center);
2158     //dbg(0,"###### map center x=%d\n",c->x);
2159     //dbg(0,"###### map center y=%d\n",c->y);
2160    
2161     enum projection pro=transform_get_projection(global_navit->trans_cursor);
2162     struct coord_geo g22;
2163     struct coord *c22;
2164     struct point mcenter_pnt;
2165     c22=&(t->map_center);
2166     transform_to_geo(projection_mg, c22, &g22);
2167     //dbg(0,"2 lat=%f, lng=%f\n",g22.lat,g22.lng);
2168     transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
2169     //dbg(0,"xxx 5 44444xxxx=%d\n",mcenter_pnt.x);
2170     //dbg(0,"yyy 5 44444yyyy=%d\n",mcenter_pnt.y);
2171    
2172    
2173     struct coord c99;
2174     struct coord_geo g99;
2175     struct point cursor_pnt;
2176     struct point p99;
2177    
2178     /*
2179     g99.lat=79.0;
2180     g99.lng=-170.0;
2181     transform_from_geo(pro, &g99, &c99);
2182     dbg(0,"left top lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2183     //dbg(0,"left top lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2184     //dbg(0,"0x%x,0x%x\n",c99.x,c99.y);
2185     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2186     dbg(0,"xxxxxxx=%d\n",cursor_pnt.x);
2187     dbg(0,"yyyyyyy=%d\n",cursor_pnt.y);
2188    
2189     g99.lat=-79.0;
2190     g99.lng=170.0;
2191     transform_from_geo(pro, &g99, &c99);
2192     dbg(0,"right bottom lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2193     //dbg(0,"right bottom lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2194     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2195     dbg(0,"xxxxxxx=%d\n",cursor_pnt.x);
2196     dbg(0,"yyyyyyy=%d\n",cursor_pnt.y);
2197     */
2198    
2199     g99.lat=0.0;
2200     g99.lng=0.0;
2201     transform_from_geo(pro, &g99, &c99);
2202     //dbg(0,"center center lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2203     //dbg(0,"center center lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2204     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2205     //dbg(0,"xxx44444xxxx=%d\n",cursor_pnt.x);
2206     //dbg(0,"yyy44444yyyy=%d\n",cursor_pnt.y);
2207    
2208     //struct coord *c77;
2209     //c77=&(t->map_center);
2210     //transform(global_navit->trans, pro, &c77, &cursor_pnt, 1, 0, 0, NULL);
2211     //dbg(0,"---> cx=%d\n",cursor_pnt.x);
2212     //dbg(0,"---> cy=%d\n",cursor_pnt.y);
2213    
2214    
2215     // now really draw it
2216     struct graphics *gra22=display_list->dc.gra;
2217     struct graphics_gc *gc22=display_list->dc.gc;
2218     if (! gc22)
2219     {
2220     gc22=graphics_gc_new(gra22);
2221     }
2222     // graphics_draw_bigmap(gra22, gc22, -t->yaw, display_list->order, g22.lat, g22.lng, c->x, c->y, t->screen_center.x, t->screen_center.y, global_vehicle_pos_onscreen.x, global_vehicle_pos_onscreen.y, valid);
2223     graphics_draw_bigmap(gra22, gc22, -t->yaw, display_list->order, g22.lat, g22.lng, cursor_pnt.x, cursor_pnt.y, mcenter_pnt.x, mcenter_pnt.y, global_vehicle_pos_onscreen.x, global_vehicle_pos_onscreen.y, valid);
2224     }
2225    
2226    
2227    
2228     lays=l->layers;
2229     while (lays) {
2230     lay=lays->data;
2231     if (lay->active)
2232     xdisplay_draw_layer(display_list, gra, lay, order);
2233     lays=g_list_next(lays);
2234     }
2235    
2236     #ifdef HAVE_API_ANDROID
2237     android_return_generic_int(2, 1);
2238     #endif
2239    
2240     }
2241    
2242     /**
2243     * FIXME
2244     * @param <>
2245     * @returns <>
2246     * @author Martin Schaller (04/2008)
2247     */
2248     extern void *route_selection;
2249    
2250     static void
2251     displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
2252     {
2253     //dbg(0,"ooo enter ooo\n");
2254    
2255     int order_corrected=order;
2256     //int saved=displaylist->order;
2257     if (order < 0)
2258     {
2259     order_corrected=0;
2260     // displaylist->order=0;
2261     }
2262     while (layers) {
2263     struct layer *layer=layers->data;
2264     GList *itemgras=layer->itemgras;
2265     while (itemgras) {
2266     struct itemgra *itemgra=itemgras->data;
2267     GList *types=itemgra->type;
2268     if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
2269     {
2270     while (types) {
2271     enum item_type type=(enum item_type) types->data;
2272     set_hash_entry(displaylist, type);
2273     types=g_list_next(types);
2274     }
2275     }
2276     itemgras=g_list_next(itemgras);
2277     }
2278     layers=g_list_next(layers);
2279     }
2280     // displaylist->order=saved;
2281     }
2282    
2283     static void
2284     displaylist_update_hash(struct displaylist *displaylist)
2285     {
2286     //dbg(0,"ooo enter ooo\n");
2287    
2288     displaylist->max_offset=0;
2289     clear_hash(displaylist);
2290     displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
2291     dbg(1,"max offset %d\n",displaylist->max_offset);
2292     }
2293    
2294     static void
2295     do_draw(struct displaylist *displaylist, int cancel, int flags)
2296     {
2297     struct item *item;
2298     int count,max=displaylist->dc.maxlen,workload=0;
2299     struct coord *ca=g_alloca(sizeof(struct coord)*max);
2300     struct attr attr,attr2;
2301     enum projection pro;
2302     int draw_vector_map=1; // do we draw the vecotor map, or not? 0=false, 1=true
2303     int mapset_counter=0;
2304     int mapset_need_draw=0;
2305    
2306     //dbg(0,"ooo enter ooo %d\n",displaylist->order);
2307    
2308     int order_corrected=displaylist->order;
2309     int saved=displaylist->order;
2310     if (order_corrected < 0)
2311     {
2312     order_corrected = 0;
2313     }
2314    
2315     if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
2316     {
2317     displaylist_update_hash(displaylist);
2318     displaylist->order_hashed=displaylist->order;
2319     displaylist->layout_hashed=displaylist->layout;
2320    
2321     // dbg(0,"-----====> order (zoom) = %d",displaylist->order);
2322     // dbg(0,"-----====> order (zoom) = %d",displaylist->order_hashed);
2323     // TODO // give new order (zoom) back to Java // TODO
2324     }
2325    
2326     profile(0,NULL);
2327     pro=transform_get_projection(displaylist->dc.trans);
2328    
2329     // dbg(0,"ooo xxx ooo1\n");
2330     // dbg(0,"ooo %d %d %d\n",displaylist->order_hashed,ORDER_USE_PRERENDERED_MAP,draw_vector_map);
2331    
2332     // if zoomed out too much then use prerendered map tiles
2333     if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP )
2334     {
2335     draw_vector_map=0;
2336     }
2337    
2338     // dbg(0,"ooo %d %d %d\n",displaylist->order_hashed,ORDER_USE_PRERENDERED_MAP,draw_vector_map);
2339     // dbg(0,"ooo xxx ooo2\n");
2340    
2341     if (!draw_vector_map)
2342     {
2343     // draw prerendered big mapimage --- HERE ---
2344    
2345     //dbg(0,"###### order=%d\n",displaylist->order_hashed);
2346     struct transformation *t;
2347     t=displaylist->dc.trans;
2348     //dbg(0,"###### screen center x=%d\n",t->screen_center.x);
2349     //dbg(0,"###### screen center y=%d\n",t->screen_center.y);
2350    
2351     struct coord *cp;
2352     cp=transform_get_center(t);
2353     //dbg(0,"###### t center x=%d\n",cp->x);
2354     //dbg(0,"###### t center y=%d\n",cp->y);
2355    
2356     struct attr attr;
2357     struct config {
2358     struct attr **attrs;
2359     struct callback_list *cbl;
2360     } *config;
2361     struct point p;
2362     int valid=0;
2363     // config_get_attr(config, attr_navit, &attr, NULL);
2364     if (global_navit)
2365     {
2366     if ((global_navit->vehicle)&&(global_navit->vehicle->vehicle))
2367     {
2368     //dbg(0,"###### v x=%d\n",p.x);
2369     //dbg(0,"###### v y=%d\n",p.y);
2370    
2371     //dbg(0,"###### v2 x=%d\n",global_vehicle_pos_onscreen.x);
2372     //dbg(0,"###### v2 y=%d\n",global_vehicle_pos_onscreen.y);
2373    
2374     //dbg(0,"### vf x=%d\n",global_navit->vehicle->last.x);
2375     //dbg(0,"### vf y=%d\n",global_navit->vehicle->last.y);
2376    
2377     //dbg(0,"### vff x=%d\n",global_navit->vehicle->coord.x);
2378     //dbg(0,"### vff y=%d\n",global_navit->vehicle->coord.y);
2379    
2380     int a,s;
2381     struct point pnt2;
2382     vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
2383     //dbg(0,"### vf 2 x=%d\n",pnt2.x);
2384     //dbg(0,"### vf 2 y=%d\n",pnt2.y);
2385     //global_vehicle_pos_onscreen.x=pnt2.x;
2386     //global_vehicle_pos_onscreen.y=pnt2.y;
2387    
2388     struct attr pos_attr;
2389     if (vehicle_get_attr(global_navit->vehicle->vehicle,attr_position_coord_geo,&pos_attr,NULL))
2390     {
2391     //dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
2392     }
2393    
2394     valid=1;
2395     }
2396     }
2397    
2398     //dbg(0,"###### yaw=%d\n",-t->yaw);
2399     struct coord *c;
2400     c=&(t->map_center);
2401     //dbg(0,"###### map center x=%d\n",c->x);
2402     //dbg(0,"###### map center y=%d\n",c->y);
2403    
2404     enum projection pro=transform_get_projection(global_navit->trans_cursor);
2405     struct coord_geo g22;
2406     struct coord *c22;
2407     struct point mcenter_pnt;
2408     c22=&(t->map_center);
2409     transform_to_geo(projection_mg, c22, &g22);
2410     //dbg(0,"2 lat=%f, lng=%f\n",g22.lat,g22.lng);
2411     transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
2412     //dbg(0,"xxx 5 33333xxxx=%d\n",mcenter_pnt.x);
2413     //dbg(0,"yyy 5 33333yyyy=%d\n",mcenter_pnt.y);
2414    
2415    
2416     struct coord c99;
2417     struct coord_geo g99;
2418     struct point cursor_pnt;
2419     struct point p99;
2420    
2421     /*
2422     g99.lat=79.0;
2423     g99.lng=-170.0;
2424     transform_from_geo(pro, &g99, &c99);
2425     dbg(0,"left top lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2426     //dbg(0,"left top lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2427     //dbg(0,"0x%x,0x%x\n",c99.x,c99.y);
2428     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2429     dbg(0,"xxxxxxx=%d\n",cursor_pnt.x);
2430     dbg(0,"yyyyyyy=%d\n",cursor_pnt.y);
2431    
2432     g99.lat=-79.0;
2433     g99.lng=170.0;
2434     transform_from_geo(pro, &g99, &c99);
2435     dbg(0,"right bottom lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2436     //dbg(0,"right bottom lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2437     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2438     dbg(0,"xxxxxxx=%d\n",cursor_pnt.x);
2439     dbg(0,"yyyyyyy=%d\n",cursor_pnt.y);
2440     */
2441    
2442     g99.lat=0.0;
2443     g99.lng=0.0;
2444     transform_from_geo(pro, &g99, &c99);
2445     //dbg(0,"center center lat=%f, lng=%f, x=%d y=%d\n",g99.lat,g99.lng,c99.x,c99.y);
2446     //dbg(0,"center center lat=%f, lng=%f, x=%f y=%f\n",g99.lat,g99.lng,c99.x,c99.y);
2447     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2448     //dbg(0,"xxxx333xxx=%d\n",cursor_pnt.x);
2449     //dbg(0,"yyyy333yyy=%d\n",cursor_pnt.y);
2450    
2451     //struct coord *c77;
2452     //c77=&(t->map_center);
2453     //transform(global_navit->trans, pro, &c77, &cursor_pnt, 1, 0, 0, NULL);
2454     //dbg(0,"---> cx=%d\n",cursor_pnt.x);
2455     //dbg(0,"---> cy=%d\n",cursor_pnt.y);
2456    
2457    
2458     // now really draw it
2459     struct graphics *gra22=displaylist->dc.gra;
2460     struct graphics_gc *gc22=displaylist->dc.gc;
2461     if (! gc22)
2462     {
2463     gc22=graphics_gc_new(gra22);
2464     }
2465     graphics_draw_bigmap(gra22, gc22, -t->yaw, displaylist->order, g22.lat, g22.lng, cursor_pnt.x, cursor_pnt.y, mcenter_pnt.x, mcenter_pnt.y, global_vehicle_pos_onscreen.x, global_vehicle_pos_onscreen.y, valid);
2466     }
2467    
2468     //dbg(0,"xxx uuu xxx\n");
2469    
2470     displaylist->order=order_corrected;
2471    
2472     while (!cancel)
2473     {
2474     if (!displaylist->msh)
2475     displaylist->msh=mapset_open(displaylist->ms);
2476     if (!displaylist->m) {
2477     displaylist->m=mapset_next(displaylist->msh, 1);
2478     if (!displaylist->m) {
2479     mapset_close(displaylist->msh);
2480     displaylist->msh=NULL;
2481     break;
2482     }
2483    
2484     mapset_counter++;
2485     mapset_need_draw=1;
2486     struct attr map_name_attr;
2487     if(map_get_attr(displaylist->m,attr_name, &map_name_attr,NULL))
2488     {
2489     // dbg(0,"map name=%s",map_name_attr.u.str);
2490     if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
2491     {
2492     if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
2493     {
2494     // if its the countryborder map, always draw it
2495     mapset_need_draw=0; // --> now dont even draw borders on low zoom level, we have prerendered image
2496     }
2497     else
2498     {
2499     // if its an sdcard street map, don't draw it
2500     mapset_need_draw=0;
2501     }
2502     }
2503     }
2504    
2505     //dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
2506    
2507     displaylist->dc.pro=map_projection(displaylist->m);
2508     displaylist->conv=map_requires_conversion(displaylist->m);
2509     if (route_selection)
2510     {
2511     displaylist->sel=route_selection;
2512     }
2513     else
2514     {
2515     displaylist->sel=transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
2516     }
2517     displaylist->mr=map_rect_new(displaylist->m, displaylist->sel);
2518     }
2519     if (displaylist->mr)
2520     {
2521     // draw vector map, or not?
2522     // dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
2523     if ((draw_vector_map) || (mapset_need_draw == 1))
2524     {
2525     while ((item=map_rect_get_item(displaylist->mr)))
2526     {
2527     int label_count=0;
2528     char *labels[2];
2529     struct hash_entry *entry;
2530    
2531     if (item == &busy_item)
2532     {
2533     if (displaylist->workload)
2534     {
2535     // restore order :-)
2536     displaylist->order=saved;
2537     return;
2538     }
2539     else
2540     continue;
2541     }
2542    
2543     entry=get_hash_entry(displaylist, item->type);
2544    
2545     if (!entry)
2546     continue;
2547    
2548     count=item_coord_get_within_selection(item, ca, item->type < type_line ? 1: max, displaylist->sel);
2549    
2550     if (! count)
2551     continue;
2552    
2553     if (displaylist->dc.pro != pro)
2554     transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
2555    
2556     if (count == max)
2557     {
2558     dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
2559     displaylist->dc.maxlen=max*2;
2560     }
2561    
2562     if (item_is_custom_poi(*item))
2563     {
2564     if (item_attr_get(item, attr_icon_src, &attr2))
2565     labels[1]=map_convert_string(displaylist->m, attr2.u.str);
2566     else
2567     labels[1]=NULL;
2568     label_count=2;
2569     }
2570     else
2571     {
2572     labels[1]=NULL;
2573     label_count=0;
2574     }
2575    
2576     if (item_attr_get(item, attr_label, &attr))
2577     {
2578     labels[0]=attr.u.str;
2579     if (!label_count)
2580     label_count=2;
2581     }
2582     else
2583     {
2584     labels[0]=NULL;
2585     }
2586    
2587    
2588     //item_dump_attr_stdout(item, displaylist->m);
2589     struct attr attr_77;
2590     if (item_attr_get(item, attr_flags, &attr_77))
2591     {
2592     // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
2593     item->flags=attr_77.u.num;
2594     }
2595     else
2596     {
2597     item->flags=0;
2598     }
2599    
2600    
2601     //struct attr *attr88;
2602     //if (item_attr_get(item, attr_flags, &attr88))
2603     //{
2604     //dbg(0,"item flags=%d\n",attr88->u.num);
2605     //}
2606     //attr88=NULL;
2607    
2608     if (displaylist->conv && label_count)
2609     {
2610     labels[0]=map_convert_string(displaylist->m, labels[0]);
2611     display_add(entry, item, count, ca, labels, label_count);
2612     map_convert_free(labels[0]);
2613     }
2614     else
2615     {
2616     display_add(entry, item, count, ca, labels, label_count);
2617     }
2618    
2619     if (labels[1])
2620     {
2621     map_convert_free(labels[1]);
2622     }
2623    
2624     workload++;
2625    
2626     if (workload == displaylist->workload)
2627     {
2628     // restore order :-)
2629     displaylist->order=saved;
2630     return;
2631     }
2632     }
2633     map_rect_destroy(displaylist->mr);
2634     }
2635     }
2636    
2637     if (!route_selection)
2638     {
2639     map_selection_destroy(displaylist->sel);
2640     }
2641    
2642     displaylist->mr=NULL;
2643     displaylist->sel=NULL;
2644     displaylist->m=NULL;
2645     } // while ----
2646    
2647     // restore order :-)
2648     displaylist->order=saved;
2649    
2650     profile(1,"process_selection\n");
2651     if (displaylist->idle_ev)
2652     event_remove_idle(displaylist->idle_ev);
2653     displaylist->idle_ev=NULL;
2654     callback_destroy(displaylist->idle_cb);
2655     displaylist->idle_cb=NULL;
2656     displaylist->busy=0;
2657    
2658     // graphics_process_selection(displaylist->dc.gra, displaylist);
2659    
2660     profile(1,"draw\n");
2661     if (! cancel)
2662     {
2663     int flags2 = flags;
2664     if (!(flags2 & 2))
2665     {
2666     if (!draw_vector_map)
2667     {
2668     // dont clean bg of screen when drawing prerendered tiles
2669     flags2 = flags2 + 2;
2670     }
2671     }
2672     // dbg(0,"call graphics_displaylist_draw 3")
2673     graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
2674     }
2675    
2676     #ifdef HAVE_API_ANDROID
2677     android_return_generic_int(2, 0);
2678     #endif
2679    
2680    
2681     map_rect_destroy(displaylist->mr);
2682     if (!route_selection)
2683     map_selection_destroy(displaylist->sel);
2684     mapset_close(displaylist->msh);
2685     displaylist->mr=NULL;
2686     displaylist->sel=NULL;
2687     displaylist->m=NULL;
2688     displaylist->msh=NULL;
2689     profile(1,"callback\n");
2690     callback_call_1(displaylist->cb, cancel);
2691     profile(0,"end\n");
2692     }
2693    
2694     /**
2695     * FIXME
2696     * @param <>
2697     * @returns <>
2698     * @author Martin Schaller (04/2008)
2699     */
2700     void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
2701     {
2702     //dbg(0,"ooo enter ooo\n");
2703    
2704     int order=transform_get_order(trans);
2705     displaylist->dc.trans=trans;
2706     displaylist->dc.gra=gra;
2707     displaylist->dc.mindist=transform_get_scale(trans)/2;
2708     // FIXME find a better place to set the background color
2709     if (l)
2710     {
2711     graphics_gc_set_background(gra->gc[0], &l->color);
2712     graphics_gc_set_foreground(gra->gc[0], &l->color);
2713     gra->default_font = g_strdup(l->font);
2714     }
2715     graphics_background_gc(gra, gra->gc[0]);
2716     if (flags & 1)
2717     {
2718     callback_list_call_attr_0(gra->cbl, attr_predraw);
2719     }
2720     gra->meth.draw_mode(gra->priv, (flags & 8)?draw_mode_begin_clear:draw_mode_begin);
2721     if (!(flags & 2))
2722     {
2723     // clear the display/screen/whatever here
2724     gra->meth.draw_rectangle(gra->priv, gra->gc[0]->priv, &gra->r.lu, gra->r.rl.x-gra->r.lu.x, gra->r.rl.y-gra->r.lu.y);
2725     }
2726     if (l)
2727     {
2728     // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
2729     xdisplay_draw(displaylist, gra, l, order+l->order_delta);
2730     }
2731     if (flags & 1)
2732     {
2733     callback_list_call_attr_0(gra->cbl, attr_postdraw);
2734     }
2735     if (!(flags & 4))
2736     gra->meth.draw_mode(gra->priv, draw_mode_end);
2737     }
2738    
2739     static void graphics_load_mapset(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags)
2740     {
2741     int order=transform_get_order(trans);
2742    
2743     //dbg(0,"enter displaylist->busy=%d\n",displaylist->busy);
2744     //dbg(0,"async=%d\n",async);
2745     if (displaylist->busy)
2746     {
2747     if (async == 1)
2748     {
2749     return;
2750     }
2751     //dbg(0,"**draw 1");
2752     do_draw(displaylist, 1, flags);
2753     }
2754     xdisplay_free(displaylist);
2755    
2756     displaylist->dc.gra=gra;
2757     displaylist->ms=mapset;
2758     displaylist->dc.trans=trans;
2759     displaylist->workload=async ? 100 : 0;
2760     displaylist->cb=cb;
2761     displaylist->seq++;
2762    
2763     if (l)
2764     {
2765     order+=l->order_delta;
2766     }
2767     displaylist->order=order;
2768     displaylist->busy=1;
2769     displaylist->layout=l;
2770    
2771     if (async)
2772     {
2773     //dbg(0,"§§async");
2774     if (! displaylist->idle_cb)
2775     {
2776     //dbg(0,"§§async --> callback");
2777     displaylist->idle_cb=callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
2778     }
2779     //dbg(0,"§§async --> add idle");
2780     displaylist->idle_ev=event_add_idle(50, displaylist->idle_cb);
2781     }
2782     else
2783     {
2784     //dbg(0,"@@sync");
2785     do_draw(displaylist, 0, flags);
2786     }
2787     }
2788    
2789    
2790     /**
2791     * FIXME
2792     * @param <>
2793     * @returns <>
2794     * @author Martin Schaller (04/2008)
2795     */
2796     void graphics_draw(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags)
2797     {
2798     //dbg(0,"ooo enter ooo\n");
2799    
2800     graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
2801     }
2802    
2803     int
2804     graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
2805     {
2806     //dbg(0,"ooo enter ooo\n");
2807    
2808     if (!displaylist->busy)
2809     return 0;
2810     do_draw(displaylist, 1, 0);
2811     return 1;
2812     }
2813    
2814     /**
2815     * FIXME
2816     * @param <>
2817     * @returns <>
2818     * @author Martin Schaller (04/2008)
2819     */
2820     struct displaylist_handle {
2821     struct displaylist *dl;
2822     struct displayitem *di;
2823     int hashidx;
2824     };
2825    
2826     /**
2827     * FIXME
2828     * @param <>
2829     * @returns <>
2830     * @author Martin Schaller (04/2008)
2831     */
2832     struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
2833     {
2834     struct displaylist_handle *ret;
2835    
2836     ret=g_new0(struct displaylist_handle, 1);
2837     ret->dl=displaylist;
2838    
2839     return ret;
2840     }
2841    
2842     /**
2843     * FIXME
2844     * @param <>
2845     * @returns <>
2846     * @author Martin Schaller (04/2008)
2847     */
2848     struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
2849     {
2850     struct displayitem *ret;
2851     if (!dlh)
2852     return NULL;
2853     for (;;) {
2854     if (dlh->di) {
2855     ret=dlh->di;
2856     dlh->di=ret->next;
2857     break;
2858     }
2859     if (dlh->hashidx == HASH_SIZE) {
2860     ret=NULL;
2861     break;
2862     }
2863     if (dlh->dl->hash_entries[dlh->hashidx].type)
2864     dlh->di=dlh->dl->hash_entries[dlh->hashidx].di;
2865     dlh->hashidx++;
2866     }
2867     return ret;
2868     }
2869    
2870     /**
2871     * FIXME
2872     * @param <>
2873     * @returns <>
2874     * @author Martin Schaller (04/2008)
2875     */
2876     void graphics_displaylist_close(struct displaylist_handle *dlh)
2877     {
2878     g_free(dlh);
2879     }
2880    
2881     /**
2882     * FIXME
2883     * @param <>
2884     * @returns <>
2885     * @author Martin Schaller (04/2008)
2886     */
2887     struct displaylist * graphics_displaylist_new(void)
2888     {
2889     struct displaylist *ret=g_new0(struct displaylist, 1);
2890    
2891     ret->dc.maxlen=16384;
2892    
2893     return ret;
2894     }
2895    
2896     /**
2897     * FIXME
2898     * @param <>
2899     * @returns <>
2900     * @author Martin Schaller (04/2008)
2901     */
2902     struct item * graphics_displayitem_get_item(struct displayitem *di)
2903     {
2904     return &di->item;
2905     }
2906    
2907     int
2908     graphics_displayitem_get_coord_count(struct displayitem *di)
2909     {
2910     return di->count;
2911     }
2912    
2913     /**
2914     * FIXME
2915     * @param <>
2916     * @returns <>
2917     * @author Martin Schaller (04/2008)
2918     */
2919     char * graphics_displayitem_get_label(struct displayitem *di)
2920     {
2921     return di->label;
2922     }
2923    
2924     int
2925     graphics_displayitem_get_displayed(struct displayitem *di)
2926     {
2927     return 1;
2928     }
2929    
2930     /**
2931     * FIXME
2932     * @param <>
2933     * @returns <>
2934     * @author Martin Schaller (04/2008)
2935     */
2936     static int within_dist_point(struct point *p0, struct point *p1, int dist)
2937     {
2938     if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
2939     return 0;
2940     if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
2941     return 0;
2942     if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) {
2943     return 1;
2944     }
2945     return 0;
2946     }
2947    
2948     /**
2949     * FIXME
2950     * @param <>
2951     * @returns <>
2952     * @author Martin Schaller (04/2008)
2953     */
2954     static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
2955     {
2956     int vx,vy,wx,wy;
2957     int c1,c2;
2958     struct point line_p;
2959    
2960     if (line_p0->x < line_p1->x) {
2961     if (p->x < line_p0->x - dist)
2962     return 0;
2963     if (p->x > line_p1->x + dist)
2964     return 0;
2965     } else {
2966     if (p->x < line_p1->x - dist)
2967     return 0;
2968     if (p->x > line_p0->x + dist)
2969     return 0;
2970     }
2971     if (line_p0->y < line_p1->y) {
2972     if (p->y < line_p0->y - dist)
2973     return 0;
2974     if (p->y > line_p1->y + dist)
2975     return 0;
2976     } else {
2977     if (p->y < line_p1->y - dist)
2978     return 0;
2979     if (p->y > line_p0->y + dist)
2980     return 0;
2981     }
2982    
2983     vx=line_p1->x-line_p0->x;
2984     vy=line_p1->y-line_p0->y;
2985     wx=p->x-line_p0->x;
2986     wy=p->y-line_p0->y;
2987    
2988     c1=vx*wx+vy*wy;
2989     if ( c1 <= 0 )
2990     return within_dist_point(p, line_p0, dist);
2991     c2=vx*vx+vy*vy;
2992     if ( c2 <= c1 )
2993     return within_dist_point(p, line_p1, dist);
2994    
2995     line_p.x=line_p0->x+vx*c1/c2;
2996     line_p.y=line_p0->y+vy*c1/c2;
2997     return within_dist_point(p, &line_p, dist);
2998     }
2999    
3000     /**
3001     * FIXME
3002     * @param <>
3003     * @returns <>
3004     * @author Martin Schaller (04/2008)
3005     */
3006     static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
3007     {
3008     int i;
3009     for (i = 0 ; i < count-1 ; i++) {
3010     if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) {
3011     return 1;
3012     }
3013     }
3014     if (close)
3015     return (within_dist_line(p,line_pnt,line_pnt+count-1,dist));
3016     return 0;
3017     }
3018    
3019     /**
3020     * FIXME
3021     * @param <>
3022     * @returns <>
3023     * @author Martin Schaller (04/2008)
3024     */
3025     static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
3026     {
3027     int i, j, c = 0;
3028     for (i = 0, j = count-1; i < count; j = i++) {
3029     if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) ||
3030     ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) &&
3031     (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))
3032     c = !c;
3033     }
3034     if (! c)
3035     return within_dist_polyline(p, poly_pnt, count, dist, 1);
3036     return c;
3037     }
3038    
3039     /**
3040     * FIXME
3041     * @param <>
3042     * @returns <>
3043     * @author Martin Schaller (04/2008)
3044     */
3045     int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
3046     {
3047     struct point *pa=g_alloca(sizeof(struct point)*displaylist->dc.maxlen);
3048     int count;
3049    
3050     count=transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
3051    
3052     if (di->item.type < type_line) {
3053     return within_dist_point(p, &pa[0], dist);
3054     }
3055     if (di->item.type < type_area) {
3056     return within_dist_polyline(p, pa, count, dist, 0);
3057     }
3058     return within_dist_polygon(p, pa, count, dist);
3059     }
3060    
3061    
3062     static void
3063     graphics_process_selection_item(struct displaylist *dl, struct item *item)
3064     {
3065     #if 0 /* FIXME */
3066     struct displayitem di,*di_res;
3067     GHashTable *h;
3068     int count,max=dl->dc.maxlen;
3069     struct coord ca[max];
3070     struct attr attr;
3071     struct map_rect *mr;
3072    
3073     di.item=*item;
3074     di.label=NULL;
3075     di.count=0;
3076     h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
3077     if (h) {
3078     di_res=g_hash_table_lookup(h, &di);
3079     if (di_res) {
3080     di.item.type=(enum item_type)item->priv_data;
3081     display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
3082     return;
3083     }
3084     }
3085     mr=map_rect_new(item->map, NULL);
3086     item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
3087     count=item_coord_get(item, ca, item->type < type_line ? 1: max);
3088     if (!item_attr_get(item, attr_label, &attr))
3089     attr.u.str=NULL;
3090     if (dl->conv && attr.u.str && attr.u.str[0]) {
3091     char *str=map_convert_string(item->map, attr.u.str);
3092     display_add(dl, item, count, ca, &str, 1);
3093     map_convert_free(str);
3094     } else
3095     display_add(dl, item, count, ca, &attr.u.str, 1);
3096     map_rect_destroy(mr);
3097     #endif
3098     }
3099    
3100     void
3101     graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
3102     {
3103     struct item *item_dup=g_new(struct item, 1);
3104     *item_dup=*item;
3105     item_dup->priv_data=(void *)type;
3106     gra->selection=g_list_append(gra->selection, item_dup);
3107     if (dl)
3108     graphics_process_selection_item(dl, item_dup);
3109     }
3110    
3111     void
3112     graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
3113     {
3114     GList *curr;
3115     int found;
3116    
3117     for (;;) {
3118     curr=gra->selection;
3119     found=0;
3120     while (curr) {
3121     struct item *sitem=curr->data;
3122     if (item_is_equal(*item,*sitem)) {
3123     if (dl) {
3124     struct displayitem di;
3125     /* Unused Variable
3126     GHashTable *h; */
3127     di.item=*sitem;
3128     di.label=NULL;
3129     di.count=0;
3130     di.item.type=type;
3131     #if 0 /* FIXME */
3132     h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
3133     if (h)
3134     g_hash_table_remove(h, &di);
3135     #endif
3136     }
3137     g_free(sitem);
3138     gra->selection=g_list_remove(gra->selection, curr->data);
3139     found=1;
3140     break;
3141     }
3142     }
3143     if (!found)
3144     return;
3145     }
3146     }
3147    
3148     void
3149     graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
3150     {
3151     while (gra->selection) {
3152     struct item *item=(struct item *)gra->selection->data;
3153     graphics_remove_selection(gra, item, (enum item_type)item->priv_data,dl);
3154     }
3155     }
3156    
3157     static void
3158     graphics_process_selection(struct graphics *gra, struct displaylist *dl)
3159     {
3160     GList *curr;
3161    
3162     curr=gra->selection;
3163     while (curr) {
3164     struct item *item=curr->data;
3165     graphics_process_selection_item(dl, item);
3166     curr=g_list_next(curr);
3167     }
3168     }

   
Visit the ZANavi Wiki