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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide annotations) (download)
Wed Aug 22 17:01:27 2012 UTC (11 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 97245 byte(s)
ZANavi 2.0, lots of changes, everything in its own thread, more performance
1 zoff99 2 /**
2 zoff99 27 * ZANavi, Zoff Android Navigation system.
3     * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
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 zoff99 2 * Navit, a modular navigation system.
22     * Copyright (C) 2005-2008 Navit Team
23     *
24     * This program is free software; you can redistribute it and/or
25     * modify it under the terms of the GNU General Public License
26     * version 2 as published by the Free Software Foundation.
27     *
28     * This program is distributed in the hope that it will be useful,
29     * but WITHOUT ANY WARRANTY; without even the implied warranty of
30     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31     * GNU General Public License for more details.
32     *
33     * You should have received a copy of the GNU General Public License
34     * along with this program; if not, write to the
35     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36     * Boston, MA 02110-1301, USA.
37     */
38    
39     //##############################################################################################################
40     //#
41     //# File: graphics.c
42     //# Description:
43     //# Comment:
44     //# Authors: Martin Schaller (04/2008)
45     //#
46     //##############################################################################################################
47    
48     #include <stdlib.h>
49     #include <glib.h>
50     #include <stdio.h>
51     #include <math.h>
52     #include "config.h"
53     #include "debug.h"
54     #include "string.h"
55     #include "draw_info.h"
56     #include "point.h"
57     #include "graphics.h"
58     #include "projection.h"
59     #include "item.h"
60     #include "map.h"
61     #include "coord.h"
62     #include "transform.h"
63     #include "plugin.h"
64     #include "profile.h"
65     #include "mapset.h"
66     #include "layout.h"
67     #include "route.h"
68     #include "util.h"
69     #include "callback.h"
70     #include "file.h"
71     #include "event.h"
72     //
73     #include "attr.h"
74     #include "navit.h"
75 zoff99 27 #include "route.h"
76 zoff99 2
77 zoff99 30 #ifdef HAVE_API_ANDROID
78     // nothing todo for android
79     #else
80     // linux seems to need this explicitly
81     #include "pthread.h"
82     #endif
83    
84    
85     static pthread_cond_t uiConditionVariable = PTHREAD_COND_INITIALIZER;
86     static pthread_mutex_t uiConditionMutex = PTHREAD_MUTEX_INITIALIZER;
87    
88 zoff99 2 //##############################################################################################################
89     //# Description:
90     //# Comment:
91     //# Authors: Martin Schaller (04/2008)
92     //##############################################################################################################
93    
94     // above what "order" level to show only prerendered map
95     #define ORDER_USE_PRERENDERED_MAP 0
96 zoff99 29 // minimum (line legth * 32) squared (in pixel) to show text label
97 zoff99 28 #define MIN_LINE_LENGTH_FOR_TEXT_2 409600
98 zoff99 29 // minimum (line legth * 32) squared (in pixel) to show text label -> for middle segments of streets
99 zoff99 28 #define MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2 1638400
100 zoff99 2
101 zoff99 28 #define ORDER_LEVEL_FOR_STREET_SIMPLIFY 9
102     #define STREET_SIMPLIFY 24
103    
104 zoff99 2 struct graphics
105     {
106     struct graphics_priv *priv;
107     struct graphics_methods meth;
108     char *default_font;
109     int font_len;
110     struct graphics_font **font;
111     struct graphics_gc *gc[3];
112     struct attr **attrs;
113     struct callback_list *cbl;
114     struct point_rect r;
115 zoff99 27 int gamma, brightness, contrast;
116 zoff99 2 int colormgmt;
117     int font_size;
118     GList *selection;
119     };
120    
121 zoff99 27 /*
122     struct display_context
123     {
124     struct graphics *gra;
125     struct element *e;
126     struct graphics_gc *gc;
127     struct graphics_gc *gc_background;
128     struct graphics_image *img;
129     enum projection pro;
130     int mindist;
131     struct transformation *trans;
132     enum item_type type;
133     int maxlen;
134     };
135 zoff99 2
136 zoff99 27 #define HASH_SIZE 1024
137     */
138 zoff99 2
139 zoff99 27 /*
140     struct hash_entry
141     {
142     enum item_type type;
143     struct displayitem *di;
144     };
145     */
146 zoff99 2
147 zoff99 27 /*
148     struct displaylist {
149     int busy;
150     int workload;
151     struct callback *cb;
152     struct layout *layout, *layout_hashed;
153     struct display_context dc;
154     int order, order_hashed, max_offset;
155     struct mapset *ms;
156     struct mapset_handle *msh;
157     struct map *m;
158     int conv;
159     struct map_selection *sel;
160     struct map_rect *mr;
161     struct callback *idle_cb;
162     struct event_idle *idle_ev;
163     unsigned int seq;
164     struct hash_entry hash_entries[HASH_SIZE];
165     };
166     */
167 zoff99 2
168 zoff99 27 struct displaylist_icon_cache
169     {
170 zoff99 2 unsigned int seq;
171    
172     };
173    
174     /**
175     * FIXME
176     * @param <>
177     * @returns <>
178     * @author Martin Schaller (04/2008)
179 zoff99 27 */
180     struct displayitem
181     {
182 zoff99 2 struct displayitem *next;
183     struct item item;
184     char *label;
185     int count;
186     struct coord c[0];
187     };
188    
189     static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir);
190     static void graphics_process_selection(struct graphics *gra, struct displaylist *dl);
191     static void graphics_gc_init(struct graphics *this_);
192    
193 zoff99 27 static void clear_hash(struct displaylist *dl)
194 zoff99 2 {
195     int i;
196 zoff99 27 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
197 zoff99 28 {
198 zoff99 27 dl->hash_entries[i].type = type_none;
199 zoff99 28 }
200 zoff99 2 }
201    
202     static struct hash_entry *
203     get_hash_entry(struct displaylist *dl, enum item_type type)
204     {
205 zoff99 27 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
206     int offset = dl->max_offset;
207     do
208     {
209 zoff99 2 if (!dl->hash_entries[hashidx].type)
210 zoff99 27 {
211 zoff99 2 return NULL;
212 zoff99 27 }
213 zoff99 2 if (dl->hash_entries[hashidx].type == type)
214 zoff99 27 {
215 zoff99 2 return &dl->hash_entries[hashidx];
216 zoff99 27 }
217     hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
218     }
219     while (offset-- > 0);
220    
221 zoff99 2 return NULL;
222     }
223    
224     static struct hash_entry *
225     set_hash_entry(struct displaylist *dl, enum item_type type)
226     {
227 zoff99 27 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
228     int offset = 0;
229     for (;;)
230     {
231     if (!dl->hash_entries[hashidx].type)
232     {
233     dl->hash_entries[hashidx].type = type;
234 zoff99 2 if (dl->max_offset < offset)
235 zoff99 27 dl->max_offset = offset;
236 zoff99 2 return &dl->hash_entries[hashidx];
237     }
238     if (dl->hash_entries[hashidx].type == type)
239     return &dl->hash_entries[hashidx];
240 zoff99 27 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
241 zoff99 2 offset++;
242     }
243     return NULL;
244     }
245    
246 zoff99 27 static int graphics_set_attr_do(struct graphics *gra, struct attr *attr)
247 zoff99 2 {
248 zoff99 27 switch (attr->type)
249     {
250     case attr_gamma:
251     gra->gamma = attr->u.num;
252     break;
253     case attr_brightness:
254     gra->brightness = attr->u.num;
255     break;
256     case attr_contrast:
257     gra->contrast = attr->u.num;
258     break;
259     case attr_font_size:
260     gra->font_size = attr->u.num;
261     return 1;
262     default:
263     return 0;
264 zoff99 2 }
265 zoff99 27 gra->colormgmt = (gra->gamma != 65536 || gra->brightness != 0 || gra->contrast != 65536);
266 zoff99 2 graphics_gc_init(gra);
267     return 1;
268     }
269    
270 zoff99 27 int graphics_set_attr(struct graphics *gra, struct attr *attr)
271 zoff99 2 {
272 zoff99 27 int ret = 1;
273 zoff99 30 // //DBG // dbg(0,"enter\n");
274 zoff99 2 if (gra->meth.set_attr)
275 zoff99 27 ret = gra->meth.set_attr(gra->priv, attr);
276 zoff99 2 if (!ret)
277 zoff99 27 ret = graphics_set_attr_do(gra, attr);
278     return ret != 0;
279 zoff99 2 }
280    
281 zoff99 27 void graphics_set_rect(struct graphics *gra, struct point_rect *pr)
282 zoff99 2 {
283 zoff99 27 gra->r = *pr;
284 zoff99 2 }
285    
286     /**
287     * Creates a new graphics object
288     * attr type required
289     * @param <>
290     * @returns <>
291     * @author Martin Schaller (04/2008)
292 zoff99 27 */
293 zoff99 2 struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
294     {
295 zoff99 30 // dbg(0, "EEnter\n");
296    
297     int count = 0;
298 zoff99 2 struct graphics *this_;
299 zoff99 27 struct attr *type_attr;
300 zoff99 2 struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl);
301    
302 zoff99 27 if (!(type_attr = attr_search(attrs, NULL, attr_type)))
303     {
304     return NULL;
305     }
306 zoff99 2
307 zoff99 30 // dbg(0, "plugins\n");
308    
309 zoff99 27 graphicstype_new = plugin_get_graphics_type(type_attr->u.str);
310     if (!graphicstype_new)
311     {
312 zoff99 2 return NULL;
313 zoff99 27 }
314    
315 zoff99 30 // dbg(0, "g 003\n");
316    
317 zoff99 2 this_=g_new0(struct graphics, 1);
318 zoff99 27 this_->cbl = callback_list_new();
319 zoff99 30 // dbg(0, "g 003.1\n");
320 zoff99 27 this_->priv = (*graphicstype_new)(parent->u.navit, &this_->meth, attrs, this_->cbl);
321 zoff99 30 // dbg(0, "g 003.2\n");
322 zoff99 27 this_->attrs = attr_list_dup(attrs);
323     this_->brightness = 0;
324     this_->contrast = 65536;
325     this_->gamma = 65536;
326     this_->font_size = 20;
327    
328 zoff99 30 // dbg(0, "g 004\n");
329    
330 zoff99 27 while (*attrs)
331     {
332 zoff99 30 count++;
333     // dbg(0, "g 005 attr %d\n", count);
334 zoff99 27 graphics_set_attr_do(this_, *attrs);
335 zoff99 2 attrs++;
336 zoff99 30 // dbg(0, "g 006 attr\n");
337 zoff99 2 }
338 zoff99 27
339 zoff99 30 // dbg(0, "return\n");
340 zoff99 2 return this_;
341     }
342    
343     /**
344     * FIXME
345     * @param <>
346     * @returns <>
347     * @author Martin Schaller (04/2008)
348 zoff99 27 */
349 zoff99 2 int graphics_get_attr(struct graphics *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
350     {
351     return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
352     }
353    
354     /**
355     * FIXME
356     * @param <>
357     * @returns <>
358     * @author Martin Schaller (04/2008)
359 zoff99 27 */
360 zoff99 30 struct graphics * graphics_overlay_new(const char* name, struct graphics *parent, struct point *p, int w, int h, int alpha, int wraparound)
361 zoff99 2 {
362     struct graphics *this_;
363     struct point_rect pr;
364     if (!parent->meth.overlay_new)
365 zoff99 27 return NULL;this_=g_new0(struct graphics, 1);
366 zoff99 30 this_->priv = parent->meth.overlay_new(name, parent->priv, &this_->meth, p, w, h, alpha, wraparound);
367 zoff99 27 pr.lu.x = 0;
368     pr.lu.y = 0;
369     pr.rl.x = w;
370     pr.rl.y = h;
371     this_->font_size = 20;
372 zoff99 2 graphics_set_rect(this_, &pr);
373 zoff99 27 if (!this_->priv)
374     {
375 zoff99 2 g_free(this_);
376 zoff99 27 this_ = NULL;
377 zoff99 2 }
378     return this_;
379     }
380    
381     /**
382     * @brief Alters the size, position, alpha and wraparound for an overlay
383     *
384     * @param this_ The overlay's graphics struct
385     * @param p The new position of the overlay
386     * @param w The new width of the overlay
387     * @param h The new height of the overlay
388     * @param alpha The new alpha of the overlay
389     * @param wraparound The new wraparound of the overlay
390     */
391 zoff99 27 void graphics_overlay_resize(struct graphics *this_, struct point *p, int w, int h, int alpha, int wraparound)
392 zoff99 2 {
393 zoff99 27 if (!this_->meth.overlay_resize)
394     {
395 zoff99 2 return;
396     }
397    
398     this_->meth.overlay_resize(this_->priv, p, w, h, alpha, wraparound);
399     }
400    
401 zoff99 27 static void graphics_gc_init(struct graphics *this_)
402 zoff99 2 {
403 zoff99 30 // dbg(0, "EEnter\n");
404    
405     struct color background = { COLOR_BACKGROUND_ };
406     struct color black = { COLOR_BLACK_ };
407     struct color white = { COLOR_WHITE_ };
408 zoff99 2 if (!this_->gc[0] || !this_->gc[1] || !this_->gc[2])
409     return;
410 zoff99 27 graphics_gc_set_background(this_->gc[0], &background);
411     graphics_gc_set_foreground(this_->gc[0], &background);
412     graphics_gc_set_background(this_->gc[1], &black);
413     graphics_gc_set_foreground(this_->gc[1], &white);
414     graphics_gc_set_background(this_->gc[2], &white);
415     graphics_gc_set_foreground(this_->gc[2], &black);
416 zoff99 30
417     // dbg(0, "return\n");
418 zoff99 2 }
419    
420     /**
421     * FIXME
422     * @param <>
423     * @returns <>
424     * @author Martin Schaller (04/2008)
425 zoff99 27 */
426 zoff99 2 void graphics_init(struct graphics *this_)
427     {
428     if (this_->gc[0])
429     return;
430 zoff99 27 this_->gc[0] = graphics_gc_new(this_);
431     this_->gc[1] = graphics_gc_new(this_);
432     this_->gc[2] = graphics_gc_new(this_);
433 zoff99 2 graphics_gc_init(this_);
434     graphics_background_gc(this_, this_->gc[0]);
435     }
436    
437     /**
438     * FIXME
439     * @param <>
440     * @returns <>
441     * @author Martin Schaller (04/2008)
442 zoff99 27 */
443 zoff99 2 void * graphics_get_data(struct graphics *this_, const char *type)
444     {
445     return (this_->meth.get_data(this_->priv, type));
446     }
447    
448     void graphics_add_callback(struct graphics *this_, struct callback *cb)
449     {
450     callback_list_add(this_->cbl, cb);
451     }
452    
453     void graphics_remove_callback(struct graphics *this_, struct callback *cb)
454     {
455     callback_list_remove(this_->cbl, cb);
456     }
457    
458     /**
459     * FIXME
460     * @param <>
461     * @returns <>
462     * @author Martin Schaller (04/2008)
463 zoff99 27 */
464 zoff99 2 struct graphics_font * graphics_font_new(struct graphics *gra, int size, int flags)
465     {
466     struct graphics_font *this_;
467    
468     this_=g_new0(struct graphics_font,1);
469 zoff99 27 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, gra->default_font, size, flags);
470 zoff99 2 return this_;
471     }
472    
473     struct graphics_font * graphics_named_font_new(struct graphics *gra, char *font, int size, int flags)
474     {
475     struct graphics_font *this_;
476    
477     this_=g_new0(struct graphics_font,1);
478 zoff99 27 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, font, size, flags);
479 zoff99 2 return this_;
480     }
481    
482     /**
483     * Destroy graphics
484     * Called when navit exits
485     * @param gra The graphics instance
486     * @returns nothing
487     * @author David Tegze (02/2011)
488     */
489     void graphics_free(struct graphics *gra)
490     {
491     if (!gra)
492     return;
493     gra->meth.graphics_destroy(gra->priv);
494     g_free(gra->default_font);
495     graphics_font_destroy_all(gra);
496     g_free(gra);
497     }
498    
499     /**
500     * Free all loaded fonts.
501     * Used when switching layouts.
502     * @param gra The graphics instance
503     * @returns nothing
504     * @author Sarah Nordstrom (05/2008)
505     */
506     void graphics_font_destroy_all(struct graphics *gra)
507     {
508     int i;
509 zoff99 27 for (i = 0; i < gra->font_len; i++)
510     {
511     if (!gra->font[i])
512     continue;
513     gra->font[i]->meth.font_destroy(gra->font[i]->priv);
514     gra->font[i] = NULL;
515 zoff99 2 }
516     }
517    
518     /**
519     * FIXME
520     * @param <>
521     * @returns <>
522     * @author Martin Schaller (04/2008)
523 zoff99 27 */
524 zoff99 2 struct graphics_gc * graphics_gc_new(struct graphics *gra)
525     {
526     struct graphics_gc *this_;
527    
528     this_=g_new0(struct graphics_gc,1);
529 zoff99 27 this_->priv = gra->meth.gc_new(gra->priv, &this_->meth);
530     this_->gra = gra;
531 zoff99 2 return this_;
532     }
533    
534     /**
535     * FIXME
536     * @param <>
537     * @returns <>
538     * @author Martin Schaller (04/2008)
539 zoff99 27 */
540 zoff99 2 void graphics_gc_destroy(struct graphics_gc *gc)
541     {
542     gc->meth.gc_destroy(gc->priv);
543     g_free(gc);
544     }
545    
546 zoff99 27 static void graphics_convert_color(struct graphics *gra, struct color *in, struct color *out)
547 zoff99 2 {
548 zoff99 27 *out = *in;
549     if (gra->brightness)
550     {
551     out->r += gra->brightness;
552     out->g += gra->brightness;
553     out->b += gra->brightness;
554 zoff99 2 }
555 zoff99 27 if (gra->contrast != 65536)
556     {
557     out->r = out->r * gra->contrast / 65536;
558     out->g = out->g * gra->contrast / 65536;
559     out->b = out->b * gra->contrast / 65536;
560 zoff99 2 }
561     if (out->r < 0)
562 zoff99 27 out->r = 0;
563 zoff99 2 if (out->r > 65535)
564 zoff99 27 out->r = 65535;
565 zoff99 2 if (out->g < 0)
566 zoff99 27 out->g = 0;
567 zoff99 2 if (out->g > 65535)
568 zoff99 27 out->g = 65535;
569 zoff99 2 if (out->b < 0)
570 zoff99 27 out->b = 0;
571 zoff99 2 if (out->b > 65535)
572 zoff99 27 out->b = 65535;
573     if (gra->gamma != 65536)
574     {
575     out->r = pow(out->r / 65535.0, gra->gamma / 65536.0) * 65535.0;
576     out->g = pow(out->g / 65535.0, gra->gamma / 65536.0) * 65535.0;
577     out->b = pow(out->b / 65535.0, gra->gamma / 65536.0) * 65535.0;
578 zoff99 2 }
579     }
580    
581     /**
582     * FIXME
583     * @param <>
584     * @returns <>
585     * @author Martin Schaller (04/2008)
586 zoff99 27 */
587 zoff99 2 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
588     {
589     struct color cn;
590 zoff99 27 if (gc->gra->colormgmt)
591     {
592 zoff99 2 graphics_convert_color(gc->gra, c, &cn);
593 zoff99 27 c = &cn;
594 zoff99 2 }
595     gc->meth.gc_set_foreground(gc->priv, c);
596     }
597    
598     /**
599     * FIXME
600     * @param <>
601     * @returns <>
602     * @author Martin Schaller (04/2008)
603 zoff99 27 */
604 zoff99 2 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
605     {
606     struct color cn;
607 zoff99 27 if (gc->gra->colormgmt)
608     {
609 zoff99 2 graphics_convert_color(gc->gra, c, &cn);
610 zoff99 27 c = &cn;
611 zoff99 2 }
612     gc->meth.gc_set_background(gc->priv, c);
613     }
614    
615     /**
616     * FIXME
617     * @param <>
618     * @returns <>
619     * @author Martin Schaller (04/2008)
620 zoff99 27 */
621 zoff99 2 void graphics_gc_set_stipple(struct graphics_gc *gc, struct graphics_image *img)
622     {
623     gc->meth.gc_set_stipple(gc->priv, img ? img->priv : NULL);
624     }
625    
626     /**
627     * FIXME
628     * @param <>
629     * @returns <>
630     * @author Martin Schaller (04/2008)
631 zoff99 27 */
632 zoff99 2 void graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
633     {
634     gc->meth.gc_set_linewidth(gc->priv, width);
635     }
636    
637     /**
638     * FIXME
639     * @param <>
640     * @returns <>
641     * @author Martin Schaller (04/2008)
642 zoff99 27 */
643     void graphics_gc_set_dashes(struct graphics *gra, struct graphics_gc *gc, int width, int offset, int dash_list[], int n, int order)
644 zoff99 2 {
645     if (gc->meth.gc_set_dashes)
646 zoff99 27 {
647     gc->meth.gc_set_dashes(gra->priv, gc->priv, width, offset, dash_list, order);
648     }
649 zoff99 2 }
650    
651     /**
652     * Create a new image from file path scaled to w and h pixels
653     * @param gra the graphics instance
654     * @param path path of the image to load
655     * @param w width to rescale to
656     * @param h height to rescale to
657     * @returns <>
658     * @author Martin Schaller (04/2008)
659 zoff99 27 */
660 zoff99 2 struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *path, int w, int h)
661     {
662     struct graphics_image *this_;
663    
664     this_=g_new0(struct graphics_image,1);
665 zoff99 27 this_->height = h;
666     this_->width = w;
667     this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, 0);
668     if (!this_->priv)
669     {
670 zoff99 2 g_free(this_);
671 zoff99 27 this_ = NULL;
672 zoff99 2 }
673     return this_;
674     }
675    
676     /**
677     * Create a new image from file path scaled to w and h pixels and possibly rotated
678     * @param gra the graphics instance
679     * @param path path of the image to load
680     * @param w width to rescale to
681     * @param h height to rescale to
682     * @param rotate angle to rotate the image. Warning, graphics might only support 90 degree steps here
683     * @returns <>
684     * @author Martin Schaller (04/2008)
685 zoff99 27 */
686 zoff99 2 struct graphics_image * graphics_image_new_scaled_rotated(struct graphics *gra, char *path, int w, int h, int rotate)
687     {
688     struct graphics_image *this_;
689    
690     this_=g_new0(struct graphics_image,1);
691 zoff99 27 this_->height = h;
692     this_->width = w;
693     this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, rotate);
694     if (!this_->priv)
695     {
696 zoff99 2 g_free(this_);
697 zoff99 27 this_ = NULL;
698 zoff99 2 }
699     return this_;
700     }
701    
702     /**
703     * Create a new image from file path
704     * @param gra the graphics instance
705     * @param path path of the image to load
706     * @returns <>
707     * @author Martin Schaller (04/2008)
708 zoff99 27 */
709 zoff99 2 struct graphics_image * graphics_image_new(struct graphics *gra, char *path)
710     {
711     return graphics_image_new_scaled(gra, path, -1, -1);
712     }
713    
714     /**
715     * FIXME
716     * @param <>
717     * @returns <>
718     * @author Martin Schaller (04/2008)
719 zoff99 27 */
720 zoff99 2 void graphics_image_free(struct graphics *gra, struct graphics_image *img)
721     {
722     if (gra->meth.image_free)
723     gra->meth.image_free(gra->priv, img->priv);
724     g_free(img);
725     }
726    
727     /**
728     * FIXME
729     * @param <>
730     * @returns <>
731     * @author Martin Schaller (04/2008)
732 zoff99 27 */
733 zoff99 2 void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
734     {
735 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
736 zoff99 2
737     this_->meth.draw_restore(this_->priv, p, w, h);
738     }
739    
740     /**
741     * FIXME
742     * @param <>
743     * @returns <>
744     * @author Martin Schaller (04/2008)
745 zoff99 27 */
746 zoff99 2 void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
747     {
748 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
749 zoff99 2
750     this_->meth.draw_mode(this_->priv, mode);
751     }
752    
753     /**
754     * FIXME
755     * @param <>
756     * @returns <>
757     * @author Martin Schaller (04/2008)
758 zoff99 27 */
759 zoff99 2 void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
760     {
761     this_->meth.draw_lines(this_->priv, gc->priv, p, count);
762     }
763    
764     void graphics_draw_lines_dashed(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count, int order, int oneway)
765     {
766     this_->meth.draw_lines_dashed(this_->priv, gc->priv, p, count, order, oneway);
767     }
768    
769     /**
770     * FIXME
771     * @param <>
772     * @returns <>
773     * @author Martin Schaller (04/2008)
774 zoff99 27 */
775 zoff99 2 void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
776     {
777 zoff99 27 int i = 0;
778 zoff99 2
779 zoff99 27 if (this_->meth.draw_circle)
780 zoff99 30 {
781 zoff99 2 this_->meth.draw_circle(this_->priv, gc->priv, p, r);
782 zoff99 30 }
783 zoff99 2 else
784     {
785 zoff99 30 struct point *pnt = g_alloca(sizeof(struct point) * (r * 4 + 64));
786 zoff99 2 draw_circle(p, r, 0, -1, 1026, pnt, &i, 1);
787     pnt[i] = pnt[0];
788     i++;
789     this_->meth.draw_lines(this_->priv, gc->priv, pnt, i);
790     }
791     }
792    
793     /**
794     * FIXME
795     * @param <>
796     * @returns <>
797     * @author Martin Schaller (04/2008)
798 zoff99 27 */
799 zoff99 2 void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
800     {
801     this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
802     }
803    
804     void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, int r, int fill)
805     {
806 zoff99 27 struct point *p = g_alloca(sizeof(struct point) * (r * 4 + 32));
807 zoff99 30 struct point pi0 = { plu->x + r, plu->y + r };
808     struct point pi1 = { plu->x + w - r, plu->y + r };
809     struct point pi2 = { plu->x + w - r, plu->y + h - r };
810     struct point pi3 = { plu->x + r, plu->y + h - r };
811 zoff99 27 int i = 0;
812 zoff99 2
813 zoff99 27 draw_circle(&pi2, r * 2, 0, -1, 258, p, &i, 1);
814     draw_circle(&pi1, r * 2, 0, 255, 258, p, &i, 1);
815     draw_circle(&pi0, r * 2, 0, 511, 258, p, &i, 1);
816     draw_circle(&pi3, r * 2, 0, 767, 258, p, &i, 1);
817     p[i] = p[0];
818 zoff99 2 i++;
819     if (fill)
820     this_->meth.draw_polygon(this_->priv, gc->priv, p, i);
821     else
822     this_->meth.draw_lines(this_->priv, gc->priv, p, i);
823     }
824    
825     /**
826     * FIXME
827     * @param <>
828     * @returns <>
829     * @author Martin Schaller (04/2008)
830 zoff99 27 */
831 zoff99 2 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)
832     {
833     this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy);
834     }
835    
836     /**
837     * FIXME
838     * @param <>
839     * @returns <>
840     * @author Martin Schaller (04/2008)
841 zoff99 27 */
842 zoff99 2 void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret, int estimate)
843     {
844     this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret, estimate);
845     }
846    
847     /**
848     * FIXME
849     * @param <>
850     * @returns <>
851     * @author Martin Schaller (04/2008)
852 zoff99 27 */
853 zoff99 2 void graphics_overlay_disable(struct graphics *this_, int disable)
854     {
855     if (this_->meth.overlay_disable)
856     this_->meth.overlay_disable(this_->priv, disable);
857     }
858    
859     /**
860     * FIXME
861     * @param <>
862     * @returns <>
863     * @author Martin Schaller (04/2008)
864 zoff99 27 */
865 zoff99 2 void graphics_draw_image(struct graphics *this_, struct graphics_gc *gc, struct point *p, struct graphics_image *img)
866     {
867     this_->meth.draw_image(this_->priv, gc->priv, p, img->priv);
868     }
869    
870     /**
871     *
872     *
873     * @author Zoff (2011)
874 zoff99 27 */
875 zoff99 2 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)
876     {
877     this_->meth.draw_bigmap(this_->priv, gc->priv, yaw, order, clat, clng, x, y, scx, scy, px, py, valid);
878     }
879    
880     //##############################################################################################################
881     //# Description:
882     //# Comment:
883     //# Authors: Martin Schaller (04/2008)
884     //##############################################################################################################
885 zoff99 27 int graphics_draw_drag(struct graphics *this_, struct point *p)
886 zoff99 2 {
887 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
888 zoff99 2
889     if (!this_->meth.draw_drag)
890     {
891     return 0;
892     }
893 zoff99 30 ////DBG // dbg(0,"draw DRAG start ...\n");
894 zoff99 2 this_->meth.draw_drag(this_->priv, p);
895 zoff99 30 ////DBG // dbg(0,"draw DRAG end ...\n");
896 zoff99 2 return 1;
897     }
898    
899 zoff99 27 void graphics_background_gc(struct graphics *this_, struct graphics_gc *gc)
900 zoff99 2 {
901 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
902 zoff99 2
903     this_->meth.background_gc(this_->priv, gc ? gc->priv : NULL);
904     }
905    
906     #include "attr.h"
907     #include "popup.h"
908     #include <stdio.h>
909    
910     #if 0
911     //##############################################################################################################
912     //# Description:
913     //# Comment:
914     //# Authors: Martin Schaller (04/2008)
915     //##############################################################################################################
916     static void popup_view_html(struct popup_item *item, char *file)
917     {
918     char command[1024];
919     sprintf(command,"firefox %s", file);
920     system(command);
921     }
922    
923     struct transformatin *tg;
924     enum projection pg;
925    
926     //##############################################################################################################
927     //# Description:
928     //# Comment:
929     //# Authors: Martin Schaller (04/2008)
930     //##############################################################################################################
931     static void graphics_popup(struct display_list *list, struct popup_item **popup)
932     {
933     struct item *item;
934     struct attr attr;
935     struct map_rect *mr;
936     struct coord c;
937     struct popup_item *curr_item,*last=NULL;
938     item=list->data;
939     mr=map_rect_new(item->map, NULL, NULL, 0);
940     printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
941     item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
942 zoff99 27 if (item)
943     {
944     if (item_attr_get(item, attr_name, &attr))
945     {
946 zoff99 2 curr_item=popup_item_new_text(popup,attr.u.str,1);
947 zoff99 27 if (item_attr_get(item, attr_info_html, &attr))
948     {
949 zoff99 2 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
950     }
951 zoff99 27 if (item_attr_get(item, attr_price_html, &attr))
952     {
953 zoff99 2 popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
954     }
955     curr_item->submenu=last;
956     }
957     }
958     map_rect_destroy(mr);
959     }
960     #endif
961    
962     /**
963     * FIXME
964     * @param <>
965     * @returns <>
966     * @author Martin Schaller (04/2008)
967 zoff99 27 */
968 zoff99 2 static void xdisplay_free(struct displaylist *dl)
969     {
970     int i;
971 zoff99 27 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
972     {
973     struct displayitem *di = dl->hash_entries[i].di;
974     while (di)
975     {
976     struct displayitem *next = di->next;
977 zoff99 2 g_free(di);
978 zoff99 27 di = next;
979 zoff99 2 }
980 zoff99 27 dl->hash_entries[i].di = NULL;
981 zoff99 2 }
982     }
983    
984     /**
985     * FIXME
986     * @param <>
987     * @returns <>
988     * @author Martin Schaller (04/2008)
989 zoff99 27 */
990 zoff99 2 static void display_add(struct hash_entry *entry, struct item *item, int count, struct coord *c, char **label, int label_count)
991     {
992     struct displayitem *di;
993 zoff99 27 int len, i;
994 zoff99 2 char *p;
995    
996 zoff99 27 len = sizeof(*di) + count * sizeof(*c);
997     if (label && label_count)
998     {
999     for (i = 0; i < label_count; i++)
1000     {
1001 zoff99 2 if (label[i])
1002 zoff99 28 {
1003 zoff99 27 len += strlen(label[i]) + 1;
1004 zoff99 28 }
1005 zoff99 2 else
1006 zoff99 28 {
1007 zoff99 2 len++;
1008 zoff99 28 }
1009 zoff99 2 }
1010     }
1011 zoff99 27 p = g_malloc(len);
1012 zoff99 30 // // dbg(0,"malloc len:%d\n", len);
1013 zoff99 2
1014 zoff99 27 di = (struct displayitem *) p;
1015     p += sizeof(*di) + count * sizeof(*c);
1016     di->item = *item;
1017     if (label && label_count)
1018     {
1019     di->label = p;
1020     for (i = 0; i < label_count; i++)
1021     {
1022     if (label[i])
1023     {
1024 zoff99 2 strcpy(p, label[i]);
1025 zoff99 27 p += strlen(label[i]) + 1;
1026     }
1027     else
1028 zoff99 28 {
1029 zoff99 27 *p++ = '\0';
1030 zoff99 28 }
1031 zoff99 2 }
1032 zoff99 27 }
1033     else
1034     {
1035     di->label = NULL;
1036     }
1037     di->count = count;
1038     memcpy(di->c, c, count * sizeof(*c));
1039     di->next = entry->di;
1040     entry->di = di;
1041 zoff99 2 }
1042    
1043     /**
1044     * FIXME
1045     * @param <>
1046     * @returns <>
1047     * @author Martin Schaller (04/2008)
1048 zoff99 27 */
1049 zoff99 2 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)
1050     {
1051 zoff99 27 int i, x, y, tl, tlm, th, thm, tlsq, l;
1052 zoff99 2 float lsq;
1053 zoff99 28 // double dx, dy;
1054     float dx, dy;
1055 zoff99 2 struct point p_t;
1056     struct point pb[5];
1057    
1058 zoff99 27 if (gra->meth.get_text_bbox)
1059     {
1060 zoff99 2 gra->meth.get_text_bbox(gra->priv, font->priv, label, 0x10000, 0x0, pb, 1);
1061 zoff99 28 // tl -> text length
1062 zoff99 27 tl = (pb[2].x - pb[0].x);
1063 zoff99 28 // th -> text height
1064 zoff99 27 th = (pb[0].y - pb[1].y);
1065 zoff99 2 }
1066 zoff99 27 else
1067     {
1068 zoff99 28 // tl -> text length
1069 zoff99 27 tl = strlen(label) * 4;
1070 zoff99 28 // th -> text height
1071 zoff99 27 th = 8;
1072     }
1073     tlm = tl * 32;
1074     thm = th * 36;
1075 zoff99 28 // tlsq -> (text length * 32) squared
1076 zoff99 27 tlsq = tlm * tlm;
1077     for (i = 0; i < count - 1; i++)
1078     {
1079     dx = p[i + 1].x - p[i].x;
1080     dx *= 32;
1081     dy = p[i + 1].y - p[i].y;
1082     dy *= 32;
1083 zoff99 28 // lsq -> (line length * 32) squared
1084 zoff99 27 lsq = dx * dx + dy * dy;
1085     if (lsq > tlsq)
1086     {
1087 zoff99 30 if (((int) lsq > MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2) || (((i == 0) || (i == (count - 2)) && ((int) lsq > (int) MIN_LINE_LENGTH_FOR_TEXT_2))))
1088 zoff99 27 {
1089 zoff99 28 // segments in the middle of the "way" need to be longer for streetname to be drawn
1090     // l -> line length
1091     l = (int) sqrtf_fast2(lsq);
1092     x = p[i].x;
1093     y = p[i].y;
1094     if (dx < 0)
1095     {
1096     dx = -dx;
1097     dy = -dy;
1098     x = p[i + 1].x;
1099     y = p[i + 1].y;
1100     }
1101     x += (l - tlm) * dx / l / 64;
1102     y += (l - tlm) * dy / l / 64;
1103     x -= dy * thm / l / 64;
1104     y += dx * thm / l / 64;
1105     p_t.x = x;
1106     p_t.y = y;
1107 zoff99 30 #if 0
1108     //DBG // dbg(0,"display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
1109     #endif
1110 zoff99 28 if (x < gra->r.rl.x && x + tl > gra->r.lu.x && y + tl > gra->r.lu.y && y - tl < gra->r.rl.y)
1111     {
1112     gra->meth.draw_text(gra->priv, fg->priv, bg ? bg->priv : NULL, font->priv, label, &p_t, dx * 0x10000 / l, dy * 0x10000 / l);
1113     }
1114 zoff99 2 }
1115     }
1116     }
1117     }
1118    
1119     static void display_draw_arrow(struct point *p, int dx, int dy, int l, struct graphics_gc *gc, struct graphics *gra)
1120     {
1121     struct point pnt[3];
1122 zoff99 27 pnt[0] = pnt[1] = pnt[2] = *p;
1123     pnt[0].x += -dx * l / 65536 + dy * l / 65536;
1124     pnt[0].y += -dy * l / 65536 - dx * l / 65536;
1125     pnt[2].x += -dx * l / 65536 - dy * l / 65536;
1126     pnt[2].y += -dy * l / 65536 + dx * l / 65536;
1127 zoff99 2 gra->meth.draw_lines(gra->priv, gc->priv, pnt, 3);
1128     }
1129    
1130     static void display_draw_arrows(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count)
1131     {
1132 zoff99 27 int i, dx, dy, l;
1133 zoff99 2 struct point p;
1134 zoff99 27 for (i = 0; i < count - 1; i++)
1135     {
1136     dx = pnt[i + 1].x - pnt[i].x;
1137     dy = pnt[i + 1].y - pnt[i].y;
1138     l = sqrt(dx * dx + dy * dy);
1139     if (l)
1140     {
1141     dx = dx * 65536 / l;
1142     dy = dy * 65536 / l;
1143     p = pnt[i];
1144     p.x += dx * 15 / 65536;
1145     p.y += dy * 15 / 65536;
1146 zoff99 2 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1147 zoff99 27 p = pnt[i + 1];
1148     p.x -= dx * 15 / 65536;
1149     p.y -= dy * 15 / 65536;
1150 zoff99 2 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1151     }
1152     }
1153     }
1154    
1155 zoff99 27 static int intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy, struct point * res)
1156 zoff99 2 {
1157     int n, a, b;
1158     n = bdy * adx - bdx * ady;
1159     a = bdx * (a1->y - b1->y) - bdy * (a1->x - b1->x);
1160     b = adx * (a1->y - b1->y) - ady * (a1->x - b1->x);
1161 zoff99 27 if (n < 0)
1162     {
1163 zoff99 2 n = -n;
1164     a = -a;
1165     b = -b;
1166     }
1167     #if 0
1168     if (a < 0 || b < 0)
1169 zoff99 27 return 0;
1170 zoff99 2 if (a > n || b > n)
1171 zoff99 27 return 0;
1172 zoff99 2 #endif
1173     if (n == 0)
1174     return 0;
1175     res->x = a1->x + a * adx / n;
1176     res->y = a1->y + a * ady / n;
1177     return 1;
1178     }
1179    
1180 zoff99 27 struct circle
1181     {
1182     short x, y, fowler;
1183 zoff99 30 }
1184     circle64[] =
1185     { { 0, 128, 0 }, { 13, 127, 13 }, { 25, 126, 25 }, { 37, 122, 38 }, { 49, 118, 53 }, { 60, 113, 67 }, { 71, 106, 85 }, { 81, 99, 104 }, { 91, 91, 128 }, { 99, 81, 152 }, { 106, 71, 171 }, { 113, 60, 189 }, { 118, 49, 203 }, { 122, 37, 218 }, { 126, 25, 231 }, { 127, 13, 243 }, { 128, 0, 256 }, { 127, -13, 269 }, { 126, -25, 281 }, { 122, -37, 294 }, { 118, -49, 309 }, { 113, -60, 323 }, { 106, -71, 341 }, { 99, -81, 360 }, { 91, -91, 384 }, { 81, -99, 408 }, { 71, -106, 427 }, { 60, -113, 445 }, { 49, -118, 459 }, { 37, -122, 474 }, { 25, -126, 487 }, { 13, -127, 499 }, { 0, -128, 512 }, { -13, -127, 525 }, { -25, -126, 537 }, { -37, -122, 550 }, { -49, -118, 565 }, { -60, -113, 579 }, { -71, -106, 597 }, { -81, -99, 616 }, { -91, -91, 640 }, { -99, -81, 664 }, { -106, -71, 683 }, { -113, -60, 701 }, { -118, -49, 715 }, { -122, -37, 730 }, { -126, -25, 743 }, { -127, -13, 755 }, { -128, 0, 768 }, { -127, 13, 781 }, { -126, 25, 793 }, { -122, 37, 806 }, { -118, 49, 821 }, { -113, 60, 835 }, { -106, 71, 853 }, { -99, 81, 872 }, { -91, 91, 896 }, { -81, 99, 920 }, { -71, 106, 939 }, { -60, 113, 957 }, { -49, 118, 971 }, { -37, 122, 986 }, { -25, 126, 999 }, { -13, 127, 1011 }, };
1186 zoff99 2
1187 zoff99 27 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir)
1188 zoff99 2 {
1189     struct circle *c;
1190    
1191     #if 0
1192 zoff99 30 //DBG // dbg(0,"diameter=%d start=%d len=%d pos=%d dir=%d\n", diameter, start, len, *pos, dir);
1193 zoff99 2 #endif
1194 zoff99 27 int count = 64;
1195     int end = start + len;
1196     int i, step;
1197     c = circle64;
1198 zoff99 2 if (diameter > 128)
1199 zoff99 27 step = 1;
1200 zoff99 2 else if (diameter > 64)
1201 zoff99 27 step = 2;
1202 zoff99 2 else if (diameter > 24)
1203 zoff99 27 step = 4;
1204 zoff99 2 else if (diameter > 8)
1205 zoff99 27 step = 8;
1206 zoff99 2 else
1207 zoff99 27 step = 16;
1208     if (len > 0)
1209     {
1210     while (start < 0)
1211     {
1212     start += 1024;
1213     end += 1024;
1214 zoff99 2 }
1215 zoff99 27 while (end > 0)
1216     {
1217     i = 0;
1218 zoff99 2 while (i < count && c[i].fowler <= start)
1219 zoff99 27 {
1220     i += step;
1221     }
1222     while (i < count && c[i].fowler < end)
1223     {
1224     if (1 < *pos || 0 < dir)
1225     {
1226     res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1227     res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1228     (*pos) += dir;
1229 zoff99 2 }
1230 zoff99 27 i += step;
1231 zoff99 2 }
1232 zoff99 27 end -= 1024;
1233     start -= 1024;
1234 zoff99 2 }
1235 zoff99 27 }
1236     else
1237     {
1238     while (start > 1024)
1239     {
1240     start -= 1024;
1241     end -= 1024;
1242 zoff99 2 }
1243 zoff99 27 while (end < 1024)
1244     {
1245     i = count - 1;
1246 zoff99 2 while (i >= 0 && c[i].fowler >= start)
1247 zoff99 27 i -= step;
1248     while (i >= 0 && c[i].fowler > end)
1249     {
1250     if (1 < *pos || 0 < dir)
1251     {
1252     res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1253     res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1254     (*pos) += dir;
1255 zoff99 2 }
1256 zoff99 27 i -= step;
1257 zoff99 2 }
1258 zoff99 27 start += 1024;
1259     end += 1024;
1260 zoff99 2 }
1261     }
1262     }
1263    
1264 zoff99 27 static int fowler(int dy, int dx)
1265 zoff99 2 {
1266 zoff99 27 int adx, ady; /* Absolute Values of Dx and Dy */
1267     int code; /* Angular Region Classification Code */
1268 zoff99 2
1269 zoff99 27 adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
1270 zoff99 2 ady = (dy < 0) ? -dy : dy;
1271    
1272     code = (adx < ady) ? 1 : 0;
1273     if (dx < 0)
1274     code += 2;
1275     if (dy < 0)
1276     code += 4;
1277    
1278 zoff99 27 switch (code)
1279     {
1280     case 0:
1281     return (dx == 0) ? 0 : 128 * ady / adx; /* [ 0, 45] */
1282     case 1:
1283     return (256 - (128 * adx / ady)); /* ( 45, 90] */
1284     case 3:
1285     return (256 + (128 * adx / ady)); /* ( 90,135) */
1286     case 2:
1287     return (512 - (128 * ady / adx)); /* [135,180] */
1288     case 6:
1289     return (512 + (128 * ady / adx)); /* (180,225] */
1290     case 7:
1291     return (768 - (128 * adx / ady)); /* (225,270) */
1292     case 5:
1293     return (768 + (128 * adx / ady)); /* [270,315) */
1294     case 4:
1295     return (1024 - (128 * ady / adx));/* [315,360) */
1296 zoff99 2 }
1297     return 0;
1298     }
1299 zoff99 27
1300     static int int_sqrt(unsigned int n)
1301 zoff99 2 {
1302 zoff99 27 unsigned int h, p = 0, q = 1, r = n;
1303 zoff99 2
1304     /* avoid q rollover */
1305 zoff99 27 if (n >= (1 << (sizeof(n) * 8 - 2)))
1306     {
1307     q = 1 << (sizeof(n) * 8 - 2);
1308     }
1309     else
1310     {
1311     while (q <= n)
1312     {
1313 zoff99 2 q <<= 2;
1314     }
1315     q >>= 2;
1316     }
1317    
1318 zoff99 27 while (q != 0)
1319     {
1320 zoff99 2 h = p + q;
1321     p >>= 1;
1322 zoff99 27 if (r >= h)
1323     {
1324 zoff99 2 p += q;
1325     r -= h;
1326     }
1327     q >>= 2;
1328     }
1329     return p;
1330     }
1331    
1332 zoff99 27 struct offset
1333     {
1334     int px, py, nx, ny;
1335 zoff99 2 };
1336    
1337 zoff99 27 static void calc_offsets(int wi, int l, int dx, int dy, struct offset *res)
1338 zoff99 2 {
1339 zoff99 27 int x, y;
1340 zoff99 2
1341     x = (dx * wi) / l;
1342     y = (dy * wi) / l;
1343 zoff99 27 if (x < 0)
1344     {
1345     res->nx = -x / 2;
1346     res->px = (x - 1) / 2;
1347 zoff99 2 }
1348 zoff99 27 else
1349     {
1350     res->nx = -(x + 1) / 2;
1351     res->px = x / 2;
1352 zoff99 2 }
1353 zoff99 27 if (y < 0)
1354     {
1355     res->ny = -y / 2;
1356     res->py = (y - 1) / 2;
1357     }
1358     else
1359     {
1360     res->ny = -(y + 1) / 2;
1361     res->py = y / 2;
1362     }
1363 zoff99 2 }
1364    
1365 zoff99 29 // this func. is now obsolete!! and unused!!!!
1366     // this func. is now obsolete!! and unused!!!!
1367     // this func. is now obsolete!! and unused!!!!
1368 zoff99 27 static void 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)
1369 zoff99 2 {
1370 zoff99 27 int maxpoints = 200;
1371     struct point *res = g_alloca(sizeof(struct point) * maxpoints);
1372 zoff99 2 struct point pos, poso, neg, nego;
1373 zoff99 27 int i, dx = 0, dy = 0, l = 0, dxo = 0, dyo = 0;
1374 zoff99 30 struct offset o, oo = { 0, 0, 0, 0 };
1375 zoff99 27 int fow = 0, fowo = 0, delta;
1376     int wi, ppos = maxpoints / 2, npos = maxpoints / 2;
1377     int state, prec = 5;
1378     int max_circle_points = 20;
1379     int lscale = 16;
1380     i = 0;
1381     for (;;)
1382     {
1383     wi = *width;
1384     width += step;
1385     if (i < count - 1)
1386     {
1387     int dxs, dys, lscales;
1388 zoff99 2
1389     dx = (pnt[i + 1].x - pnt[i].x);
1390     dy = (pnt[i + 1].y - pnt[i].y);
1391     #if 0
1392     l = int_sqrt(dx * dx * lscale * lscale + dy * dy * lscale * lscale);
1393     #else
1394 zoff99 27 dxs = dx * dx;
1395     dys = dy * dy;
1396     lscales = lscale * lscale;
1397     if (dxs + dys > lscales)
1398     l = int_sqrt(dxs + dys) * lscale;
1399     else
1400     l = int_sqrt((dxs + dys) * lscales);
1401 zoff99 2 #endif
1402 zoff99 27 fow = fowler(-dy, dx);
1403 zoff99 2 }
1404 zoff99 27 if (!l)
1405     l = 1;
1406     if (wi * lscale > 10000)
1407     lscale = 10000 / wi;
1408     dbg_assert(wi * lscale <= 10000);
1409     calc_offsets(wi * lscale, l, dx, dy, &o);
1410 zoff99 2 pos.x = pnt[i].x + o.ny;
1411     pos.y = pnt[i].y + o.px;
1412     neg.x = pnt[i].x + o.py;
1413     neg.y = pnt[i].y + o.nx;
1414 zoff99 27 if (!i)
1415     state = 0;
1416     else if (i == count - 1)
1417     state = 2;
1418     else if (npos < max_circle_points || ppos >= maxpoints - max_circle_points)
1419     state = 3;
1420 zoff99 2 else
1421 zoff99 27 state = 1;
1422     switch (state)
1423     {
1424     case 1:
1425     if (fowo != fow)
1426     {
1427     poso.x = pnt[i].x + oo.ny;
1428     poso.y = pnt[i].y + oo.px;
1429     nego.x = pnt[i].x + oo.py;
1430     nego.y = pnt[i].y + oo.nx;
1431     delta = fowo - fow;
1432     if (delta < 0)
1433     delta += 1024;
1434     if (delta < 512)
1435     {
1436     if (intersection(&pos, dx, dy, &poso, dxo, dyo, &res[ppos]))
1437     {
1438     ppos++;
1439     }
1440     res[--npos] = nego;
1441     --npos;
1442     if (fill == 1)
1443     {
1444     if (draw_polylines_fast == 0)
1445     {
1446     draw_circle(&pnt[i], wi, prec, fowo - 512, -delta, res, &npos, -1);
1447     }
1448     }
1449     res[npos] = neg;
1450     }
1451     else
1452     {
1453     res[ppos++] = poso;
1454     if (fill == 1)
1455     {
1456     if (draw_polylines_fast == 0)
1457     {
1458     draw_circle(&pnt[i], wi, prec, fowo, 1024 - delta, res, &ppos, 1);
1459     }
1460     }
1461     res[ppos++] = pos;
1462     if (intersection(&neg, dx, dy, &nego, dxo, dyo, &res[npos - 1]))
1463     {
1464     npos--;
1465     }
1466     }
1467 zoff99 2 }
1468     break;
1469 zoff99 27 case 2:
1470     case 3:
1471     res[--npos] = neg;
1472     --npos;
1473     if (fill == 1)
1474     {
1475     if (draw_polylines_fast == 0)
1476     {
1477     draw_circle(&pnt[i], wi, prec, fow - 512, -512, res, &npos, -1);
1478     }
1479     }
1480     res[npos] = pos;
1481     res[ppos++] = pos;
1482     dbg_assert(npos > 0);
1483     dbg_assert(ppos < maxpoints);
1484     if (fill == 1)
1485     {
1486     gra->meth.draw_polygon2(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1487     }
1488     else
1489     {
1490     gra->meth.draw_lines_dashed(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1491     }
1492     if (state == 2)
1493     break;
1494     npos = maxpoints / 2;
1495     ppos = maxpoints / 2;
1496     case 0:
1497     res[ppos++] = neg;
1498     if (fill == 1)
1499     {
1500     if (draw_polylines_fast == 0)
1501     {
1502     draw_circle(&pnt[i], wi, prec, fow + 512, 512, res, &ppos, 1);
1503     }
1504     }
1505     res[ppos++] = pos;
1506     break;
1507 zoff99 2 }
1508 zoff99 27
1509 zoff99 2 i++;
1510 zoff99 27
1511 zoff99 2 if (i >= count)
1512 zoff99 27 {
1513 zoff99 2 break;
1514 zoff99 27 }
1515    
1516     if (step)
1517     {
1518     wi = *width;
1519     calc_offsets(wi * lscale, l, dx, dy, &oo);
1520     }
1521     else
1522     {
1523     oo = o;
1524     }
1525    
1526 zoff99 2 dxo = -dx;
1527     dyo = -dy;
1528 zoff99 27 fowo = fow;
1529 zoff99 2 }
1530     }
1531 zoff99 29 // this func. is now obsolete!! and unused!!!!
1532     // this func. is now obsolete!! and unused!!!!
1533     // this func. is now obsolete!! and unused!!!!
1534 zoff99 2
1535 zoff99 28
1536 zoff99 27 struct wpoint
1537     {
1538     int x, y, w;
1539 zoff99 2 };
1540    
1541 zoff99 27 static int clipcode(struct wpoint *p, struct point_rect *r)
1542 zoff99 2 {
1543 zoff99 27 int code = 0;
1544 zoff99 2 if (p->x < r->lu.x)
1545 zoff99 27 code = 1;
1546 zoff99 2 if (p->x > r->rl.x)
1547 zoff99 27 code = 2;
1548 zoff99 2 if (p->y < r->lu.y)
1549 zoff99 27 code |= 4;
1550 zoff99 2 if (p->y > r->rl.y)
1551 zoff99 27 code |= 8;
1552 zoff99 2 return code;
1553     }
1554    
1555 zoff99 28 #define DONT_INTERSECT 0
1556     #define DO_INTERSECT 1
1557     #define COLLINEAR 2
1558     #define SAME_SIGNS( a, b ) \
1559     (((long) ((unsigned long) a ^ (unsigned long) b)) >= 0 )
1560    
1561 zoff99 30 static int lines_intersect(int x1, int y1, /* First line segment */
1562     int x2, int y2,
1563 zoff99 28
1564 zoff99 30 int x3, int y3, /* Second line segment */
1565     int x4, int y4,
1566 zoff99 28
1567 zoff99 30 int *x, int *y /* Output value:
1568     * point of intersection */
1569     )
1570 zoff99 28 {
1571 zoff99 30 int a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
1572     int r1, r2, r3, r4; /* 'Sign' values */
1573     int denom, offset, num; /* Intermediate values */
1574 zoff99 28
1575 zoff99 30 /* Compute a1, b1, c1, where line joining points 1 and 2
1576     * is "a1 x + b1 y + c1 = 0".
1577     */
1578 zoff99 28
1579 zoff99 30 a1 = y2 - y1;
1580     b1 = x1 - x2;
1581     c1 = x2 * y1 - x1 * y2;
1582 zoff99 28
1583 zoff99 30 /* Compute r3 and r4.
1584     */
1585     r3 = a1 * x3 + b1 * y3 + c1;
1586     r4 = a1 * x4 + b1 * y4 + c1;
1587 zoff99 28
1588 zoff99 30 /* Check signs of r3 and r4. If both point 3 and point 4 lie on
1589     * same side of line 1, the line segments do not intersect.
1590     */
1591     if (r3 != 0 && r4 != 0 && SAME_SIGNS( r3, r4 ))
1592 zoff99 28 {
1593 zoff99 30 return (DONT_INTERSECT);
1594 zoff99 28 }
1595    
1596 zoff99 30 /* Compute a2, b2, c2 */
1597     a2 = y4 - y3;
1598     b2 = x3 - x4;
1599     c2 = x4 * y3 - x3 * y4;
1600 zoff99 28
1601 zoff99 30 /* Compute r1 and r2 */
1602     r1 = a2 * x1 + b2 * y1 + c2;
1603     r2 = a2 * x2 + b2 * y2 + c2;
1604 zoff99 28
1605 zoff99 30 /* Check signs of r1 and r2. If both point 1 and point 2 lie
1606     * on same side of second line segment, the line segments do
1607     * not intersect.
1608     */
1609     if (r1 != 0 && r2 != 0 && SAME_SIGNS( r1, r2 ))
1610 zoff99 28 {
1611 zoff99 30 return (DONT_INTERSECT);
1612 zoff99 28 }
1613    
1614 zoff99 30 /* Line segments intersect: compute intersection point.
1615     */
1616 zoff99 28
1617 zoff99 30 denom = a1 * b2 - a2 * b1;
1618     if (denom == 0)
1619 zoff99 28 {
1620 zoff99 30 return (COLLINEAR);
1621 zoff99 28 }
1622 zoff99 30 offset = denom < 0 ? -denom / 2 : denom / 2;
1623 zoff99 28
1624 zoff99 30 /* The denom/2 is to get rounding instead of truncating. It
1625     * is added or subtracted to the numerator, depending upon the
1626     * sign of the numerator.
1627     */
1628 zoff99 28 /*
1629 zoff99 30 num = b1 * c2 - b2 * c1;
1630     *x = ( num < 0 ? num - offset : num + offset ) / denom;
1631     num = a2 * c1 - a1 * c2;
1632     *y = ( num < 0 ? num - offset : num + offset ) / denom;
1633     */
1634 zoff99 28
1635 zoff99 30 return (DO_INTERSECT);
1636 zoff99 28 } /* lines_intersect */
1637    
1638     static int clip_line_aprox(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1639     {
1640     int code1, code2;
1641     code1 = clipcode(p1, r);
1642     code2 = clipcode(p2, r);
1643     if (code1 & code2)
1644     {
1645     // line completely invisible!
1646     return 0;
1647     }
1648 zoff99 30 else if ((code1 == 0) && (code2 == 0))
1649 zoff99 28 {
1650     // line completely visible!
1651     return 1;
1652     }
1653 zoff99 30 else if ((code1 == 0) || (code2 == 0))
1654 zoff99 28 {
1655     // at least 1 point of line is visible
1656     return 2;
1657     }
1658     else
1659     {
1660     int xx;
1661     int yy;
1662     // top
1663 zoff99 30 int ret_ = lines_intersect(p1->x, p1->y, p2->x, p2->y, r->lu.x, r->lu.y, r->rl.x, r->lu.y, &xx, &yy);
1664 zoff99 28 if (ret_ == DO_INTERSECT)
1665     {
1666     return 3;
1667     }
1668     // bottom
1669 zoff99 30 ret_ = lines_intersect(p1->x, p1->y, p2->x, p2->y, r->lu.x, r->rl.y, r->rl.x, r->rl.y, &xx, &yy);
1670 zoff99 28 if (ret_ == DO_INTERSECT)
1671     {
1672     return 3;
1673     }
1674     // left
1675 zoff99 30 ret_ = lines_intersect(p1->x, p1->y, p2->x, p2->y, r->lu.x, r->lu.y, r->lu.x, r->rl.y, &xx, &yy);
1676 zoff99 28 if (ret_ == DO_INTERSECT)
1677     {
1678     return 3;
1679     }
1680     // right
1681 zoff99 30 ret_ = lines_intersect(p1->x, p1->y, p2->x, p2->y, r->rl.x, r->lu.y, r->rl.x, r->rl.y, &xx, &yy);
1682 zoff99 28 if (ret_ == DO_INTERSECT)
1683     {
1684     return 3;
1685     }
1686     }
1687     // not visible
1688     return 0;
1689     }
1690    
1691 zoff99 27 static int clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1692 zoff99 2 {
1693 zoff99 27 int code1, code2, ret = 1;
1694     int dx, dy, dw;
1695     code1 = clipcode(p1, r);
1696 zoff99 2 if (code1)
1697     ret |= 2;
1698 zoff99 27 code2 = clipcode(p2, r);
1699 zoff99 2 if (code2)
1700     ret |= 4;
1701 zoff99 27 dx = p2->x - p1->x;
1702     dy = p2->y - p1->y;
1703     dw = p2->w - p1->w;
1704     while (code1 || code2)
1705     {
1706 zoff99 2 if (code1 & code2)
1707 zoff99 28 {
1708 zoff99 2 return 0;
1709 zoff99 28 }
1710 zoff99 27 if (code1 & 1)
1711     {
1712     p1->y += (r->lu.x - p1->x) * dy / dx;
1713     p1->w += (r->lu.x - p1->x) * dw / dx;
1714     p1->x = r->lu.x;
1715 zoff99 2 }
1716 zoff99 27 else if (code1 & 2)
1717     {
1718     p1->y += (r->rl.x - p1->x) * dy / dx;
1719     p1->w += (r->rl.x - p1->x) * dw / dx;
1720     p1->x = r->rl.x;
1721     }
1722     else if (code1 & 4)
1723     {
1724     p1->x += (r->lu.y - p1->y) * dx / dy;
1725     p1->w += (r->lu.y - p1->y) * dw / dy;
1726     p1->y = r->lu.y;
1727     }
1728     else if (code1 & 8)
1729     {
1730     p1->x += (r->rl.y - p1->y) * dx / dy;
1731     p1->w += (r->rl.y - p1->y) * dw / dy;
1732     p1->y = r->rl.y;
1733     }
1734     code1 = clipcode(p1, r);
1735 zoff99 2 if (code1 & code2)
1736     return 0;
1737 zoff99 27 if (code2 & 1)
1738     {
1739     p2->y += (r->lu.x - p2->x) * dy / dx;
1740     p2->w += (r->lu.x - p2->x) * dw / dx;
1741     p2->x = r->lu.x;
1742 zoff99 2 }
1743 zoff99 27 else if (code2 & 2)
1744     {
1745     p2->y += (r->rl.x - p2->x) * dy / dx;
1746     p2->w += (r->rl.x - p2->x) * dw / dx;
1747     p2->x = r->rl.x;
1748     }
1749     else if (code2 & 4)
1750     {
1751     p2->x += (r->lu.y - p2->y) * dx / dy;
1752     p2->w += (r->lu.y - p2->y) * dw / dy;
1753     p2->y = r->lu.y;
1754     }
1755     else if (code2 & 8)
1756     {
1757     p2->x += (r->rl.y - p2->y) * dx / dy;
1758     p2->w += (r->rl.y - p2->y) * dw / dy;
1759     p2->y = r->rl.y;
1760     }
1761     code2 = clipcode(p2, r);
1762 zoff99 2 }
1763     return ret;
1764     }
1765    
1766 zoff99 30 static void 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, int dashes, struct color *c)
1767 zoff99 2 {
1768 zoff99 27 struct point *p = g_alloca(sizeof(struct point) * (count + 1));
1769     struct wpoint p1, p2;
1770 zoff99 28 int i;
1771     int code;
1772 zoff99 2 int wmax;
1773 zoff99 28 int out = 0;
1774 zoff99 30 // const int max_segs = 2000;
1775     const int max_segs = 60; // send max this many segments to java with one single call
1776 zoff99 27 struct point_rect r = gra->r;
1777 zoff99 2
1778 zoff99 30 //if (count > 30)
1779     //{
1780     // dbg(0,"segment count=%d\n", count);
1781     //}
1782 zoff99 29
1783     #if 0
1784 zoff99 28 // check if whole line is within a 2x2 pixel square
1785     if (order < 11)
1786 zoff99 27 {
1787 zoff99 28 const int max_dist = 2*2;
1788     int need_draw = 0;
1789     int diff;
1790     for (i = 0; i < count; i++)
1791 zoff99 27 {
1792 zoff99 28 if (i > 0)
1793     {
1794     p2.x = pa[i].x;
1795     p2.y = pa[i].y;
1796     diff = (p2.x - p1.x) * (p2.y - p1.y);
1797     if (diff < 0)
1798     {
1799     diff = -diff;
1800     }
1801    
1802     if (diff > max_dist)
1803     {
1804     // line is bigger, so we need to draw it
1805     need_draw = 1;
1806     break;
1807     }
1808     }
1809     else
1810     {
1811     p1.x = pa[i - 1].x;
1812     p1.y = pa[i - 1].y;
1813     }
1814 zoff99 2 }
1815 zoff99 28
1816     if (need_draw == 0)
1817     {
1818     // dont draw this line
1819     return;
1820     }
1821 zoff99 2 }
1822 zoff99 29 #endif
1823 zoff99 27
1824 zoff99 28 // calc visible area on screen
1825 zoff99 30 wmax = width[0];
1826     r.lu.x -= wmax;
1827     r.lu.y -= wmax;
1828     r.rl.x += wmax;
1829     r.rl.y += wmax;
1830 zoff99 28
1831 zoff99 27 for (i = 0; i < count; i++)
1832     {
1833 zoff99 28 if (i > 0)
1834 zoff99 27 {
1835     p1.x = pa[i - 1].x;
1836     p1.y = pa[i - 1].y;
1837     p2.x = pa[i].x;
1838     p2.y = pa[i].y;
1839 zoff99 28 /* 0 = invisible, 1 = completely visible, 2,3 = at least part of line visible */
1840 zoff99 30 code = clip_line_aprox(&p1, &p2, &r);
1841 zoff99 29 // code = 1;
1842 zoff99 27
1843 zoff99 28 if (code > 0)
1844 zoff99 27 {
1845 zoff99 28 if (out == 0)
1846     {
1847 zoff99 30 p[out].x = p1.x;
1848     p[out].y = p1.y;
1849 zoff99 28 out++;
1850     }
1851 zoff99 30 p[out].x = p2.x;
1852     p[out].y = p2.y;
1853 zoff99 2 out++;
1854 zoff99 28
1855     if ((out <= max_segs) && (i < (count - 1)))
1856     {
1857     // ok gather more line segs
1858     continue;
1859     }
1860 zoff99 2 }
1861 zoff99 28 else // (code == 0)
1862 zoff99 27 {
1863 zoff99 28 if (out == 0)
1864     {
1865     // first visible line seg not yet found, search on ...
1866     continue;
1867     }
1868 zoff99 2 }
1869 zoff99 27
1870 zoff99 28 // PAINT --- LINE SEGMENTS ------------
1871     // PAINT --- LINE SEGMENTS ------------
1872    
1873 zoff99 30 if ((poly == 1) || (poly == 0))
1874     {
1875     // normal street
1876     //if (1 == 0)
1877     //{
1878     // // draw as polygon --> OLD method
1879     // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 1, order, 0);
1880     //}
1881     //else
1882     //{
1883     // draw as line
1884     gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c);
1885     //draw_lines_count_3++;
1886     //}
1887 zoff99 27
1888 zoff99 30 // one way arrow
1889     if ((oneway > 0) && (order > 13))
1890     {
1891     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1892     //draw_lines_count_2++;
1893     }
1894     }
1895     else if (poly == 2)
1896     {
1897     // ******* street is underground ********
1898     // ******* street is underground ********
1899     // ******* street is underground ********
1900 zoff99 27
1901 zoff99 30 //if (1 == 0)
1902     //{
1903     // // draw as polygon --> OLD method
1904     // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 0, order, 0);
1905     //}
1906     //else
1907     //{
1908 zoff99 28
1909 zoff99 30 // draw as line
1910     gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 1, dashes, c);
1911     //draw_lines_count_4++;
1912     //}
1913 zoff99 27
1914 zoff99 30 // one way arrow
1915     if ((oneway > 0) && (order > 13))
1916     {
1917     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1918     //draw_lines_count_2++;
1919     }
1920     }
1921     else if (poly == 3)
1922     {
1923     // ******* street has bridge ********
1924     // ******* street has bridge ********
1925     // ******* street has bridge ********
1926     gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 2, dashes, c);
1927     //draw_lines_count_4++;
1928 zoff99 27
1929 zoff99 30 // one way arrow
1930     if ((oneway > 0) && (order > 13))
1931     {
1932     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1933     //draw_lines_count_2++;
1934     }
1935     }
1936     // --> now NOT used anymore!!
1937     else // poly==0 -> street that is only a line (width=1)
1938     {
1939     // OLD // gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, 0);
1940 zoff99 27
1941 zoff99 30 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c);
1942     //draw_lines_count_3++;
1943 zoff99 27
1944 zoff99 30 // one way arrow
1945     if ((oneway > 0) && (order > 13))
1946     {
1947     gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1948     //draw_lines_count_2++;
1949     }
1950     }
1951 zoff99 28
1952     out = 0; // reset point counter after painting
1953     // PAINT --- LINE SEGMENTS ------------
1954     // PAINT --- LINE SEGMENTS ------------
1955     // PAINT --- LINE SEGMENTS ------------
1956 zoff99 2 }
1957     }
1958     }
1959    
1960 zoff99 27 static int is_inside(struct point *p, struct point_rect *r, int edge)
1961 zoff99 2 {
1962 zoff99 27 switch (edge)
1963     {
1964     case 0:
1965     return p->x >= r->lu.x;
1966     case 1:
1967     return p->x <= r->rl.x;
1968     case 2:
1969     return p->y >= r->lu.y;
1970     case 3:
1971     return p->y <= r->rl.y;
1972     default:
1973     return 0;
1974 zoff99 2 }
1975     }
1976    
1977 zoff99 27 static void poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
1978 zoff99 2 {
1979 zoff99 27 int dx = p2->x - p1->x;
1980     int dy = p2->y - p1->y;
1981     switch (edge)
1982     {
1983     case 0:
1984     ret->y = p1->y + (r->lu.x - p1->x) * dy / dx;
1985     ret->x = r->lu.x;
1986     break;
1987     case 1:
1988     ret->y = p1->y + (r->rl.x - p1->x) * dy / dx;
1989     ret->x = r->rl.x;
1990     break;
1991     case 2:
1992     ret->x = p1->x + (r->lu.y - p1->y) * dx / dy;
1993     ret->y = r->lu.y;
1994     break;
1995     case 3:
1996     ret->x = p1->x + (r->rl.y - p1->y) * dx / dy;
1997     ret->y = r->rl.y;
1998     break;
1999 zoff99 2 }
2000     }
2001    
2002 zoff99 27 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
2003 zoff99 2 {
2004 zoff99 27 struct point_rect r = gra->r;
2005     struct point *pout, *p, *s, pi, *p1, *p2;
2006     int limit = 10000;
2007     struct point *pa1 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2008     struct point *pa2 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2009     int count_out, edge = 3;
2010 zoff99 2 int i;
2011     #if 0
2012     r.lu.x+=20;
2013     r.lu.y+=20;
2014     r.rl.x-=20;
2015     r.rl.y-=20;
2016     #endif
2017 zoff99 27 if (count_in < limit)
2018     {
2019     p1 = pa1;
2020     p2 = pa2;
2021     }
2022     else
2023     {
2024 zoff99 30 p1 =g_new(struct point, count_in*8+1);
2025     p2=g_new(struct point, count_in*8+1);
2026     }
2027 zoff99 2
2028 zoff99 30 pout=p1;
2029     for (edge = 0; edge < 4; edge++)
2030     {
2031     p=pin;
2032     s=pin+count_in-1;
2033     count_out=0;
2034     for (i = 0; i < count_in; i++)
2035 zoff99 27 {
2036 zoff99 30 if (is_inside(p, &r, edge))
2037 zoff99 27 {
2038 zoff99 30 if (! is_inside(s, &r, edge))
2039 zoff99 27 {
2040 zoff99 30 poly_intersection(s,p,&r,edge,&pi);
2041     pout[count_out++]=pi;
2042 zoff99 27 }
2043 zoff99 30 pout[count_out++]=*p;
2044 zoff99 2 }
2045 zoff99 27 else
2046     {
2047 zoff99 30 if (is_inside(s, &r, edge))
2048     {
2049     poly_intersection(p,s,&r,edge,&pi);
2050     pout[count_out++]=pi;
2051     }
2052 zoff99 2 }
2053 zoff99 30 s=p;
2054     p++;
2055 zoff99 2 }
2056 zoff99 30 count_in=count_out;
2057     if (pin == p1)
2058 zoff99 27 {
2059 zoff99 30 pin=p2;
2060     pout=p1;
2061 zoff99 2 }
2062 zoff99 30 else
2063     {
2064     pin=p1;
2065     pout=p2;
2066     }
2067 zoff99 2 }
2068    
2069 zoff99 30 gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
2070     if (count_in >= limit)
2071     {
2072     g_free(p1);
2073     g_free(p2);
2074     }
2075     }
2076    
2077 zoff99 27 static void display_context_free(struct display_context *dc)
2078 zoff99 2 {
2079     if (dc->gc)
2080     graphics_gc_destroy(dc->gc);
2081     if (dc->gc_background)
2082     graphics_gc_destroy(dc->gc_background);
2083     if (dc->img)
2084     graphics_image_free(dc->gra, dc->img);
2085 zoff99 27 dc->gc = NULL;
2086     dc->gc_background = NULL;
2087     dc->img = NULL;
2088 zoff99 2 }
2089    
2090     static struct graphics_font *
2091     get_font(struct graphics *gra, int size)
2092     {
2093     if (size > 64)
2094 zoff99 27 {
2095     size = 64;
2096     }
2097     if (size >= gra->font_len)
2098     {
2099 zoff99 2 gra->font=g_renew(struct graphics_font *, gra->font, size+1);
2100     while (gra->font_len <= size)
2101 zoff99 27 {
2102     gra->font[gra->font_len++] = NULL;
2103     }
2104 zoff99 2 }
2105 zoff99 27 if (!gra->font[size])
2106     {
2107     gra->font[size] = graphics_font_new(gra, size * gra->font_size, 0);
2108     }
2109 zoff99 2 return gra->font[size];
2110     }
2111    
2112     void graphics_draw_text_std(struct graphics *this_, int text_size, char *text, struct point *p)
2113     {
2114 zoff99 27 struct graphics_font *font = get_font(this_, text_size);
2115 zoff99 2 struct point bbox[4];
2116     int i;
2117    
2118     graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
2119 zoff99 27 for (i = 0; i < 4; i++)
2120     {
2121     bbox[i].x += p->x;
2122     bbox[i].y += p->y;
2123 zoff99 2 }
2124 zoff99 27 graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x - bbox[0].x, bbox[0].y - bbox[1].y + 5);
2125 zoff99 2 graphics_draw_text(this_, this_->gc[1], this_->gc[2], font, text, p, 0x10000, 0);
2126     }
2127    
2128     char *
2129     graphics_icon_path(char *icon)
2130     {
2131     static char *navit_sharedir;
2132 zoff99 27 char *ret = NULL;
2133     struct file_wordexp *wordexp = NULL;
2134     // dbg(1, "enter %s\n", icon);
2135     if (strchr(icon, '$'))
2136     {
2137     wordexp = file_wordexp_new(icon);
2138 zoff99 2 if (file_wordexp_get_count(wordexp))
2139 zoff99 27 {
2140     icon = file_wordexp_get_array(wordexp)[0];
2141     }
2142 zoff99 2 }
2143 zoff99 27
2144     if (strchr(icon, '/'))
2145     {
2146     ret = g_strdup(icon);
2147     }
2148     else
2149     {
2150 zoff99 2 #ifdef HAVE_API_ANDROID
2151     // get resources for the correct screen density
2152     //
2153     // this part not needed, android unpacks only the correct version into res/drawable dir!
2154 zoff99 27 // // dbg(1,"android icon_path %s\n",icon);
2155 zoff99 2 // static char *android_density;
2156     // android_density = getenv("ANDROID_DENSITY");
2157     // ret=g_strdup_printf("res/drawable-%s/%s",android_density ,icon);
2158     ret=g_strdup_printf("res/drawable/%s" ,icon);
2159     #else
2160 zoff99 27 if (!navit_sharedir)
2161     {
2162 zoff99 2 navit_sharedir = getenv("NAVIT_SHAREDIR");
2163 zoff99 27 }
2164     ret = g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
2165 zoff99 2 #endif
2166     }
2167 zoff99 27
2168 zoff99 2 if (wordexp)
2169 zoff99 27 {
2170 zoff99 2 file_wordexp_destroy(wordexp);
2171 zoff99 27 }
2172    
2173 zoff99 2 return ret;
2174     }
2175    
2176 zoff99 27 static int limit_count(struct coord *c, int count)
2177 zoff99 2 {
2178     int i;
2179 zoff99 27 for (i = 1; i < count; i++)
2180     {
2181 zoff99 2 if (c[i].x == c[0].x && c[i].y == c[0].y)
2182 zoff99 27 return i + 1;
2183 zoff99 2 }
2184     return count;
2185     }
2186    
2187 zoff99 28 static void displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc, int order, int allow_dashed, int run_type)
2188 zoff99 2 {
2189 zoff99 30 //// dbg(0, "EEnter\n");
2190 zoff99 2
2191 zoff99 27 int *width = g_alloca(sizeof(int) * dc->maxlen);
2192     struct point *pa = g_alloca(sizeof(struct point) * dc->maxlen);
2193     struct graphics *gra = dc->gra;
2194     struct graphics_gc *gc = dc->gc;
2195     struct element *e = dc->e;
2196     struct graphics_image *img = dc->img;
2197 zoff99 2 struct point p;
2198     char *path;
2199    
2200 zoff99 30 //if (run_type > 100) // dbg(0,"enter\n");
2201 zoff99 2
2202     while (di)
2203     {
2204 zoff99 30
2205     // stop drawing is requested
2206     if (cancel_drawing_global == 1)
2207     {
2208     break;
2209     }
2210    
2211 zoff99 28 if (run_type != 99)
2212     {
2213     if (run_type == 1)
2214     {
2215     if (di->item.flags & AF_UNDERGROUND)
2216     {
2217     // next item
2218     di = di->next;
2219     continue;
2220     }
2221     else if (di->item.flags & AF_BRIDGE)
2222     {
2223     // next item
2224     di = di->next;
2225     continue;
2226     }
2227     }
2228     else if (run_type == 2)
2229     {
2230     // tunnel
2231     if (di->item.flags & AF_UNDERGROUND)
2232     {
2233     }
2234     else
2235     {
2236     // next item
2237     di = di->next;
2238     continue;
2239     }
2240     }
2241     else if (run_type == 3)
2242     {
2243     // bridge
2244     if (di->item.flags & AF_BRIDGE)
2245     {
2246     }
2247     else
2248     {
2249     // next item
2250     di = di->next;
2251     continue;
2252     }
2253     }
2254     }
2255    
2256 zoff99 27 int i, count = di->count, mindist = dc->mindist;
2257 zoff99 2
2258 zoff99 27 if (!gc)
2259 zoff99 2 {
2260 zoff99 27 gc = graphics_gc_new(gra);
2261 zoff99 2 graphics_gc_set_foreground(gc, &e->color);
2262 zoff99 27 dc->gc = gc;
2263 zoff99 2 }
2264    
2265     if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
2266 zoff99 27 {
2267     count = limit_count(di->c, count);
2268     }
2269 zoff99 2 if (dc->type == type_poly_water_tiled)
2270 zoff99 27 {
2271     mindist = 0;
2272     }
2273 zoff99 28 if (dc->type == type_border_country)
2274     {
2275     if (order < 10)
2276     {
2277     mindist = 3;
2278     }
2279     }
2280 zoff99 2 if (dc->e->type == element_polyline)
2281 zoff99 27 {
2282     count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
2283     }
2284 zoff99 2 else
2285 zoff99 27 {
2286     count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
2287     }
2288 zoff99 2
2289     switch (e->type)
2290     {
2291 zoff99 27 case element_polygon:
2292     graphics_draw_polygon_clipped(gra, gc, pa, count);
2293     break;
2294     case element_polyline:
2295 zoff99 2 {
2296     gc->meth.gc_set_linewidth(gc->priv, 1);
2297    
2298 zoff99 27 int poly = e->u.polyline.width > 1;
2299 zoff99 2
2300     // detect underground streets/lines/etc ...
2301 zoff99 27 //if ((allow_dashed) && (di->item.flags & AF_UNDERGROUND))
2302     if (di->item.flags & AF_UNDERGROUND)
2303 zoff99 2 {
2304 zoff99 27 poly = 2;
2305 zoff99 2 }
2306 zoff99 27 else if (di->item.flags & AF_BRIDGE)
2307     {
2308     poly = 3;
2309     }
2310 zoff99 2
2311 zoff99 27 int oneway = 0;
2312 zoff99 2
2313     if (di->item.flags & AF_ONEWAYREV)
2314     {
2315 zoff99 27 oneway = 2;
2316 zoff99 2 }
2317     else if (di->item.flags & AF_ONEWAY)
2318     {
2319 zoff99 27 oneway = 1;
2320 zoff99 2 }
2321    
2322 zoff99 27 // -------- apply dashes -------
2323 zoff99 30 //if (e->u.polyline.dash_num > 0)
2324     //{
2325     // graphics_gc_set_dashes(gra, gc, e->u.polyline.width, e->u.polyline.offset, e->u.polyline.dash_table, e->u.polyline.dash_num, order);
2326     //}
2327 zoff99 27 // -------- apply dashes -------
2328    
2329 zoff99 30 //for (i = 0; i < count; i++)
2330     //{
2331     // if (width[i] < 1)
2332     // {
2333     // width[i] = 1;
2334     // }
2335     //}
2336 zoff99 27
2337 zoff99 28 if (dc->type == type_border_country)
2338     {
2339 zoff99 30 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway, e->u.polyline.dash_num, &e->color);
2340 zoff99 28 }
2341     else
2342     {
2343 zoff99 30 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->color);
2344 zoff99 28 // graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway);
2345     }
2346    
2347 zoff99 27 // -------- cancel dashes -------
2348 zoff99 30 //if (e->u.polyline.dash_num > 0)
2349     //{
2350     // int dummy_1[1];
2351     // dummy_1[0] = 0;
2352     // graphics_gc_set_dashes(gra, gc, e->u.polyline.width, e->u.polyline.offset, dummy_1, e->u.polyline.dash_num, order);
2353     //}
2354     //if (run_type > 100) // dbg(0,"gg005\n");
2355 zoff99 27 // -------- cancel dashes -------
2356 zoff99 2 }
2357 zoff99 27 break;
2358     case element_circle:
2359     if (count)
2360     {
2361     if (e->u.circle.width > 1)
2362     {
2363     gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
2364     }
2365 zoff99 2
2366 zoff99 30 //// dbg(0, "graphics_draw_circle\n");
2367 zoff99 27 graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
2368 zoff99 2
2369 zoff99 27 if (di->label && e->text_size)
2370     {
2371     struct graphics_font *font = get_font(gra, e->text_size);
2372     struct graphics_gc *gc_background = dc->gc_background;
2373     if (!gc_background && e->u.circle.background_color.a)
2374     {
2375     gc_background = graphics_gc_new(gra);
2376     graphics_gc_set_foreground(gc_background, &e->u.circle.background_color);
2377     dc->gc_background = gc_background;
2378     }
2379     p.x = pa[0].x + 3;
2380     p.y = pa[0].y + 10;
2381    
2382     if (font)
2383     {
2384     gra->meth.draw_text(gra->priv, gc->priv, gc_background ? gc_background->priv : NULL, font->priv, di->label, &p, 0x10000, 0);
2385     }
2386     else
2387     {
2388 zoff99 30 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2389 zoff99 27 }
2390     }
2391     }
2392     break;
2393     case element_text:
2394     if (count && di->label)
2395 zoff99 2 {
2396 zoff99 30 //if (run_type > 100) // dbg(0,"gg006\n");
2397 zoff99 28
2398 zoff99 27 struct graphics_font *font = get_font(gra, e->text_size);
2399     struct graphics_gc *gc_background = dc->gc_background;
2400    
2401     if (!gc_background && e->u.text.background_color.a)
2402     {
2403     gc_background = graphics_gc_new(gra);
2404     graphics_gc_set_foreground(gc_background, &e->u.text.background_color);
2405     dc->gc_background = gc_background;
2406 zoff99 2 }
2407    
2408     if (font)
2409 zoff99 27 {
2410     label_line(gra, gc, gc_background, font, pa, count, di->label);
2411     }
2412 zoff99 2 else
2413 zoff99 27 {
2414 zoff99 30 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2415 zoff99 27 }
2416 zoff99 2 }
2417 zoff99 27 break;
2418     case element_icon:
2419     if (count)
2420 zoff99 2 {
2421 zoff99 27 if (!img || item_is_custom_poi(di->item))
2422 zoff99 2 {
2423 zoff99 27 if (item_is_custom_poi(di->item))
2424     {
2425     char *icon;
2426     char *src;
2427     if (img)
2428     {
2429     graphics_image_free(dc->gra, img);
2430     }
2431     src = e->u.icon.src;
2432     if (!src || !src[0])
2433     {
2434     src = "%s";
2435     }
2436     icon = g_strdup_printf(src, di->label + strlen(di->label) + 1);
2437     path = graphics_icon_path(icon);
2438     g_free(icon);
2439     }
2440     else
2441     {
2442     path = graphics_icon_path(e->u.icon.src);
2443     }
2444     img = graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
2445 zoff99 2 if (img)
2446 zoff99 27 {
2447     dc->img = img;
2448     }
2449     else
2450     {
2451 zoff99 30 // missing icon // // dbg(0, "-- ICON MISSING -- failed to load icon '%s'\n", path);
2452 zoff99 27 }
2453     g_free(path);
2454 zoff99 2 }
2455 zoff99 27
2456     if (img)
2457 zoff99 2 {
2458 zoff99 27 p.x = pa[0].x - img->hot.x;
2459     p.y = pa[0].y - img->hot.y;
2460 zoff99 30 //// dbg(0, "icon: '%s'\n", path);
2461     //// dbg(0,"hot: %d %d\n", img->hot.x, img->hot.y);
2462 zoff99 27 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
2463 zoff99 2 }
2464     }
2465 zoff99 27 break;
2466     case element_image:
2467 zoff99 30 //// dbg(0, "image: '%s'\n", di->label);
2468 zoff99 27 if (gra->meth.draw_image_warp)
2469     gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2470     else
2471 zoff99 2 {
2472 zoff99 30 // // dbg(0,"draw_image_warp not supported by graphics driver drawing '%s'\n",di->label);
2473 zoff99 2 }
2474 zoff99 27 break;
2475     case element_arrows:
2476     display_draw_arrows(gra, gc, pa, count);
2477     break;
2478 zoff99 30 //default:
2479     // printf("Unhandled element type %d\n", e->type);
2480 zoff99 2 }
2481 zoff99 27 di = di->next;
2482 zoff99 2 }
2483 zoff99 28
2484 zoff99 30 //if (run_type > 100) // dbg(0,"gg099\n");
2485 zoff99 28
2486 zoff99 2 }
2487     /**
2488     * FIXME
2489     * @param <>
2490     * @returns <>
2491     * @author Martin Schaller (04/2008)
2492 zoff99 27 */
2493 zoff99 28 static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, int run_type)
2494 zoff99 2 {
2495 zoff99 30 // // dbg(0,"Enter\n");
2496 zoff99 2
2497     struct element *e;
2498 zoff99 27 GList *es, *types;
2499     struct display_context *dc = &display_list->dc;
2500 zoff99 2 struct hash_entry *entry;
2501 zoff99 28 int draw_it = 1;
2502 zoff99 2
2503 zoff99 28 #ifdef NAVIT_MEASURE_TIME_DEBUG
2504     clock_t s_ = debug_measure_start();
2505     #endif
2506    
2507 zoff99 27 es = itm->elements;
2508 zoff99 2 while (es)
2509     {
2510 zoff99 30 //// dbg(0,"*es\n");
2511 zoff99 27 e = es->data;
2512     dc->e = e;
2513     types = itm->type;
2514 zoff99 2 while (types)
2515     {
2516 zoff99 28 draw_it = 1;
2517    
2518 zoff99 30 // stop drawing is requested
2519     if (cancel_drawing_global == 1)
2520     {
2521     break;
2522     }
2523    
2524 zoff99 27 dc->type = GPOINTER_TO_INT(types->data);
2525 zoff99 30 //// dbg(0,"**type=%d\n", dc->type);
2526 zoff99 28
2527     if (dc->type == type_poly_water_from_relations)
2528 zoff99 2 {
2529 zoff99 28 // ok "poly_water_from_relations" is found, now what?
2530     if (enable_water_from_relations == 0)
2531     {
2532     draw_it = 0;
2533     }
2534 zoff99 2 }
2535 zoff99 28
2536     if (draw_it == 1)
2537     {
2538     entry = get_hash_entry(display_list, dc->type);
2539     if (entry && entry->di)
2540     {
2541 zoff99 30 // // dbg(0,"++type=%s\n", item_to_name(dc->type));
2542 zoff99 28 //if (!strcmp(item_to_name(dc->type), "border_country"))
2543     //{
2544     // displayitem_draw(entry->di, NULL, dc, display_list->order, 1, 101);
2545     //}
2546     //else
2547     //{
2548 zoff99 30 displayitem_draw(entry->di, NULL, dc, display_list->order, 1, run_type);
2549 zoff99 28 //}
2550 zoff99 30 // // dbg(0,"**+gc free\n");
2551 zoff99 28 display_context_free(dc);
2552     }
2553     }
2554 zoff99 27 types = g_list_next(types);
2555 zoff99 28 draw_it = 1;
2556 zoff99 2 }
2557 zoff99 27 es = g_list_next(es);
2558 zoff99 2 }
2559 zoff99 28
2560     #ifdef NAVIT_MEASURE_TIME_DEBUG
2561     debug_mrp("xdisplay_draw_elements:", debug_measure_end(s_));
2562     #endif
2563 zoff99 2 }
2564    
2565 zoff99 27 void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
2566 zoff99 2 {
2567 zoff99 30 // dbg(0, "EEnter\n");
2568 zoff99 2
2569     // HINT: seems to only be called from vehicle.c (draw the vehicle on screen)
2570    
2571     GList *es;
2572     struct display_context dc;
2573 zoff99 27 int max_coord = 32;
2574     char *buffer = g_alloca(sizeof(struct displayitem) + max_coord * sizeof(struct coord));
2575     struct displayitem *di = (struct displayitem *) buffer;
2576     es = itm->elements;
2577     di->item.type = type_none;
2578     di->item.id_hi = 0;
2579     di->item.id_lo = 0;
2580     di->item.map = NULL;
2581     di->label = label;
2582     dc.gra = gra;
2583     dc.gc = NULL;
2584     dc.gc_background = NULL;
2585     dc.img = NULL;
2586     dc.pro = projection_screen;
2587     dc.mindist = 0;
2588     dc.trans = t;
2589     dc.type = type_none;
2590     dc.maxlen = max_coord;
2591     while (es)
2592     {
2593 zoff99 30 // dbg(0, "while loop\n");
2594 zoff99 27 struct element *e = es->data;
2595     if (e->coord_count)
2596     {
2597     if (e->coord_count > max_coord)
2598     {
2599 zoff99 30 //DBG // dbg(0, "maximum number of coords reached: %d > %d\n", e->coord_count, max_coord);
2600 zoff99 27 di->count = max_coord;
2601     }
2602     else
2603 zoff99 28 {
2604 zoff99 27 di->count = e->coord_count;
2605 zoff99 28 }
2606 zoff99 27 memcpy(di->c, e->coord, di->count * sizeof(struct coord));
2607 zoff99 2 }
2608 zoff99 27 else
2609     {
2610     di->c[0].x = 0;
2611     di->c[0].y = 0;
2612     di->count = 1;
2613     }
2614     dc.e = e;
2615     di->next = NULL;
2616 zoff99 28 displayitem_draw(di, NULL, &dc, transform_get_scale(t), 0, 99);
2617 zoff99 2 display_context_free(&dc);
2618 zoff99 27 es = g_list_next(es);
2619 zoff99 2 }
2620     }
2621    
2622     /**
2623     * FIXME
2624     * @param <>
2625     * @returns <>
2626     * @author Martin Schaller (04/2008)
2627 zoff99 27 */
2628 zoff99 2 static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order)
2629     {
2630 zoff99 30 //DBG // dbg(0,"ooo enter ooo\n");
2631 zoff99 2
2632     GList *itms;
2633     struct itemgra *itm;
2634 zoff99 28
2635 zoff99 30 int run_type = 0; // 99 -> normal
2636     // 1 -> normal streets (except tunnels and bridges)
2637     // 2 -> tunnel
2638     // 3 -> bridge
2639 zoff99 28
2640 zoff99 29 int send_refresh = 0;
2641    
2642 zoff99 28 int order_corrected = order + shift_order;
2643 zoff99 27 if (order_corrected < limit_order_corrected)
2644 zoff99 2 {
2645 zoff99 27 order_corrected = limit_order_corrected;
2646 zoff99 2 }
2647 zoff99 28
2648     int order_corrected_2 = order + shift_order;
2649 zoff99 27 if (order < 0)
2650     {
2651     order_corrected_2 = 0;
2652     }
2653 zoff99 2
2654 zoff99 30 //// dbg(0,"layer name=%s\n", lay->name);
2655 zoff99 27
2656 zoff99 28 if ((strncmp("streets_1", lay->name, 9) == 0))
2657 zoff99 2 {
2658 zoff99 30 //// dbg(0,"MT:7.3.1 - tunnel start\n");
2659 zoff99 28 //draw_lines_count_2 = 0;
2660     //draw_lines_count_3 = 0;
2661     //draw_lines_count_4 = 0;
2662    
2663 zoff99 29 send_refresh = 1;
2664    
2665 zoff99 28 run_type = 2;
2666     itms = lay->itemgras;
2667     while (itms)
2668 zoff99 27 {
2669 zoff99 28 // stop drawing is requested
2670     if (cancel_drawing_global == 1)
2671     {
2672 zoff99 30 //DBG // dbg(0, "** STOP MD 002 **\n");
2673 zoff99 28 break;
2674     }
2675    
2676     itm = itms->data;
2677     //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2678     if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2679     {
2680     xdisplay_draw_elements(gra, display_list, itm, run_type);
2681     }
2682     itms = g_list_next(itms);
2683 zoff99 27 }
2684    
2685 zoff99 30 //// dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2686     //// dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2687     //// dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2688 zoff99 28 //draw_lines_count_2 = 0;
2689     //draw_lines_count_3 = 0;
2690     //draw_lines_count_4 = 0;
2691 zoff99 30 //// dbg(0,"MT:7.3.2 - streets start\n");
2692 zoff99 28
2693     run_type = 1;
2694     itms = lay->itemgras;
2695     while (itms)
2696 zoff99 27 {
2697 zoff99 28 // stop drawing is requested
2698     if (cancel_drawing_global == 1)
2699     {
2700 zoff99 30 //DBG // dbg(0, "** STOP MD 002 **\n");
2701 zoff99 28 break;
2702     }
2703    
2704     itm = itms->data;
2705     //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2706     if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2707     {
2708     xdisplay_draw_elements(gra, display_list, itm, run_type);
2709     }
2710     itms = g_list_next(itms);
2711 zoff99 27 }
2712    
2713 zoff99 28 /*
2714 zoff99 30 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2715     // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2716     // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2717     draw_lines_count_2 = 0;
2718     draw_lines_count_3 = 0;
2719     draw_lines_count_4 = 0;
2720     // dbg(0,"MT:7.3.3 - bridges start\n");
2721     */
2722 zoff99 28
2723     run_type = 3;
2724     itms = lay->itemgras;
2725     while (itms)
2726     {
2727     // stop drawing is requested
2728     if (cancel_drawing_global == 1)
2729     {
2730 zoff99 30 //DBG // dbg(0, "** STOP MD 002 **\n");
2731 zoff99 28 break;
2732     }
2733    
2734     itm = itms->data;
2735     //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2736     if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2737     {
2738     xdisplay_draw_elements(gra, display_list, itm, run_type);
2739     }
2740     itms = g_list_next(itms);
2741     }
2742    
2743     /*
2744 zoff99 30 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2745     // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2746     // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2747     draw_lines_count_2 = 0;
2748     draw_lines_count_3 = 0;
2749     draw_lines_count_4 = 0;
2750     // dbg(0,"MT:7.3.4 - ready\n");
2751     */
2752 zoff99 28
2753 zoff99 27 }
2754 zoff99 28 else
2755 zoff99 27 {
2756 zoff99 28 run_type = 99;
2757     itms = lay->itemgras;
2758     while (itms)
2759     {
2760     // stop drawing is requested
2761     if (cancel_drawing_global == 1)
2762     {
2763 zoff99 30 //DBG // dbg(0, "** STOP MD 002 **\n");
2764 zoff99 28 break;
2765     }
2766    
2767     itm = itms->data;
2768     //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2769     if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2770     {
2771     xdisplay_draw_elements(gra, display_list, itm, run_type);
2772     }
2773     itms = g_list_next(itms);
2774     }
2775 zoff99 27 }
2776 zoff99 28
2777     //if (strncmp("streets__tunnel", lay->name, 15) == 0)
2778     //{
2779     //}
2780     //else if (strncmp("streets__bridge", lay->name, 15) == 0)
2781     //{
2782     //}
2783    
2784 zoff99 27 // dirty hack to draw "waypoint(s)" ---------------------------
2785 zoff99 28 if (strncmp("Internal", lay->name, 8) == 0)
2786 zoff99 27 {
2787     if (global_navit->route)
2788     {
2789     if (global_navit->destination_valid == 1)
2790 zoff99 2 {
2791 zoff99 27 int count_ = 0;
2792     int curr_ = 0;
2793     count_ = g_list_length(global_navit->route->destinations);
2794     if (count_ > 1)
2795     {
2796     if (!global_img_waypoint)
2797     {
2798     char *path2;
2799     path2 = graphics_icon_path("nav_waypoint_bk_center.png");
2800     global_img_waypoint = graphics_image_new_scaled_rotated(gra, path2, 59, 59, 0);
2801     g_free(path2);
2802     }
2803    
2804     struct point p2;
2805     struct coord pc77;
2806     GList *ldest = global_navit->route->destinations;
2807     while (ldest)
2808     {
2809     curr_++;
2810     if (curr_ < count_)
2811     {
2812     struct route_info *dst = ldest->data;
2813     pc77.x = dst->c.x;
2814     pc77.y = dst->c.y;
2815 zoff99 30 //// dbg(0, "draw1 curr=%d x y: %d %d\n", curr_, dst->c.x, dst->c.y);
2816 zoff99 27 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2817     transform(global_navit->trans, pro, &pc77, &p2, 1, 0, 0, NULL);
2818     // transform(global_navit->trans, projection_mg, &pc77, &p2, 1, 0, 0, NULL);
2819     p2.x = p2.x - global_img_waypoint->hot.x; // hot = 29
2820     p2.y = p2.y - global_img_waypoint->hot.y; // hot = 29
2821     gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p2, global_img_waypoint->priv);
2822     }
2823     // next dest. / waypoint
2824 zoff99 30 ldest = g_list_next(ldest);
2825 zoff99 27 }
2826     }
2827 zoff99 2 }
2828 zoff99 27 }
2829 zoff99 2 }
2830 zoff99 27 // dirty hack to draw "waypoint(s)" ---------------------------
2831 zoff99 29
2832    
2833     if (send_refresh == 1)
2834     {
2835     // dummy "ready" signal ------------------------------------------
2836 zoff99 30 // dbg(0, "dummy \"ready\" signal (layers)\n");
2837     gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 96, 0, NULL);
2838 zoff99 29 // dummy "ready" signal ------------------------------------------
2839     }
2840    
2841 zoff99 2 }
2842    
2843     /**
2844     * FIXME
2845     * @param <>
2846     * @returns <>
2847     * @author Martin Schaller (04/2008)
2848 zoff99 27 */
2849 zoff99 2 static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
2850     {
2851 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
2852 zoff99 2
2853     GList *lays;
2854     struct layer *lay;
2855    
2856 zoff99 27 int draw_vector_map = 1;
2857    
2858 zoff99 2 // if zoomed out too much then use prerendered map tiles
2859 zoff99 27 if (display_list->order < ORDER_USE_PRERENDERED_MAP)
2860 zoff99 2 {
2861 zoff99 27 draw_vector_map = 0;
2862 zoff99 2 }
2863    
2864     if (!draw_vector_map)
2865     {
2866     // draw prerendered big mapimage --- HERE ---
2867     struct transformation *t;
2868 zoff99 27 t = display_list->dc.trans;
2869 zoff99 2 struct coord *cp;
2870 zoff99 27 cp = transform_get_center(t);
2871 zoff99 2 struct attr attr;
2872 zoff99 27 struct config
2873     {
2874     struct attr **attrs;
2875     struct callback_list *cbl;
2876     }*config;
2877 zoff99 2 struct point p;
2878 zoff99 27 int valid = 0;
2879 zoff99 2 if (global_navit)
2880     {
2881 zoff99 27 if ((global_navit->vehicle) && (global_navit->vehicle->vehicle))
2882 zoff99 2 {
2883 zoff99 28 //int a, s;
2884     //struct point pnt2;
2885     //vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
2886 zoff99 2
2887 zoff99 28 //struct attr pos_attr;
2888     //if (vehicle_get_attr(global_navit->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL))
2889     //{
2890 zoff99 30 // ////DBG // dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
2891 zoff99 28 //}
2892 zoff99 2
2893 zoff99 27 valid = 1;
2894 zoff99 2 }
2895     }
2896    
2897     struct coord *c;
2898 zoff99 27 c = &(t->map_center);
2899 zoff99 2
2900 zoff99 27 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2901 zoff99 2 struct coord_geo g22;
2902     struct coord *c22;
2903     struct point mcenter_pnt;
2904 zoff99 27 c22 = &(t->map_center);
2905 zoff99 2 transform_to_geo(projection_mg, c22, &g22);
2906     transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
2907    
2908     struct coord c99;
2909     struct coord_geo g99;
2910     struct point cursor_pnt;
2911     struct point p99;
2912 zoff99 28 long my_scale;
2913 zoff99 2
2914 zoff99 28 my_scale = transform_get_scale(global_navit->trans);
2915 zoff99 2
2916 zoff99 27 g99.lat = 0.0;
2917     g99.lng = 0.0;
2918 zoff99 28 // g99.lat = 80.0;
2919     // g99.lng = -174.0;
2920 zoff99 2 transform_from_geo(pro, &g99, &c99);
2921     transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2922    
2923     // now really draw it
2924 zoff99 27 struct graphics *gra22 = display_list->dc.gra;
2925     struct graphics_gc *gc22 = display_list->dc.gc;
2926     if (!gc22)
2927 zoff99 2 {
2928 zoff99 27 gc22 = graphics_gc_new(gra22);
2929 zoff99 2 }
2930 zoff99 28 // 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);
2931 zoff99 30 graphics_draw_bigmap(gra22, gc22, -t->yaw, (int) (my_scale / 100), 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);
2932 zoff99 2 }
2933    
2934 zoff99 28 // reset value; --> not sure here, maybe it should NOT be reset here!!!???
2935 zoff99 30 // cancel_drawing_global = 0;
2936 zoff99 2
2937 zoff99 27 lays = l->layers;
2938     while (lays)
2939     {
2940 zoff99 30 // stop drawing is requested
2941     if (cancel_drawing_global == 1)
2942     {
2943     break;
2944     }
2945    
2946 zoff99 27 lay = lays->data;
2947 zoff99 2 if (lay->active)
2948 zoff99 27 {
2949 zoff99 2 xdisplay_draw_layer(display_list, gra, lay, order);
2950 zoff99 27 }
2951     lays = g_list_next(lays);
2952 zoff99 2 }
2953    
2954 zoff99 27 // reset value;
2955 zoff99 30 // cancel_drawing_global = 0;
2956 zoff99 27
2957 zoff99 29 // dummy "start" signal ------------------------------------------
2958 zoff99 30 // // dbg(0, "dummy \"start\" signal\n");
2959     // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 97);
2960 zoff99 29 // dummy "start" signal ------------------------------------------
2961    
2962 zoff99 2 }
2963    
2964     /**
2965     * FIXME
2966     * @param <>
2967     * @returns <>
2968     * @author Martin Schaller (04/2008)
2969 zoff99 27 */
2970 zoff99 2 extern void *route_selection;
2971    
2972 zoff99 27 static void displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
2973 zoff99 2 {
2974 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
2975 zoff99 2
2976 zoff99 28 int order_corrected = order + shift_order;
2977 zoff99 2 //int saved=displaylist->order;
2978 zoff99 27 if (order < limit_order_corrected)
2979 zoff99 2 {
2980 zoff99 27 order_corrected = limit_order_corrected;
2981 zoff99 2 // displaylist->order=0;
2982     }
2983 zoff99 27
2984     while (layers)
2985     {
2986     struct layer *layer = layers->data;
2987     GList *itemgras = layer->itemgras;
2988     while (itemgras)
2989     {
2990     struct itemgra *itemgra = itemgras->data;
2991     GList *types = itemgra->type;
2992 zoff99 2 if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
2993     {
2994 zoff99 27 while (types)
2995     {
2996     enum item_type type = (enum item_type) types->data;
2997 zoff99 2 set_hash_entry(displaylist, type);
2998 zoff99 27 types = g_list_next(types);
2999 zoff99 2 }
3000     }
3001 zoff99 27 itemgras = g_list_next(itemgras);
3002 zoff99 2 }
3003 zoff99 27 layers = g_list_next(layers);
3004 zoff99 2 }
3005     // displaylist->order=saved;
3006     }
3007    
3008 zoff99 27 static void displaylist_update_hash(struct displaylist *displaylist)
3009 zoff99 2 {
3010 zoff99 30 ////DBG // dbg(0,"ooo enter ooo\n");
3011 zoff99 2
3012 zoff99 27 displaylist->max_offset = 0;
3013 zoff99 2 clear_hash(displaylist);
3014     displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
3015 zoff99 27 // dbg(1, "max offset %d\n", displaylist->max_offset);
3016 zoff99 2 }
3017    
3018 zoff99 27 static void do_draw(struct displaylist *displaylist, int cancel, int flags)
3019 zoff99 2 {
3020 zoff99 28
3021     #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3022 zoff99 30 // dbg(0,"+#+:enter\n");
3023 zoff99 28 #endif
3024    
3025 zoff99 30 int rnd = rand();
3026 zoff99 28
3027 zoff99 30 // dbg(0, "DO__DRAW:%d enter\n", rnd);
3028    
3029     // try to cancel any previous drawing that might be going on ...
3030     // try to cancel any previous drawing that might be going on ...
3031     // try to cancel any previous drawing that might be going on ...
3032     // dbg(0, "DO__DRAW:%d cancel_drawing_global 1=%d\n", rnd, cancel_drawing_global);
3033     cancel_drawing_global = 1;
3034     // dbg(0, "DO__DRAW:%d cancel_drawing_global 2=%d\n", rnd, cancel_drawing_global);
3035     // try to cancel any previous drawing that might be going on ...
3036     // try to cancel any previous drawing that might be going on ...
3037     // try to cancel any previous drawing that might be going on ...
3038    
3039    
3040     // dbg(0, "DO__DRAW:%d lock mutex\n", rnd);
3041     pthread_mutex_lock(&uiConditionMutex);
3042     // dbg(0, "DO__DRAW:%d OK lock mutex\n", rnd);
3043    
3044     // drawing is now starting ...
3045     // drawing is now starting ...
3046     // drawing is now starting ...
3047     // dbg(0, "DO__DRAW:%d cancel_drawing_global 3=%d\n", rnd, cancel_drawing_global);
3048     cancel_drawing_global = 0;
3049     // dbg(0, "DO__DRAW:%d cancel_drawing_global 4=%d\n", rnd, cancel_drawing_global);
3050     // drawing is now starting ...
3051     // drawing is now starting ...
3052     // drawing is now starting ...
3053    
3054    
3055 zoff99 28 #ifdef HAVE_API_ANDROID
3056     // ---- disable map view -----
3057     // ---- disable map view -----
3058     // ---- disable map view -----
3059     if (disable_map_drawing == 1)
3060     {
3061 zoff99 30 //android_return_generic_int(2, 0);
3062 zoff99 28
3063 zoff99 30 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3064 zoff99 28 displaylist->busy = 0;
3065    
3066 zoff99 30 // dbg(0,"DO__DRAW:%d UN-lock mutex 001\n", rnd);
3067     pthread_mutex_unlock(&uiConditionMutex);
3068     // dbg(0,"DO__DRAW:%d OK UN-lock mutex 001\n", rnd);
3069    
3070     // dbg(0,"DO__DRAW:%d return 001\n", rnd);
3071 zoff99 28 return;
3072     }
3073     // ---- disable map view -----
3074     // ---- disable map view -----
3075     // ---- disable map view -----
3076     #endif
3077    
3078     clock_t s_;
3079     #ifdef NAVIT_MEASURE_TIME_DEBUG
3080     s_ = debug_measure_start();
3081     #endif
3082    
3083 zoff99 2 struct item *item;
3084 zoff99 27 int count, max = displaylist->dc.maxlen, workload = 0;
3085     struct coord *ca = g_alloca(sizeof(struct coord) * max);
3086     struct attr attr, attr2;
3087 zoff99 2 enum projection pro;
3088 zoff99 27 int draw_vector_map = 1; // do we draw the vecotor map, or not? 0=false, 1=true
3089     int mapset_counter = 0;
3090     int mapset_need_draw = 0;
3091 zoff99 2
3092 zoff99 30 // // dbg(0,"ooo enter ooo %d\n",displaylist->order);
3093 zoff99 2
3094 zoff99 28 int order_corrected = displaylist->order + shift_order;
3095 zoff99 27 int saved = displaylist->order;
3096     if (order_corrected < limit_order_corrected)
3097 zoff99 2 {
3098 zoff99 27 order_corrected = limit_order_corrected;
3099 zoff99 2 }
3100    
3101     if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
3102     {
3103     displaylist_update_hash(displaylist);
3104 zoff99 27 displaylist->order_hashed = displaylist->order;
3105     displaylist->layout_hashed = displaylist->layout;
3106 zoff99 2 }
3107    
3108 zoff99 27 pro = transform_get_projection(displaylist->dc.trans);
3109 zoff99 2
3110     // if zoomed out too much then use prerendered map tiles
3111 zoff99 27 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP)
3112 zoff99 2 {
3113 zoff99 27 draw_vector_map = 0;
3114 zoff99 2 }
3115    
3116 zoff99 27 displaylist->order = order_corrected;
3117 zoff99 2
3118 zoff99 30 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 003\n");
3119 zoff99 27
3120     // reset value;
3121 zoff99 30 // cancel_drawing_global = 0;
3122 zoff99 27
3123 zoff99 2 while (!cancel)
3124     {
3125     if (!displaylist->msh)
3126 zoff99 27 {
3127     displaylist->msh = mapset_open(displaylist->ms);
3128     }
3129    
3130     if (!displaylist->m)
3131     {
3132     displaylist->m = mapset_next(displaylist->msh, 1);
3133     if (!displaylist->m)
3134     {
3135 zoff99 2 mapset_close(displaylist->msh);
3136 zoff99 27 displaylist->msh = NULL;
3137 zoff99 2 break;
3138     }
3139    
3140     mapset_counter++;
3141 zoff99 27 mapset_need_draw = 1;
3142 zoff99 2 struct attr map_name_attr;
3143 zoff99 27
3144     if (map_get_attr(displaylist->m, attr_name, &map_name_attr, NULL))
3145 zoff99 2 {
3146 zoff99 30 //// dbg(0,"#+* start reading map file #+*=%s\n",map_name_attr.u.str);
3147 zoff99 2 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
3148     {
3149     if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
3150     {
3151     // if its the countryborder map, always draw it
3152 zoff99 28 mapset_need_draw = 0; // now dont even draw border map!!
3153 zoff99 2 }
3154     else
3155     {
3156     // if its an sdcard street map, don't draw it
3157 zoff99 27 mapset_need_draw = 0;
3158 zoff99 2 }
3159     }
3160     }
3161    
3162 zoff99 30 ////DBG // dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
3163 zoff99 2
3164 zoff99 27 displaylist->dc.pro = map_projection(displaylist->m);
3165     displaylist->conv = map_requires_conversion(displaylist->m);
3166 zoff99 2 if (route_selection)
3167     {
3168 zoff99 27 displaylist->sel = route_selection;
3169 zoff99 2 }
3170     else
3171     {
3172 zoff99 27 displaylist->sel = transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
3173 zoff99 2 }
3174 zoff99 27 displaylist->mr = map_rect_new(displaylist->m, displaylist->sel);
3175 zoff99 2 }
3176 zoff99 27
3177 zoff99 2 if (displaylist->mr)
3178     {
3179     // draw vector map, or not?
3180 zoff99 30 //// dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
3181 zoff99 2 if ((draw_vector_map) || (mapset_need_draw == 1))
3182     {
3183 zoff99 27
3184 zoff99 30 //// dbg(0, "XXXXXYYYYYYY Draw: A.01\n");
3185 zoff99 27
3186 zoff99 28
3187     // ------ READ all items in this map rectangle ---------
3188     // ------ READ all items in this map rectangle ---------
3189     // ------ READ all items in this map rectangle ---------
3190     // ------ READ all items in this map rectangle ---------
3191     // ------ READ all items in this map rectangle ---------
3192 zoff99 30 //// dbg(0,"#+* start reading map file #+*\n");
3193 zoff99 28 int _item_counter_ = 0;
3194 zoff99 27 while ((item = map_rect_get_item(displaylist->mr)))
3195 zoff99 2 {
3196 zoff99 28 _item_counter_++;
3197    
3198 zoff99 27 int label_count = 0;
3199 zoff99 2 char *labels[2];
3200     struct hash_entry *entry;
3201    
3202 zoff99 27 if (cancel_drawing_global == 1)
3203     {
3204     // stop drawing map is requested
3205 zoff99 30 //DBG // dbg(0, "** STOP MD 001 **\n");
3206 zoff99 27 break;
3207     }
3208    
3209 zoff99 2 if (item == &busy_item)
3210     {
3211     if (displaylist->workload)
3212     {
3213     // restore order :-)
3214 zoff99 27 displaylist->order = saved;
3215 zoff99 28
3216 zoff99 30 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3217 zoff99 28 displaylist->busy = 0;
3218    
3219 zoff99 30 // dbg(0, "DO__DRAW:%d UN-lock mutex 002\n", rnd);
3220     pthread_mutex_unlock(&uiConditionMutex);
3221     // dbg(0, "DO__DRAW:%d OK UN-lock mutex 002\n", rnd);
3222    
3223     //// dbg(0,"return 002\n");
3224     // dbg(0, "DO__DRAW:%d return 002\n", rnd);
3225 zoff99 2 return;
3226     }
3227     else
3228 zoff99 27 {
3229 zoff99 2 continue;
3230 zoff99 27 }
3231 zoff99 2 }
3232    
3233 zoff99 27 entry = get_hash_entry(displaylist, item->type);
3234 zoff99 2
3235 zoff99 30 //// dbg(0, "XXXXXYYYYYYY Draw: A.item1 %p %i\n", entry, item->type);
3236 zoff99 27
3237     // DEBUG -------- zoffzoff
3238     // DEBUG -------- zoffzoff
3239     // DEBUG -------- zoffzoff
3240     //item_dump_attr_stdout(item, displaylist->m);
3241     // DEBUG -------- zoffzoff
3242     // DEBUG -------- zoffzoff
3243     // DEBUG -------- zoffzoff
3244    
3245 zoff99 2 if (!entry)
3246 zoff99 27 {
3247 zoff99 2 continue;
3248 zoff99 27 }
3249 zoff99 2
3250 zoff99 27 count = item_coord_get_within_selection(item, ca, item->type < type_line ? 1 : max, displaylist->sel);
3251 zoff99 2
3252 zoff99 27 if (!count)
3253     {
3254 zoff99 2 continue;
3255 zoff99 27 }
3256 zoff99 2
3257 zoff99 30 //// dbg(0, "XXXXXYYYYYYY Draw: A.item2\n");
3258 zoff99 27
3259 zoff99 2 if (displaylist->dc.pro != pro)
3260 zoff99 28 {
3261 zoff99 2 transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
3262 zoff99 28 }
3263 zoff99 2
3264     if (count == max)
3265     {
3266 zoff99 30 //DBG // dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
3267 zoff99 27 displaylist->dc.maxlen = max * 2;
3268 zoff99 2 }
3269    
3270     if (item_is_custom_poi(*item))
3271     {
3272     if (item_attr_get(item, attr_icon_src, &attr2))
3273 zoff99 27 labels[1] = map_convert_string(displaylist->m, attr2.u.str);
3274 zoff99 2 else
3275 zoff99 27 labels[1] = NULL;
3276     label_count = 2;
3277 zoff99 2 }
3278     else
3279     {
3280 zoff99 27 labels[1] = NULL;
3281     label_count = 0;
3282 zoff99 2 }
3283    
3284     if (item_attr_get(item, attr_label, &attr))
3285     {
3286 zoff99 27 labels[0] = attr.u.str;
3287 zoff99 2 if (!label_count)
3288 zoff99 27 {
3289     label_count = 2;
3290     }
3291 zoff99 2 }
3292     else
3293     {
3294 zoff99 27 labels[0] = NULL;
3295 zoff99 2 }
3296    
3297 zoff99 27 // DEBUG -------- zoffzoff
3298     // DEBUG -------- zoffzoff
3299     // DEBUG -------- zoffzoff
3300     // item_dump_attr_stdout(item, displaylist->m);
3301     // DEBUG -------- zoffzoff
3302     // DEBUG -------- zoffzoff
3303     // DEBUG -------- zoffzoff
3304 zoff99 2
3305     struct attr attr_77;
3306     if (item_attr_get(item, attr_flags, &attr_77))
3307     {
3308 zoff99 30 // // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
3309 zoff99 27 item->flags = attr_77.u.num;
3310 zoff99 2 }
3311     else
3312     {
3313 zoff99 27 item->flags = 0;
3314 zoff99 2 }
3315    
3316     //struct attr *attr88;
3317     //if (item_attr_get(item, attr_flags, &attr88))
3318     //{
3319 zoff99 30 ////DBG // dbg(0,"item flags=%d\n",attr88->u.num);
3320 zoff99 2 //}
3321     //attr88=NULL;
3322    
3323 zoff99 27
3324     /*
3325 zoff99 30 if (item->flags & AF_UNDERGROUND)
3326     {
3327     // dbg(0,"is UNDERGROUND\n");
3328     }
3329     else if (item->flags & AF_BRIDGE)
3330     {
3331     // dbg(0,"is BRIDGE\n");
3332     }
3333     */
3334 zoff99 27
3335 zoff99 2 if (displaylist->conv && label_count)
3336     {
3337 zoff99 27 labels[0] = map_convert_string(displaylist->m, labels[0]);
3338 zoff99 2 display_add(entry, item, count, ca, labels, label_count);
3339     map_convert_free(labels[0]);
3340     }
3341     else
3342     {
3343     display_add(entry, item, count, ca, labels, label_count);
3344     }
3345    
3346     if (labels[1])
3347     {
3348     map_convert_free(labels[1]);
3349     }
3350    
3351 zoff99 28 //workload++;
3352     /*
3353 zoff99 30 if (workload == displaylist->workload)
3354     {
3355     // restore order :-)
3356     displaylist->order = saved;
3357     // reset value;
3358     cancel_drawing_global = 0;
3359 zoff99 28
3360 zoff99 30 // dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3361     displaylist->busy = 0;
3362 zoff99 28
3363 zoff99 30 // dbg(0,"return 003\n");
3364     return;
3365     }
3366     */
3367 zoff99 27 } // while item=map_rect_get_item
3368 zoff99 28 // ------ READ all items in this map rectangle ---------
3369     // ------ READ all items in this map rectangle ---------
3370     // ------ READ all items in this map rectangle ---------
3371     // ------ READ all items in this map rectangle ---------
3372     // ------ READ all items in this map rectangle ---------
3373 zoff99 27
3374 zoff99 28
3375 zoff99 30 ////DBG // dbg(0, "XXXXXYYYYYYY Draw: A.02\n");
3376 zoff99 27
3377 zoff99 2 map_rect_destroy(displaylist->mr);
3378     }
3379     }
3380    
3381     if (!route_selection)
3382     {
3383     map_selection_destroy(displaylist->sel);
3384     }
3385    
3386 zoff99 27 displaylist->mr = NULL;
3387     displaylist->sel = NULL;
3388     displaylist->m = NULL;
3389 zoff99 2 } // while ----
3390    
3391 zoff99 28
3392 zoff99 30 // dbg(0, "DO__DRAW:%d load ready\n", rnd);
3393 zoff99 28
3394     #ifdef NAVIT_MEASURE_TIME_DEBUG
3395     debug_mrp("do_draw:load", debug_measure_end(s_));
3396     #endif
3397     s_ = debug_measure_start();
3398    
3399 zoff99 29 // remove the "wait" screen
3400 zoff99 30 //#ifdef HAVE_API_ANDROID
3401     // android_return_generic_int(2, 0);
3402     //#endif
3403 zoff99 29
3404 zoff99 30 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 004\n");
3405 zoff99 29
3406 zoff99 27 // reset value;
3407 zoff99 30 // cancel_drawing_global = 0;
3408 zoff99 27
3409 zoff99 2 // restore order :-)
3410 zoff99 27 displaylist->order = saved;
3411 zoff99 2
3412 zoff99 27 // profile(1,"process_selection\n");
3413    
3414 zoff99 30
3415 zoff99 2 if (displaylist->idle_ev)
3416 zoff99 27 {
3417 zoff99 2 event_remove_idle(displaylist->idle_ev);
3418 zoff99 30 displaylist->idle_ev = NULL;
3419 zoff99 27 }
3420 zoff99 29
3421 zoff99 30 if (displaylist->idle_cb)
3422     {
3423     callback_destroy(displaylist->idle_cb);
3424     displaylist->idle_cb = NULL;
3425     }
3426    
3427     //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3428 zoff99 28 //displaylist->busy = 0;
3429 zoff99 2
3430     // graphics_process_selection(displaylist->dc.gra, displaylist);
3431    
3432 zoff99 27 //profile(1, "draw\n");
3433    
3434 zoff99 30 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 005\n");
3435 zoff99 27
3436     if (!cancel)
3437 zoff99 2 {
3438     int flags2 = flags;
3439     if (!(flags2 & 2))
3440     {
3441     if (!draw_vector_map)
3442     {
3443     // dont clean bg of screen when drawing prerendered tiles
3444     flags2 = flags2 + 2;
3445     }
3446     }
3447 zoff99 30 //DBG // dbg(0,"call graphics_displaylist_draw 3")
3448     //// dbg(0,"# MT:002 #\n");
3449    
3450     // stop drawing is requested
3451     if (cancel_drawing_global != 1)
3452     {
3453     graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
3454     }
3455     //// dbg(0,"# MT:003 #\n");
3456 zoff99 2 }
3457    
3458 zoff99 28 #ifdef NAVIT_MEASURE_TIME_DEBUG
3459     debug_mrp("do_draw:draw", debug_measure_end(s_));
3460     #endif
3461    
3462 zoff99 30 // dbg(0, "DO__DRAW:%d draw ready\n", rnd);
3463    
3464 zoff99 28 #ifdef HAVE_API_ANDROID
3465     if (cur_mapdraw_time_index < 11)
3466     {
3467     mapdraw_time[cur_mapdraw_time_index] = debug_measure_end_tsecs(s_);
3468 zoff99 30 // // dbg(0,"maptime: %d\n", mapdraw_time[cur_mapdraw_time_index]);
3469 zoff99 28 cur_mapdraw_time_index++;
3470     }
3471    
3472     if (cur_mapdraw_time_index > 10)
3473     {
3474     cur_mapdraw_time_index = 0;
3475     int jk;
3476     int mean_time = 0;
3477     for (jk=0;jk<11;jk++)
3478     {
3479     mean_time = mean_time + mapdraw_time[jk];
3480     }
3481     android_return_generic_int(6, (int)((float)mean_time / (float)10));
3482     }
3483     #endif
3484    
3485 zoff99 30 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3486 zoff99 28 displaylist->busy = 0;
3487    
3488 zoff99 30 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 006\n");
3489 zoff99 27
3490 zoff99 2 map_rect_destroy(displaylist->mr);
3491     if (!route_selection)
3492 zoff99 28 {
3493 zoff99 2 map_selection_destroy(displaylist->sel);
3494 zoff99 28 }
3495 zoff99 2 mapset_close(displaylist->msh);
3496 zoff99 27 displaylist->mr = NULL;
3497     displaylist->sel = NULL;
3498     displaylist->m = NULL;
3499     displaylist->msh = NULL;
3500 zoff99 28
3501 zoff99 30 //dbg(0, "callback\n");
3502 zoff99 28
3503 zoff99 30 // only some old crap need this!! ----------
3504     // only some old crap need this!! ----------
3505     /// **** callback_call_1(displaylist->cb, cancel);
3506     // only some old crap need this!! ----------
3507     // only some old crap need this!! ----------
3508    
3509    
3510     // dbg(0, "DO__DRAW:%d UN-lock mutex leave\n", rnd);
3511     pthread_mutex_unlock(&uiConditionMutex);
3512     // dbg(0, "DO__DRAW:%d OK UN-lock mutex leave\n", rnd);
3513    
3514     // dbg(0, "DO__DRAW:%d cancel_drawing_global 99=%d\n", rnd, cancel_drawing_global);
3515    
3516     if (cancel_drawing_global != 1)
3517     {
3518     // dummy "ready" signal ------------------------------------------
3519     // dbg(0, "DO__DRAW:%d dummy \"ready\" signal\n", rnd);
3520     // gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 99);
3521     #ifdef HAVE_API_ANDROID
3522     android_return_generic_int(2, 2);
3523     #endif
3524     // dummy "ready" signal ------------------------------------------
3525     }
3526     else
3527     {
3528     // dummy "cancel" signal ------------------------------------------
3529     // dbg(0, "DO__DRAW:%d dummy \"cancel\" signal\n", rnd);
3530     //gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 95);
3531     #ifdef HAVE_API_ANDROID
3532     android_return_generic_int(2, 3);
3533     #endif
3534     // dummy "ready" signal ------------------------------------------
3535     }
3536    
3537     // dbg(0, "DO__DRAW:%d leave\n", rnd);
3538     // dbg(0, "DO__DRAW:%d __\n", rnd);
3539    
3540 zoff99 28 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3541 zoff99 30 // dbg(0,"+#+:leave\n");
3542 zoff99 28 #endif
3543    
3544 zoff99 2 }
3545    
3546     /**
3547     * FIXME
3548     * @param <>
3549     * @returns <>
3550     * @author Martin Schaller (04/2008)
3551 zoff99 27 */
3552 zoff99 2 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
3553     {
3554 zoff99 28 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3555 zoff99 30 // dbg(0,"+#+:enter\n");
3556 zoff99 28 #endif
3557 zoff99 2
3558 zoff99 30 // // dbg(0,"ooo enter ooo flags=%d\n", flags);
3559 zoff99 28
3560 zoff99 30
3561 zoff99 27 int order = transform_get_order(trans);
3562     displaylist->dc.trans = trans;
3563     displaylist->dc.gra = gra;
3564 zoff99 28
3565     // *********DISABLED*******
3566     // *********DISABLED*******
3567     // *********DISABLED*******
3568     // set min. distanct of 2 points on line at which a point will be left out when zoomed out too much!!
3569     // *********DISABLED******* displaylist->dc.mindist = transform_get_scale(trans) / 2;
3570 zoff99 30 //// dbg(0,"mindist would be:%d\n", (int)(transform_get_scale(trans) / 2));
3571 zoff99 28 displaylist->dc.mindist = 0;
3572     if (order < 13)
3573     {
3574     displaylist->dc.mindist = transform_get_scale(trans);
3575     }
3576     // *********DISABLED*******
3577     // *********DISABLED*******
3578     // *********DISABLED*******
3579    
3580    
3581 zoff99 2 // FIXME find a better place to set the background color
3582     if (l)
3583     {
3584     graphics_gc_set_background(gra->gc[0], &l->color);
3585     graphics_gc_set_foreground(gra->gc[0], &l->color);
3586     gra->default_font = g_strdup(l->font);
3587     }
3588     graphics_background_gc(gra, gra->gc[0]);
3589     if (flags & 1)
3590     {
3591 zoff99 28 // calls -> navit.c navit_predraw --> draw all vehicles
3592 zoff99 2 callback_list_call_attr_0(gra->cbl, attr_predraw);
3593     }
3594 zoff99 27 gra->meth.draw_mode(gra->priv, (flags & 8) ? draw_mode_begin_clear : draw_mode_begin);
3595 zoff99 2 if (!(flags & 2))
3596 zoff99 27 {
3597 zoff99 29 // clear the gfx object pipeline ------------------------------
3598 zoff99 30 // // dbg(0, "clear the gfx object pipeline\n");
3599     // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 98);
3600 zoff99 29
3601 zoff99 2 // clear the display/screen/whatever here
3602 zoff99 30 // dbg(0, "clear the screen: rectangle=%d,%d - %d,%d\n", gra->r.lu.x, gra->r.lu.y, gra->r.rl.x, gra->r.rl.y);
3603 zoff99 27 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);
3604     }
3605 zoff99 2 if (l)
3606     {
3607 zoff99 28 // draw the mapitems
3608 zoff99 30 // // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
3609 zoff99 27 xdisplay_draw(displaylist, gra, l, order + l->order_delta);
3610 zoff99 2 }
3611     if (flags & 1)
3612     {
3613     callback_list_call_attr_0(gra->cbl, attr_postdraw);
3614     }
3615     if (!(flags & 4))
3616 zoff99 27 {
3617 zoff99 2 gra->meth.draw_mode(gra->priv, draw_mode_end);
3618 zoff99 27 }
3619    
3620 zoff99 28 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3621 zoff99 30 // dbg(0,"+#+:leave\n");
3622 zoff99 28 #endif
3623    
3624 zoff99 2 }
3625    
3626     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)
3627     {
3628 zoff99 30 // dbg(0, "DO__DRAW:gl_ms enter\n");
3629    
3630 zoff99 27 int order = transform_get_order(trans);
3631 zoff99 2
3632 zoff99 30 //// dbg(0,"enter displaylist->busy=%d\n",displaylist->busy);
3633     //// dbg(0,"async=%d\n",async);
3634 zoff99 2 if (displaylist->busy)
3635     {
3636     if (async == 1)
3637     {
3638 zoff99 30 //// dbg(0,"**draw 1.a\n");
3639     // dbg(0, "DO__DRAW:gl_ms return 001\n");
3640 zoff99 2 return;
3641     }
3642 zoff99 30 ///// dbg(0,"**draw 1\n");
3643     // dbg(0, "DO__DRAW:gl_ms return 002\n");
3644 zoff99 28 return;
3645     //do_draw(displaylist, 1, flags);
3646 zoff99 2 }
3647     xdisplay_free(displaylist);
3648    
3649 zoff99 27 displaylist->dc.gra = gra;
3650     displaylist->ms = mapset;
3651     displaylist->dc.trans = trans;
3652     displaylist->workload = async ? 100 : 0;
3653     displaylist->cb = cb;
3654 zoff99 2 displaylist->seq++;
3655    
3656     if (l)
3657     {
3658 zoff99 27 order += l->order_delta;
3659 zoff99 2 }
3660 zoff99 27 displaylist->order = order;
3661 zoff99 30 //// dbg(0,"set:1:displaylist->busy=%d\n",displaylist->busy);
3662 zoff99 27 displaylist->busy = 1;
3663     displaylist->layout = l;
3664 zoff99 2
3665 zoff99 30 // ---------- DISABLED ------ no more async!!
3666     /*
3667     if (async)
3668     {
3669     //DBG // dbg(0,"§§async");
3670     if (!displaylist->idle_cb)
3671     {
3672     //DBG // dbg(0,"§§async --> callback");
3673     displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3674     }
3675     //DBG // dbg(0,"§§async --> add idle");
3676     displaylist->idle_ev = event_add_idle(50, displaylist->idle_cb);
3677     }
3678     else
3679     {
3680     //DBG // dbg(0,"@@sync");
3681     do_draw(displaylist, 0, flags);
3682     }
3683     */
3684 zoff99 28
3685 zoff99 2 if (async)
3686     {
3687 zoff99 27 if (!displaylist->idle_cb)
3688 zoff99 2 {
3689 zoff99 30 //dbg(0,"**draw 2.b1\n");
3690 zoff99 27 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3691 zoff99 30 callback_add_names(displaylist->idle_cb, "graphics_load_mapset", "do_draw");
3692     //// dbg(0,"**draw 2.b2\n");
3693 zoff99 2 }
3694 zoff99 28 //dbg(0,"**draw 2.b3\n");
3695 zoff99 30 //dbg(0, "DO__DRAW:call 003 (async callback)\n");
3696 zoff99 29 displaylist->idle_ev = event_add_idle(1000, displaylist->idle_cb);
3697 zoff99 30 // dbg(0, "**draw 2.b4 %p\n", displaylist->idle_ev);
3698 zoff99 28 }
3699     else
3700     {
3701 zoff99 30 //// dbg(0,"**draw 2.b5\n");
3702     // dbg(0, "DO__DRAW:call 001\n");
3703 zoff99 28 do_draw(displaylist, 0, flags);
3704     }
3705 zoff99 30
3706     // dbg(0, "DO__DRAW:gl_ms leave\n");
3707 zoff99 2 }
3708    
3709     /**
3710     * FIXME
3711     * @param <>
3712     * @returns <>
3713     * @author Martin Schaller (04/2008)
3714 zoff99 27 */
3715 zoff99 2 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)
3716     {
3717 zoff99 30 //// dbg(0,"ooo enter ooo\n");
3718 zoff99 2
3719 zoff99 30 // dbg(0, "DO__DRAW:gras_draw enter\n");
3720 zoff99 2 graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
3721 zoff99 30 // dbg(0, "DO__DRAW:gras_draw leave\n");
3722 zoff99 2 }
3723    
3724 zoff99 27 int graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
3725 zoff99 2 {
3726 zoff99 30 //DBG // dbg(0,"ooo enter ooo\n");
3727 zoff99 2
3728     if (!displaylist->busy)
3729 zoff99 30 {
3730 zoff99 2 return 0;
3731 zoff99 30 }
3732     // dbg(0, "DO__DRAW:call 002\n");
3733 zoff99 2 do_draw(displaylist, 1, 0);
3734     return 1;
3735     }
3736    
3737     /**
3738     * FIXME
3739     * @param <>
3740     * @returns <>
3741     * @author Martin Schaller (04/2008)
3742 zoff99 27 */
3743     struct displaylist_handle
3744     {
3745 zoff99 2 struct displaylist *dl;
3746     struct displayitem *di;
3747     int hashidx;
3748     };
3749    
3750     /**
3751     * FIXME
3752     * @param <>
3753     * @returns <>
3754     * @author Martin Schaller (04/2008)
3755 zoff99 27 */
3756 zoff99 2 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
3757     {
3758     struct displaylist_handle *ret;
3759    
3760     ret=g_new0(struct displaylist_handle, 1);
3761 zoff99 27 ret->dl = displaylist;
3762 zoff99 2
3763     return ret;
3764     }
3765    
3766     /**
3767     * FIXME
3768     * @param <>
3769     * @returns <>
3770     * @author Martin Schaller (04/2008)
3771 zoff99 27 */
3772 zoff99 2 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
3773     {
3774     struct displayitem *ret;
3775     if (!dlh)
3776     return NULL;
3777 zoff99 27 for (;;)
3778     {
3779     if (dlh->di)
3780     {
3781     ret = dlh->di;
3782     dlh->di = ret->next;
3783 zoff99 2 break;
3784     }
3785 zoff99 27 if (dlh->hashidx == HASH_SIZE_GRAPHICS_)
3786     {
3787     ret = NULL;
3788 zoff99 2 break;
3789     }
3790     if (dlh->dl->hash_entries[dlh->hashidx].type)
3791 zoff99 27 dlh->di = dlh->dl->hash_entries[dlh->hashidx].di;
3792 zoff99 2 dlh->hashidx++;
3793     }
3794     return ret;
3795     }
3796    
3797     /**
3798     * FIXME
3799     * @param <>
3800     * @returns <>
3801     * @author Martin Schaller (04/2008)
3802 zoff99 27 */
3803 zoff99 2 void graphics_displaylist_close(struct displaylist_handle *dlh)
3804     {
3805     g_free(dlh);
3806     }
3807    
3808     /**
3809     * FIXME
3810     * @param <>
3811     * @returns <>
3812     * @author Martin Schaller (04/2008)
3813 zoff99 27 */
3814 zoff99 2 struct displaylist * graphics_displaylist_new(void)
3815     {
3816     struct displaylist *ret=g_new0(struct displaylist, 1);
3817    
3818 zoff99 27 ret->dc.maxlen = 16384;
3819 zoff99 28 ret->busy = 0;
3820 zoff99 2
3821     return ret;
3822     }
3823    
3824     /**
3825     * FIXME
3826     * @param <>
3827     * @returns <>
3828     * @author Martin Schaller (04/2008)
3829 zoff99 27 */
3830 zoff99 2 struct item * graphics_displayitem_get_item(struct displayitem *di)
3831     {
3832     return &di->item;
3833     }
3834    
3835 zoff99 27 int graphics_displayitem_get_coord_count(struct displayitem *di)
3836 zoff99 2 {
3837     return di->count;
3838     }
3839    
3840     /**
3841     * FIXME
3842     * @param <>
3843     * @returns <>
3844     * @author Martin Schaller (04/2008)
3845 zoff99 27 */
3846 zoff99 2 char * graphics_displayitem_get_label(struct displayitem *di)
3847     {
3848     return di->label;
3849     }
3850    
3851 zoff99 27 int graphics_displayitem_get_displayed(struct displayitem *di)
3852 zoff99 2 {
3853     return 1;
3854     }
3855    
3856     /**
3857     * FIXME
3858     * @param <>
3859     * @returns <>
3860     * @author Martin Schaller (04/2008)
3861 zoff99 27 */
3862 zoff99 2 static int within_dist_point(struct point *p0, struct point *p1, int dist)
3863     {
3864     if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
3865     return 0;
3866     if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
3867     return 0;
3868 zoff99 27 if ((p0->x - p1->x) * (p0->x - p1->x) + (p0->y - p1->y) * (p0->y - p1->y) <= dist * dist)
3869     {
3870     return 1;
3871     }
3872     return 0;
3873 zoff99 2 }
3874    
3875     /**
3876     * FIXME
3877     * @param <>
3878     * @returns <>
3879     * @author Martin Schaller (04/2008)
3880 zoff99 27 */
3881 zoff99 2 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
3882     {
3883 zoff99 27 int vx, vy, wx, wy;
3884     int c1, c2;
3885 zoff99 2 struct point line_p;
3886    
3887 zoff99 27 if (line_p0->x < line_p1->x)
3888     {
3889 zoff99 2 if (p->x < line_p0->x - dist)
3890     return 0;
3891     if (p->x > line_p1->x + dist)
3892     return 0;
3893 zoff99 27 }
3894     else
3895     {
3896 zoff99 2 if (p->x < line_p1->x - dist)
3897     return 0;
3898     if (p->x > line_p0->x + dist)
3899     return 0;
3900     }
3901 zoff99 27 if (line_p0->y < line_p1->y)
3902     {
3903 zoff99 2 if (p->y < line_p0->y - dist)
3904     return 0;
3905     if (p->y > line_p1->y + dist)
3906     return 0;
3907 zoff99 27 }
3908     else
3909     {
3910 zoff99 2 if (p->y < line_p1->y - dist)
3911     return 0;
3912     if (p->y > line_p0->y + dist)
3913     return 0;
3914     }
3915    
3916 zoff99 27 vx = line_p1->x - line_p0->x;
3917     vy = line_p1->y - line_p0->y;
3918     wx = p->x - line_p0->x;
3919     wy = p->y - line_p0->y;
3920 zoff99 2
3921 zoff99 27 c1 = vx * wx + vy * wy;
3922     if (c1 <= 0)
3923 zoff99 2 return within_dist_point(p, line_p0, dist);
3924 zoff99 27 c2 = vx * vx + vy * vy;
3925     if (c2 <= c1)
3926 zoff99 2 return within_dist_point(p, line_p1, dist);
3927    
3928 zoff99 27 line_p.x = line_p0->x + vx * c1 / c2;
3929     line_p.y = line_p0->y + vy * c1 / c2;
3930 zoff99 2 return within_dist_point(p, &line_p, dist);
3931     }
3932    
3933     /**
3934     * FIXME
3935     * @param <>
3936     * @returns <>
3937     * @author Martin Schaller (04/2008)
3938 zoff99 27 */
3939 zoff99 2 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
3940     {
3941     int i;
3942 zoff99 27 for (i = 0; i < count - 1; i++)
3943     {
3944     if (within_dist_line(p, line_pnt + i, line_pnt + i + 1, dist))
3945     {
3946 zoff99 2 return 1;
3947     }
3948     }
3949     if (close)
3950 zoff99 27 return (within_dist_line(p, line_pnt, line_pnt + count - 1, dist));
3951 zoff99 2 return 0;
3952     }
3953    
3954     /**
3955     * FIXME
3956     * @param <>
3957     * @returns <>
3958     * @author Martin Schaller (04/2008)
3959 zoff99 27 */
3960 zoff99 2 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
3961     {
3962     int i, j, c = 0;
3963 zoff99 27 for (i = 0, j = count - 1; i < count; j = i++)
3964     {
3965     if ((((poly_pnt[i].y <= p->y) && (p->y < poly_pnt[j].y)) || ((poly_pnt[j].y <= p->y) && (p->y < poly_pnt[i].y))) && (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))
3966     c = !c;
3967     }
3968     if (!c)
3969 zoff99 2 return within_dist_polyline(p, poly_pnt, count, dist, 1);
3970 zoff99 27 return c;
3971 zoff99 2 }
3972    
3973     /**
3974     * FIXME
3975     * @param <>
3976     * @returns <>
3977     * @author Martin Schaller (04/2008)
3978 zoff99 27 */
3979 zoff99 2 int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
3980     {
3981 zoff99 27 struct point *pa = g_alloca(sizeof(struct point) * displaylist->dc.maxlen);
3982 zoff99 2 int count;
3983    
3984 zoff99 27 count = transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
3985 zoff99 2
3986 zoff99 27 if (di->item.type < type_line)
3987     {
3988 zoff99 2 return within_dist_point(p, &pa[0], dist);
3989     }
3990 zoff99 27 if (di->item.type < type_area)
3991     {
3992 zoff99 2 return within_dist_polyline(p, pa, count, dist, 0);
3993     }
3994     return within_dist_polygon(p, pa, count, dist);
3995     }
3996    
3997 zoff99 27 static void graphics_process_selection_item(struct displaylist *dl, struct item *item)
3998 zoff99 2 {
3999     #if 0 /* FIXME */
4000     struct displayitem di,*di_res;
4001     GHashTable *h;
4002     int count,max=dl->dc.maxlen;
4003     struct coord ca[max];
4004     struct attr attr;
4005     struct map_rect *mr;
4006    
4007     di.item=*item;
4008     di.label=NULL;
4009     di.count=0;
4010     h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
4011 zoff99 27 if (h)
4012     {
4013 zoff99 2 di_res=g_hash_table_lookup(h, &di);
4014 zoff99 27 if (di_res)
4015     {
4016 zoff99 2 di.item.type=(enum item_type)item->priv_data;
4017     display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
4018     return;
4019     }
4020     }
4021     mr=map_rect_new(item->map, NULL);
4022     item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
4023     count=item_coord_get(item, ca, item->type < type_line ? 1: max);
4024     if (!item_attr_get(item, attr_label, &attr))
4025 zoff99 27 attr.u.str=NULL;
4026     if (dl->conv && attr.u.str && attr.u.str[0])
4027     {
4028 zoff99 2 char *str=map_convert_string(item->map, attr.u.str);
4029     display_add(dl, item, count, ca, &str, 1);
4030     map_convert_free(str);
4031 zoff99 27 }
4032     else
4033     display_add(dl, item, count, ca, &attr.u.str, 1);
4034 zoff99 2 map_rect_destroy(mr);
4035     #endif
4036     }
4037    
4038 zoff99 27 void graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
4039 zoff99 2 {
4040     struct item *item_dup=g_new(struct item, 1);
4041 zoff99 27 *item_dup = *item;
4042     item_dup->priv_data = (void *) type;
4043     gra->selection = g_list_append(gra->selection, item_dup);
4044 zoff99 2 if (dl)
4045     graphics_process_selection_item(dl, item_dup);
4046     }
4047    
4048 zoff99 27 void graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
4049 zoff99 2 {
4050     GList *curr;
4051     int found;
4052    
4053 zoff99 27 for (;;)
4054     {
4055     curr = gra->selection;
4056     found = 0;
4057     while (curr)
4058     {
4059     struct item *sitem = curr->data;
4060     if (item_is_equal(*item, *sitem))
4061     {
4062     if (dl)
4063     {
4064 zoff99 2 struct displayitem di;
4065     /* Unused Variable
4066 zoff99 27 GHashTable *h; */
4067     di.item = *sitem;
4068     di.label = NULL;
4069     di.count = 0;
4070     di.item.type = type;
4071 zoff99 2 #if 0 /* FIXME */
4072     h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
4073     if (h)
4074 zoff99 27 g_hash_table_remove(h, &di);
4075 zoff99 2 #endif
4076     }
4077     g_free(sitem);
4078 zoff99 27 gra->selection = g_list_remove(gra->selection, curr->data);
4079     found = 1;
4080 zoff99 2 break;
4081     }
4082     }
4083     if (!found)
4084     return;
4085     }
4086     }
4087    
4088 zoff99 27 void graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
4089 zoff99 2 {
4090 zoff99 27 while (gra->selection)
4091     {
4092     struct item *item = (struct item *) gra->selection->data;
4093     graphics_remove_selection(gra, item, (enum item_type) item->priv_data, dl);
4094 zoff99 2 }
4095     }
4096    
4097 zoff99 27 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl)
4098 zoff99 2 {
4099     GList *curr;
4100    
4101 zoff99 27 curr = gra->selection;
4102     while (curr)
4103     {
4104     struct item *item = curr->data;
4105 zoff99 2 graphics_process_selection_item(dl, item);
4106 zoff99 27 curr = g_list_next(curr);
4107 zoff99 2 }
4108     }

   
Visit the ZANavi Wiki