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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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