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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 51 - (show annotations) (download)
Mon Jul 25 19:29:08 2016 UTC (7 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 147194 byte(s)
v2.0.52
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2014 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2008 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 //##############################################################################################################
40 //#
41 //# File: graphics.c
42 //# Description:
43 //# Comment:
44 //# Authors: Martin Schaller (04/2008)
45 //#
46 //##############################################################################################################
47
48 #include <stdlib.h>
49 #include <glib.h>
50 #include <stdio.h>
51 #include <math.h>
52 #include <zlib.h>
53 #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 #include "track.h"
76 #include "navit.h"
77 #include "route.h"
78
79 #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
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 //##############################################################################################################
120 //# Description:
121 //# Comment:
122 //# Authors: Martin Schaller (04/2008)
123 //##############################################################################################################
124
125 // 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 #define ORDER_USE_PRERENDERED_MAP__C 4
129 #define ORDER_USE_NORMAL_MAP__C 3
130 #define ORDER_USE_BORDERS_MAP 14
131
132 // minimum (line legth * 32) squared (in pixel) to show text label
133 #define MIN_LINE_LENGTH_FOR_TEXT_2 409600
134 // minimum (line legth * 32) squared (in pixel) to show text label -> for middle segments of streets
135 #define MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2 1638400
136
137 #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 #define ORDER_LEVEL_FOR_STREET_SIMPLIFY 9
145 #define STREET_SIMPLIFY 24
146
147 #define X_COLOR_BACKGROUND_NM 0x6666, 0x6666, 0x6666, 0xffff
148 struct color background_night_mode = { X_COLOR_BACKGROUND_NM };
149
150
151 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 int gamma, brightness, contrast;
163 int colormgmt;
164 int font_size;
165 GList *selection;
166 };
167
168 /*
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
183 #define HASH_SIZE 1024
184 */
185
186 /*
187 struct hash_entry
188 {
189 enum item_type type;
190 struct displayitem *di;
191 };
192 */
193
194 /*
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
215 struct displaylist_icon_cache
216 {
217 unsigned int seq;
218
219 };
220
221 /**
222 * FIXME
223 * @param <>
224 * @returns <>
225 * @author Martin Schaller (04/2008)
226 */
227 struct displayitem
228 {
229 struct displayitem *next;
230 struct item item;
231 char *label;
232 // struct color color;
233 unsigned int col_int_value;
234 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 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in);
242
243
244 // ------------- TILES -------------
245 // ------------- TILES -------------
246 // ------------- TILES -------------
247 #include "mvt_tiles.h"
248 // ------------- TILES -------------
249 // ------------- TILES -------------
250 // ------------- TILES -------------
251
252
253
254 static void clear_hash(struct displaylist *dl)
255 {
256 int i;
257 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
258 {
259 dl->hash_entries[i].type = type_none;
260 }
261 }
262
263 static struct hash_entry *
264 get_hash_entry(struct displaylist *dl, enum item_type type)
265 {
266 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
267 int offset = dl->max_offset;
268 do
269 {
270 if (!dl->hash_entries[hashidx].type)
271 {
272 return NULL;
273 }
274 if (dl->hash_entries[hashidx].type == type)
275 {
276 return &dl->hash_entries[hashidx];
277 }
278 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
279 }
280 while (offset-- > 0);
281
282 return NULL;
283 }
284
285 static struct hash_entry *
286 set_hash_entry(struct displaylist *dl, enum item_type type)
287 {
288 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 if (dl->max_offset < offset)
296 dl->max_offset = offset;
297 return &dl->hash_entries[hashidx];
298 }
299 if (dl->hash_entries[hashidx].type == type)
300 return &dl->hash_entries[hashidx];
301 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
302 offset++;
303 }
304 return NULL;
305 }
306
307 static int graphics_set_attr_do(struct graphics *gra, struct attr *attr)
308 {
309 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 }
326 gra->colormgmt = (gra->gamma != 65536 || gra->brightness != 0 || gra->contrast != 65536);
327 graphics_gc_init(gra);
328 return 1;
329 }
330
331 int graphics_set_attr(struct graphics *gra, struct attr *attr)
332 {
333 int ret = 1;
334 // //DBG // dbg(0,"enter\n");
335 if (gra->meth.set_attr)
336 ret = gra->meth.set_attr(gra->priv, attr);
337 if (!ret)
338 ret = graphics_set_attr_do(gra, attr);
339 return ret != 0;
340 }
341
342 void graphics_set_rect(struct graphics *gra, struct point_rect *pr)
343 {
344 gra->r = *pr;
345 }
346
347 /**
348 * Creates a new graphics object
349 * attr type required
350 * @param <>
351 * @returns <>
352 * @author Martin Schaller (04/2008)
353 */
354 struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
355 {
356 // dbg(0, "EEnter\n");
357
358 int count = 0;
359 struct graphics *this_;
360 struct attr *type_attr;
361 struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl);
362
363 if (!(type_attr = attr_search(attrs, NULL, attr_type)))
364 {
365 return NULL;
366 }
367
368 // dbg(0, "plugins\n");
369
370 #ifdef PLUGSSS
371 graphicstype_new = plugin_get_graphics_type(type_attr->u.str);
372 if (!graphicstype_new)
373 {
374 return NULL;
375 }
376 #endif
377
378 // dbg(0, "g 003\n");
379
380 this_=g_new0(struct graphics, 1);
381 this_->cbl = callback_list_new("graphics_new:this_->cbl");
382
383 #ifdef PLUGSSS
384 this_->priv = (*graphicstype_new)(parent->u.navit, &this_->meth, attrs, this_->cbl);
385 #else
386 this_->priv = graphics_android_new(parent->u.navit, &this_->meth, attrs, this_->cbl);
387 #endif
388
389 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 // dbg(0, "g 004\n");
396
397 while (*attrs)
398 {
399 count++;
400 // dbg(0, "g 005 attr %d\n", count);
401 graphics_set_attr_do(this_, *attrs);
402 attrs++;
403 // dbg(0, "g 006 attr\n");
404 }
405
406 // dbg(0, "return\n");
407 return this_;
408 }
409
410 /**
411 * FIXME
412 * @param <>
413 * @returns <>
414 * @author Martin Schaller (04/2008)
415 */
416 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 */
427 struct graphics * graphics_overlay_new(const char* name, struct graphics *parent, struct point *p, int w, int h, int alpha, int wraparound)
428 {
429 struct graphics *this_;
430 struct point_rect pr;
431 if (!parent->meth.overlay_new)
432 return NULL;this_=g_new0(struct graphics, 1);
433 this_->priv = parent->meth.overlay_new(name, parent->priv, &this_->meth, p, w, h, alpha, wraparound);
434 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 graphics_set_rect(this_, &pr);
440 if (!this_->priv)
441 {
442 g_free(this_);
443 this_ = NULL;
444 }
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 void graphics_overlay_resize(struct graphics *this_, struct point *p, int w, int h, int alpha, int wraparound)
459 {
460 if (!this_->meth.overlay_resize)
461 {
462 return;
463 }
464
465 this_->meth.overlay_resize(this_->priv, p, w, h, alpha, wraparound);
466 }
467
468 static void graphics_gc_init(struct graphics *this_)
469 {
470 // dbg(0, "EEnter\n");
471
472 struct color background = { COLOR_BACKGROUND_ };
473 struct color black = { COLOR_BLACK_ };
474 struct color white = { COLOR_WHITE_ };
475
476 if (!this_->gc[0] || !this_->gc[1] || !this_->gc[2])
477 {
478 return;
479 }
480
481 graphics_gc_set_background(this_->gc[0], &background);
482 graphics_gc_set_foreground(this_->gc[0], &background);
483
484 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
489 // dbg(0, "return\n");
490 }
491
492 /**
493 * FIXME
494 * @param <>
495 * @returns <>
496 * @author Martin Schaller (04/2008)
497 */
498 void graphics_init(struct graphics *this_)
499 {
500 if (this_->gc[0])
501 {
502 return;
503 }
504
505 this_->gc[0] = graphics_gc_new(this_);
506 this_->gc[1] = graphics_gc_new(this_);
507 this_->gc[2] = graphics_gc_new(this_);
508
509 graphics_gc_init(this_);
510
511 graphics_background_gc(this_, this_->gc[0]);
512 }
513
514 /**
515 * FIXME
516 * @param <>
517 * @returns <>
518 * @author Martin Schaller (04/2008)
519 */
520 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 */
541 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 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, gra->default_font, size, flags);
547 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 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, font, size, flags);
556 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 {
570 return;
571 }
572
573 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 for (i = 0; i < gra->font_len; i++)
590 {
591 if (!gra->font[i])
592 {
593 continue;
594 }
595
596 gra->font[i]->meth.font_destroy(gra->font[i]->priv);
597 gra->font[i] = NULL;
598 }
599 }
600
601 /**
602 * FIXME
603 * @param <>
604 * @returns <>
605 * @author Martin Schaller (04/2008)
606 */
607 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 this_->priv = gra->meth.gc_new(gra->priv, &this_->meth);
613 this_->gra = gra;
614 return this_;
615 }
616
617 /**
618 * FIXME
619 * @param <>
620 * @returns <>
621 * @author Martin Schaller (04/2008)
622 */
623 void graphics_gc_destroy(struct graphics_gc *gc)
624 {
625 gc->meth.gc_destroy(gc->priv);
626 g_free(gc);
627 }
628
629 static void graphics_convert_color(struct graphics *gra, struct color *in, struct color *out)
630 {
631 *out = *in;
632
633 if (gra->brightness)
634 {
635 out->r += gra->brightness;
636 out->g += gra->brightness;
637 out->b += gra->brightness;
638 }
639
640 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 }
646
647 if (out->r < 0)
648 out->r = 0;
649
650 if (out->r > 65535)
651 out->r = 65535;
652
653 if (out->g < 0)
654 out->g = 0;
655
656 if (out->g > 65535)
657 out->g = 65535;
658
659 if (out->b < 0)
660 out->b = 0;
661
662 if (out->b > 65535)
663 out->b = 65535;
664
665 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 }
671 }
672
673 /**
674 * FIXME
675 * @param <>
676 * @returns <>
677 * @author Martin Schaller (04/2008)
678 */
679 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
680 {
681 struct color cn;
682 if (gc->gra->colormgmt)
683 {
684 graphics_convert_color(gc->gra, c, &cn);
685 c = &cn;
686 }
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 */
696 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
697 {
698 struct color cn;
699 if (gc->gra->colormgmt)
700 {
701 graphics_convert_color(gc->gra, c, &cn);
702 c = &cn;
703 }
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 */
713 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 */
724 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 */
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 {
737 if (gc->meth.gc_set_dashes)
738 {
739 gc->meth.gc_set_dashes(gra->priv, gc->priv, width, offset, dash_list, order);
740 }
741 }
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 */
752 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 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 g_free(this_);
763 this_ = NULL;
764 }
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 */
778 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 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 g_free(this_);
789 this_ = NULL;
790 }
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 */
801 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 */
812 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 */
825 void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
826 {
827 ////DBG // dbg(0,"ooo enter ooo\n");
828
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 */
838 void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
839 {
840 ////DBG // dbg(0,"ooo enter ooo\n");
841
842 this_->meth.draw_mode(this_->priv, mode);
843 }
844
845 /**
846 * FIXME
847 * @param <>
848 * @returns <>
849 * @author Martin Schaller (04/2008)
850 */
851 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 */
867 void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
868 {
869 int i = 0;
870
871 if (this_->meth.draw_circle)
872 {
873 this_->meth.draw_circle(this_->priv, gc->priv, p, r);
874 }
875 else
876 {
877 struct point *pnt = g_alloca(sizeof(struct point) * (r * 4 + 64));
878 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 */
891 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 struct point *p = g_alloca(sizeof(struct point) * (r * 4 + 32));
899 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 int i = 0;
904
905 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 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 */
923 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 */
934 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 */
945 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 */
957 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 */
967 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 int graphics_draw_drag(struct graphics *this_, struct point *p)
978 {
979 __F_START__
980
981 if (!this_->meth.draw_drag)
982 {
983 return2 0;
984 }
985 ////DBG // dbg(0,"draw DRAG start ...\n");
986 this_->meth.draw_drag(this_->priv, p);
987 ////DBG // dbg(0,"draw DRAG end ...\n");
988 return2 1;
989
990 __F_END__
991
992 }
993
994 void graphics_background_gc(struct graphics *this_, struct graphics_gc *gc)
995 {
996 ////DBG // dbg(0,"ooo enter ooo\n");
997
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 if (item)
1038 {
1039 if (item_attr_get(item, attr_name, &attr))
1040 {
1041 curr_item=popup_item_new_text(popup,attr.u.str,1);
1042 if (item_attr_get(item, attr_info_html, &attr))
1043 {
1044 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
1045 }
1046 if (item_attr_get(item, attr_price_html, &attr))
1047 {
1048 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 */
1063 static void xdisplay_free(struct displaylist *dl)
1064 {
1065 int i;
1066 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 g_free(di);
1073 di = next;
1074 }
1075 dl->hash_entries[i].di = NULL;
1076 }
1077 }
1078
1079 /**
1080 * FIXME
1081 * @param <>
1082 * @returns <>
1083 * @author Martin Schaller (04/2008)
1084 */
1085 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 {
1087 struct displayitem *di;
1088 int len, i;
1089 // int len2;
1090 char *p;
1091
1092 len = sizeof(*di) + count * sizeof(*c);
1093 if (label && label_count > 0)
1094 {
1095 for (i = 0; i < label_count; i++)
1096 {
1097 if (label[i])
1098 {
1099 //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 }
1106 }
1107 len++; // NULL at the end
1108 }
1109
1110 p = g_malloc(len);
1111 //len2 = len - (sizeof(*di) + count * sizeof(*c));
1112 //dbg(0,"malloc len:%d len2:%d\n", len, len2);
1113
1114 di = (struct displayitem *) p;
1115 p += sizeof(*di) + count * sizeof(*c);
1116 di->item = *item;
1117
1118 if (color_yes_no)
1119 {
1120 //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 di->label = p;
1136 for (i = 0; i < label_count; i++)
1137 {
1138 if (label[i])
1139 {
1140 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 }
1149 }
1150 *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 }
1156 else
1157 {
1158 di->label = NULL;
1159 }
1160
1161 di->count = count;
1162 memcpy(di->c, c, count * sizeof(*c));
1163 di->next = entry->di;
1164 entry->di = di;
1165 }
1166
1167 /**
1168 * FIXME
1169 * @param <>
1170 * @returns <>
1171 * @author Martin Schaller (04/2008)
1172 */
1173 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 int i, x, y, tl, tlm, th, thm, tlsq, l;
1176 float lsq;
1177 // double dx, dy;
1178 float dx, dy;
1179 struct point p_t;
1180 struct point pb[5];
1181
1182 if (gra->meth.get_text_bbox)
1183 {
1184 gra->meth.get_text_bbox(gra->priv, font->priv, label, 0x10000, 0x0, pb, 1);
1185 // tl -> text length
1186 tl = (pb[2].x - pb[0].x);
1187 // th -> text height
1188 th = (pb[0].y - pb[1].y);
1189 }
1190 else
1191 {
1192 // tl -> text length
1193 tl = strlen(label) * 4;
1194 // th -> text height
1195 th = 8;
1196 }
1197 tlm = tl * 32;
1198 thm = th * 36;
1199 // tlsq -> (text length * 32) squared
1200 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 // lsq -> (line length * 32) squared
1208 lsq = dx * dx + dy * dy;
1209 if (lsq > tlsq)
1210 {
1211
1212
1213 // warning: suggest parentheses around '&&' within '||' [-Wparentheses]
1214 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 {
1216
1217
1218 // 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 #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 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 }
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 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 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 int i, dx, dy, l;
1262 struct point p;
1263 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 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1276 p = pnt[i + 1];
1277 p.x -= dx * 15 / 65536;
1278 p.y -= dy * 15 / 65536;
1279 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1280 }
1281 }
1282 }
1283
1284 static int intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy, struct point * res)
1285 {
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 if (n < 0)
1291 {
1292 n = -n;
1293 a = -a;
1294 b = -b;
1295 }
1296 #if 0
1297 if (a < 0 || b < 0)
1298 return 0;
1299 if (a > n || b > n)
1300 return 0;
1301 #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 struct circle
1310 {
1311 short x, y, fowler;
1312 }
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
1316 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir)
1317 {
1318 struct circle *c;
1319
1320 #if 0
1321 //DBG // dbg(0,"diameter=%d start=%d len=%d pos=%d dir=%d\n", diameter, start, len, *pos, dir);
1322 #endif
1323 int count = 64;
1324 int end = start + len;
1325 int i, step;
1326 c = circle64;
1327 if (diameter > 128)
1328 step = 1;
1329 else if (diameter > 64)
1330 step = 2;
1331 else if (diameter > 24)
1332 step = 4;
1333 else if (diameter > 8)
1334 step = 8;
1335 else
1336 step = 16;
1337 if (len > 0)
1338 {
1339 while (start < 0)
1340 {
1341 start += 1024;
1342 end += 1024;
1343 }
1344 while (end > 0)
1345 {
1346 i = 0;
1347 while (i < count && c[i].fowler <= start)
1348 {
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 }
1359 i += step;
1360 }
1361 end -= 1024;
1362 start -= 1024;
1363 }
1364 }
1365 else
1366 {
1367 while (start > 1024)
1368 {
1369 start -= 1024;
1370 end -= 1024;
1371 }
1372 while (end < 1024)
1373 {
1374 i = count - 1;
1375 while (i >= 0 && c[i].fowler >= start)
1376 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 }
1385 i -= step;
1386 }
1387 start += 1024;
1388 end += 1024;
1389 }
1390 }
1391 }
1392
1393 static int fowler(int dy, int dx)
1394 {
1395 int adx, ady; /* Absolute Values of Dx and Dy */
1396 int code; /* Angular Region Classification Code */
1397
1398 adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
1399 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 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 }
1426 return 0;
1427 }
1428
1429 static int int_sqrt(unsigned int n)
1430 {
1431 unsigned int h, p = 0, q = 1, r = n;
1432
1433 /* avoid q rollover */
1434 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 q <<= 2;
1443 }
1444 q >>= 2;
1445 }
1446
1447 while (q != 0)
1448 {
1449 h = p + q;
1450 p >>= 1;
1451 if (r >= h)
1452 {
1453 p += q;
1454 r -= h;
1455 }
1456 q >>= 2;
1457 }
1458 return p;
1459 }
1460
1461 struct offset
1462 {
1463 int px, py, nx, ny;
1464 };
1465
1466 static void calc_offsets(int wi, int l, int dx, int dy, struct offset *res)
1467 {
1468 int x, y;
1469
1470 x = (dx * wi) / l;
1471 y = (dy * wi) / l;
1472 if (x < 0)
1473 {
1474 res->nx = -x / 2;
1475 res->px = (x - 1) / 2;
1476 }
1477 else
1478 {
1479 res->nx = -(x + 1) / 2;
1480 res->px = x / 2;
1481 }
1482 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 }
1493
1494 // this func. is now obsolete!! and unused!!!!
1495 // this func. is now obsolete!! and unused!!!!
1496 // this func. is now obsolete!! and unused!!!!
1497 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 {
1499 int maxpoints = 200;
1500 struct point *res = g_alloca(sizeof(struct point) * maxpoints);
1501 struct point pos, poso, neg, nego;
1502 int i, dx = 0, dy = 0, l = 0, dxo = 0, dyo = 0;
1503 struct offset o, oo = { 0, 0, 0, 0 };
1504 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
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 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 #endif
1531 fow = fowler(-dy, dx);
1532 }
1533 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 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 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 else
1550 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 }
1597 break;
1598 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 }
1637
1638 i++;
1639
1640 if (i >= count)
1641 {
1642 break;
1643 }
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 dxo = -dx;
1656 dyo = -dy;
1657 fowo = fow;
1658 }
1659 }
1660 // this func. is now obsolete!! and unused!!!!
1661 // this func. is now obsolete!! and unused!!!!
1662 // this func. is now obsolete!! and unused!!!!
1663
1664
1665 struct wpoint
1666 {
1667 int x, y, w;
1668 };
1669
1670 static int clipcode(struct wpoint *p, struct point_rect *r)
1671 {
1672 int code = 0;
1673 if (p->x < r->lu.x)
1674 code = 1;
1675 if (p->x > r->rl.x)
1676 code = 2;
1677 if (p->y < r->lu.y)
1678 code |= 4;
1679 if (p->y > r->rl.y)
1680 code |= 8;
1681 return code;
1682 }
1683
1684 #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 static int lines_intersect(int x1, int y1, /* First line segment */
1691 int x2, int y2,
1692
1693 int x3, int y3, /* Second line segment */
1694 int x4, int y4,
1695
1696 int *x, int *y /* Output value:
1697 * point of intersection */
1698 )
1699 {
1700 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
1704 /* Compute a1, b1, c1, where line joining points 1 and 2
1705 * is "a1 x + b1 y + c1 = 0".
1706 */
1707
1708 a1 = y2 - y1;
1709 b1 = x1 - x2;
1710 c1 = x2 * y1 - x1 * y2;
1711
1712 /* Compute r3 and r4.
1713 */
1714 r3 = a1 * x3 + b1 * y3 + c1;
1715 r4 = a1 * x4 + b1 * y4 + c1;
1716
1717 /* 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 {
1722 return (DONT_INTERSECT);
1723 }
1724
1725 /* Compute a2, b2, c2 */
1726 a2 = y4 - y3;
1727 b2 = x3 - x4;
1728 c2 = x4 * y3 - x3 * y4;
1729
1730 /* Compute r1 and r2 */
1731 r1 = a2 * x1 + b2 * y1 + c2;
1732 r2 = a2 * x2 + b2 * y2 + c2;
1733
1734 /* 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 {
1740 return (DONT_INTERSECT);
1741 }
1742
1743 /* Line segments intersect: compute intersection point.
1744 */
1745
1746 denom = a1 * b2 - a2 * b1;
1747 if (denom == 0)
1748 {
1749 return (COLLINEAR);
1750 }
1751 offset = denom < 0 ? -denom / 2 : denom / 2;
1752
1753 /* 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 /*
1758 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
1764 return (DO_INTERSECT);
1765 } /* 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 else if ((code1 == 0) && (code2 == 0))
1778 {
1779 // line completely visible!
1780 return 1;
1781 }
1782 else if ((code1 == 0) || (code2 == 0))
1783 {
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 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 if (ret_ == DO_INTERSECT)
1794 {
1795 return 3;
1796 }
1797 // bottom
1798 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 if (ret_ == DO_INTERSECT)
1800 {
1801 return 3;
1802 }
1803 // left
1804 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 if (ret_ == DO_INTERSECT)
1806 {
1807 return 3;
1808 }
1809 // right
1810 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 if (ret_ == DO_INTERSECT)
1812 {
1813 return 3;
1814 }
1815 }
1816 // not visible
1817 return 0;
1818 }
1819
1820 static int clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1821 {
1822 int code1, code2, ret = 1;
1823 int dx, dy, dw;
1824 code1 = clipcode(p1, r);
1825 if (code1)
1826 ret |= 2;
1827 code2 = clipcode(p2, r);
1828 if (code2)
1829 ret |= 4;
1830 dx = p2->x - p1->x;
1831 dy = p2->y - p1->y;
1832 dw = p2->w - p1->w;
1833 while (code1 || code2)
1834 {
1835 if (code1 & code2)
1836 {
1837 return 0;
1838 }
1839 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 }
1845 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 if (code1 & code2)
1865 return 0;
1866 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 }
1872 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 }
1892 return ret;
1893 }
1894
1895
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 {
1905
1906 struct point *p = g_alloca(sizeof(struct point) * (count + 1));
1907 struct wpoint p1, p2;
1908 int i;
1909 int code;
1910 int wmax;
1911 int out = 0;
1912 // const int max_segs = 2000;
1913 int max_segs = 20; // send max this many segments to java with one single call
1914 struct point_rect r = gra->r;
1915
1916
1917 if (order < global_order_level_for_fast_draw)
1918 {
1919 max_segs = 100;
1920 }
1921
1922 //if (count > 30)
1923 //{
1924 // dbg(0,"segment count=%d\n", count);
1925 //}
1926
1927 #if 0
1928 // check if whole line is within a 2x2 pixel square
1929 if (order < 11)
1930 {
1931 const int max_dist = 2*2;
1932 int need_draw = 0;
1933 int diff;
1934 for (i = 0; i < count; i++)
1935 {
1936 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 }
1959
1960 if (need_draw == 0)
1961 {
1962 // dont draw this line
1963 return;
1964 }
1965 }
1966 #endif
1967
1968 // calc visible area on screen
1969 wmax = width[0];
1970 r.lu.x -= wmax;
1971 r.lu.y -= wmax;
1972 r.rl.x += wmax;
1973 r.rl.y += wmax;
1974
1975 for (i = 0; i < count; i++)
1976 {
1977 if (i > 0)
1978 {
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 /* 0 = invisible, 1 = completely visible, 2,3 = at least part of line visible */
1984 code = clip_line_aprox(&p1, &p2, &r);
1985 // code = 1;
1986
1987 if (code > 0)
1988 {
1989 if (out == 0)
1990 {
1991 p[out].x = p1.x;
1992 p[out].y = p1.y;
1993 out++;
1994 }
1995 p[out].x = p2.x;
1996 p[out].y = p2.y;
1997 out++;
1998
1999 if ((out <= max_segs) && (i < (count - 1)))
2000 {
2001 // ok gather more line segs
2002 continue;
2003 }
2004 }
2005 else // (code == 0)
2006 {
2007 if (out == 0)
2008 {
2009 // first visible line seg not yet found, search on ...
2010 continue;
2011 }
2012 }
2013
2014 // PAINT --- LINE SEGMENTS ------------
2015 // PAINT --- LINE SEGMENTS ------------
2016
2017 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 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 //draw_lines_count_3++;
2042 //}
2043
2044 // 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
2057 //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
2065 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 // draw as line
2077 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 1, dashes, c, 1);
2078 //draw_lines_count_4++;
2079 //}
2080
2081 // 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
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 //draw_lines_count_4++;
2107
2108 // 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
2120 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c, global_clinedrawing_active, 1);
2121 //draw_lines_count_3++;
2122
2123 // 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
2131 out = 0; // reset point counter after painting
2132 // PAINT --- LINE SEGMENTS ------------
2133 // PAINT --- LINE SEGMENTS ------------
2134 // PAINT --- LINE SEGMENTS ------------
2135 }
2136 }
2137 }
2138
2139 static int is_inside(struct point *p, struct point_rect *r, int edge)
2140 {
2141 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 }
2154 }
2155
2156 static void poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
2157 {
2158 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 }
2179 }
2180
2181 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
2182 {
2183 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 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 if (count_in < limit)
2197 {
2198 p1 = pa1;
2199 p2 = pa2;
2200 }
2201 else
2202 {
2203 p1 = g_new0(struct point, count_in*8+1);
2204 p2 = g_new0(struct point, count_in*8+1);
2205 }
2206
2207 pout=p1;
2208 for (edge = 0; edge < 4; edge++)
2209 {
2210 p=pin;
2211 s=pin+count_in-1;
2212 count_out=0;
2213 for (i = 0; i < count_in; i++)
2214 {
2215 if (is_inside(p, &r, edge))
2216 {
2217 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 }
2224 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 }
2235 count_in=count_out;
2236 if (pin == p1)
2237 {
2238 pin=p2;
2239 pout=p1;
2240 }
2241 else
2242 {
2243 pin=p1;
2244 pout=p2;
2245 }
2246 }
2247
2248
2249
2250 gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
2251 if (count_in >= limit)
2252 {
2253 g_free(p1);
2254 g_free(p2);
2255 }
2256 }
2257
2258 static void display_context_free(struct display_context *dc)
2259 {
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 dc->gc = NULL;
2267 dc->gc_background = NULL;
2268 dc->img = NULL;
2269 }
2270
2271 static struct graphics_font *
2272 get_font(struct graphics *gra, int size)
2273 {
2274 if (size > 64)
2275 {
2276 size = 64;
2277 }
2278
2279 if (size >= gra->font_len)
2280 {
2281 gra->font=g_renew(struct graphics_font *, gra->font, size+1);
2282 while (gra->font_len <= size)
2283 {
2284 gra->font[gra->font_len++] = NULL;
2285 }
2286 }
2287
2288 if (!gra->font[size])
2289 {
2290 gra->font[size] = graphics_font_new(gra, size * gra->font_size, 0);
2291 }
2292
2293 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 struct graphics_font *font = get_font(this_, text_size);
2299 struct point bbox[4];
2300 int i;
2301
2302 graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
2303 for (i = 0; i < 4; i++)
2304 {
2305 bbox[i].x += p->x;
2306 bbox[i].y += p->y;
2307 }
2308 graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x - bbox[0].x, bbox[0].y - bbox[1].y + 5);
2309 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 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 if (file_wordexp_get_count(wordexp))
2323 {
2324 icon = file_wordexp_get_array(wordexp)[0];
2325 }
2326 }
2327
2328 if (strchr(icon, '/'))
2329 {
2330 ret = g_strdup(icon);
2331 }
2332 else
2333 {
2334 #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 // // dbg(1,"android icon_path %s\n",icon);
2339 // 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 if (!navit_sharedir)
2345 {
2346 navit_sharedir = getenv("NAVIT_SHAREDIR");
2347 }
2348 ret = g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
2349 #endif
2350 }
2351
2352 if (wordexp)
2353 {
2354 file_wordexp_destroy(wordexp);
2355 }
2356
2357 return ret;
2358 }
2359
2360 static int limit_count(struct coord *c, int count)
2361 {
2362 int i;
2363 for (i = 1; i < count; i++)
2364 {
2365 if (c[i].x == c[0].x && c[i].y == c[0].y)
2366 return i + 1;
2367 }
2368 return count;
2369 }
2370
2371 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 {
2373
2374 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 struct point p;
2381 char *path;
2382 struct color custom_color;
2383 int dont_draw = 0;
2384
2385 int oneway;
2386 int mark_way;
2387
2388 //if (run_type > 100) // dbg(0,"enter\n");
2389
2390 while (di)
2391 {
2392
2393 // stop drawing is requested
2394 if (cancel_drawing_global == 1)
2395 {
2396 break;
2397 }
2398
2399 if (run_type != 99)
2400 {
2401 if (run_type == 1)
2402 {
2403 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2404 {
2405 // next item
2406 di = di->next;
2407 continue;
2408 }
2409 else if (di->item.flags & NAVIT_AF_BRIDGE)
2410 {
2411 // next item
2412 di = di->next;
2413 continue;
2414 }
2415 }
2416 else if (run_type == 2)
2417 {
2418 // tunnel
2419 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2420 {
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 if (di->item.flags & NAVIT_AF_BRIDGE)
2433 {
2434 }
2435 else
2436 {
2437 // next item
2438 di = di->next;
2439 continue;
2440 }
2441 }
2442 }
2443
2444 int i, count = di->count, mindist = dc->mindist;
2445
2446 if (!gc)
2447 {
2448 gc = graphics_gc_new(gra);
2449
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 dc->gc = gc;
2467 }
2468
2469 if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
2470 {
2471 count = limit_count(di->c, count);
2472 }
2473
2474 if (dc->type == type_poly_water_tiled)
2475 {
2476 mindist = 0;
2477 if (order < 12)
2478 {
2479 mindist = 4;
2480 }
2481 }
2482 else if (dc->type == type_border_country)
2483 {
2484 if (order < 10)
2485 {
2486 mindist = 4;
2487 }
2488 }
2489 else if (dc->type == type_poly_wood_from_triang)
2490 {
2491 if (order > 11)
2492 {
2493 mindist = 0;
2494 }
2495 }
2496 else if (dc->type == type_poly_water_from_triang)
2497 {
2498 if (order > 10)
2499 {
2500 mindist = 0;
2501 }
2502 }
2503 #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
2516
2517 if (dc->e->type == element_polyline)
2518 {
2519 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
2520 }
2521 else
2522 {
2523 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
2524 }
2525
2526 //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 switch (e->type)
2530 {
2531 case element_polygon:
2532 graphics_draw_polygon_clipped(gra, gc, pa, count);
2533 break;
2534 case element_polyline:
2535 {
2536 gc->meth.gc_set_linewidth(gc->priv, 1);
2537
2538 int poly = e->u.polyline.width > 1;
2539
2540 // detect underground streets/lines/etc ...
2541 //if ((allow_dashed) && (di->item.flags & NAVIT_AF_UNDERGROUND))
2542 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2543 {
2544 poly = 2;
2545 }
2546 else if (di->item.flags & NAVIT_AF_BRIDGE)
2547 {
2548 poly = 3;
2549 }
2550
2551 oneway = 0;
2552 if (di->item.flags & NAVIT_AF_ONEWAYREV)
2553 {
2554 oneway = 2;
2555 if (di->item.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)
2556 {
2557 oneway = oneway + 4; // oneway does not apply to bicycles here
2558 }
2559 }
2560 else if (di->item.flags & NAVIT_AF_ONEWAY)
2561 {
2562 oneway = 1;
2563 if (di->item.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)
2564 {
2565 oneway = oneway + 4; // oneway does not apply to bicycles here
2566 }
2567 }
2568
2569 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 // -------- apply dashes -------
2584 //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 // -------- apply dashes -------
2589
2590 //for (i = 0; i < count; i++)
2591 //{
2592 // if (width[i] < 1)
2593 // {
2594 // width[i] = 1;
2595 // }
2596 //}
2597
2598 if (dc->type == type_border_country)
2599 {
2600 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway, e->u.polyline.dash_num, &e->color, 0);
2601 }
2602 else
2603 {
2604 // 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 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &custom_color, 0);
2626 }
2627 else
2628 {
2629 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 }
2638 }
2639 // change color of route if in bicycle-route-mode and we want to drive against the oneway street
2640 else if ((dc->type == type_street_route || dc->type == type_street_route_waypoint) && (global_vehicle_profile == 1) && ((di->col_int_value >> 26) & 3))
2641 {
2642 // 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 }
2670 else // all other ways
2671 {
2672 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 }
2681 }
2682
2683 // -------- cancel dashes -------
2684 //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 // -------- cancel dashes -------
2692 }
2693 break;
2694 case element_circle:
2695 if (count)
2696 {
2697 //// dbg(0, "graphics_draw_circle\n");
2698
2699 if (di->label)
2700 {
2701 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 {
2706 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 }
2715 else if (item_is_town_label_no_major(dc->type))
2716 {
2717 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 }
2726 else if (item_is_town_label_major(dc->type))
2727 {
2728 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 }
2737 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 }
2788 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 }
2800 break;
2801 case element_text:
2802 if (count && di->label)
2803 {
2804 //if (run_type > 100) // dbg(0,"gg006\n");
2805
2806 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 }
2815
2816 if (font)
2817 {
2818 if (order > 8)
2819 {
2820 label_line(gra, gc, gc_background, font, pa, count, di->label);
2821 }
2822 }
2823 else
2824 {
2825 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2826 }
2827 }
2828 break;
2829 case element_icon:
2830 if (count)
2831 {
2832 dont_draw = 0;
2833
2834 // dbg(0,"MAP:poi-on_map:#%d:%s\n", poi_icon_on_map_count, item_to_name(dc->type));
2835
2836 if (item_is_poi(dc->type))
2837 {
2838 if (poi_icon_on_map_count > MAX_POI_ICONS_ON_MAP)
2839 {
2840 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
2867 path = graphics_icon_path(icon);
2868 g_free(icon);
2869 }
2870 else
2871 {
2872 path = graphics_icon_path(e->u.icon.src);
2873
2874 // dbg(0,"MAP:icon=%s\n", path);
2875 }
2876
2877 img = graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
2878 if (img)
2879 {
2880 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 }
2894 else
2895 {
2896 // missing icon //
2897 dbg(0, "-- ICON MISSING -- failed to load icon '%s'\n", path);
2898 }
2899
2900 g_free(path);
2901 }
2902
2903 if (img)
2904 {
2905 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 }
2911 }
2912 }
2913 break;
2914 case element_image:
2915 //dbg(0, "***image***: '%s'\n", di->label);
2916 if (gra->meth.draw_image_warp)
2917 {
2918 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2919 }
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 {
2929 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2930 }
2931 //else
2932 //{
2933 // dbg(0,"draw_image_warp not supported by graphics driver drawing: image='%s' count=%d\n",di->label, count);
2934 //}
2935 break;
2936 case element_arrows:
2937 display_draw_arrows(gra, gc, pa, count);
2938 break;
2939 //default:
2940 // printf("Unhandled element type %d\n", e->type);
2941 }
2942 di = di->next;
2943 }
2944
2945 //if (run_type > 100) // dbg(0,"gg099\n");
2946 }
2947
2948
2949
2950
2951
2952 /**
2953 * FIXME
2954 * @param <>
2955 * @returns <>
2956 * @author Martin Schaller (04/2008)
2957 */
2958 static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, int run_type)
2959 {
2960
2961 struct element *e;
2962 GList *es, *types;
2963 struct display_context *dc = &display_list->dc;
2964 struct hash_entry *entry;
2965 int draw_it = 1;
2966 int is_first_item = 1;
2967
2968 #ifdef NAVIT_MEASURE_TIME_DEBUG
2969 clock_t s_ = debug_measure_start();
2970 #endif
2971
2972 is_first_item = 1;
2973
2974 es = itm->elements;
2975 while (es)
2976 {
2977 //// dbg(0,"*es\n");
2978 e = es->data;
2979 dc->e = e;
2980 types = itm->type;
2981 while (types)
2982 {
2983 draw_it = 1;
2984
2985 // stop drawing is requested
2986 if (cancel_drawing_global == 1)
2987 {
2988 break;
2989 }
2990
2991 dc->type = GPOINTER_TO_INT(types->data);
2992 // dbg(0,"**type=%s\n", item_to_name(dc->type));
2993
2994 if (global_draw_multipolygons == 0)
2995 {
2996 if (dc->type == type_poly_water_from_relations)
2997 {
2998 // ok "poly_water_from_relations" is found, now what?
2999 draw_it = 0;
3000 }
3001 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 }
3018
3019 if (draw_it == 1)
3020 {
3021 entry = get_hash_entry(display_list, dc->type);
3022 if (entry && entry->di)
3023 {
3024 //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 //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 displayitem_draw(entry->di, NULL, dc, display_list->order, 1, run_type, is_first_item);
3033 is_first_item = 0;
3034 //}
3035 // // dbg(0,"**+gc free\n");
3036 display_context_free(dc);
3037 }
3038 }
3039 types = g_list_next(types);
3040 draw_it = 1;
3041 }
3042 es = g_list_next(es);
3043 }
3044
3045 #ifdef NAVIT_MEASURE_TIME_DEBUG
3046 debug_mrp("xdisplay_draw_elements:", debug_measure_end(s_));
3047 #endif
3048
3049
3050 }
3051
3052 void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
3053 {
3054 // dbg(0, "EEnter\n");
3055
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 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 // dbg(0, "while loop\n");
3081 struct element *e = es->data;
3082 if (e->coord_count)
3083 {
3084 if (e->coord_count > max_coord)
3085 {
3086 //DBG // dbg(0, "maximum number of coords reached: %d > %d\n", e->coord_count, max_coord);
3087 di->count = max_coord;
3088 }
3089 else
3090 {
3091 di->count = e->coord_count;
3092 }
3093 memcpy(di->c, e->coord, di->count * sizeof(struct coord));
3094 }
3095 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 displayitem_draw(di, NULL, &dc, transform_get_scale(t), 0, 99, 0);
3104 display_context_free(&dc);
3105 es = g_list_next(es);
3106 }
3107 }
3108
3109 /**
3110 * FIXME
3111 * @param <>
3112 * @returns <>
3113 * @author Martin Schaller (04/2008)
3114 */
3115 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
3121 int run_type = 0; // 99 -> normal
3122 // 1 -> normal streets (except tunnels and bridges)
3123 // 2 -> tunnel
3124 // 3 -> bridge
3125
3126 int send_refresh = 0;
3127
3128 int order_corrected = order + shift_order;
3129 if (order_corrected < limit_order_corrected)
3130 {
3131 order_corrected = limit_order_corrected;
3132 }
3133
3134 int order_corrected_2 = order + shift_order;
3135 if (order < 0)
3136 {
3137 order_corrected_2 = 0;
3138 }
3139
3140 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 // dbg(0,"layer name=%s\n", lay->name);
3150
3151 // 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 if ((strncmp("streets_1", lay->name, 9) == 0))
3161 {
3162 //// dbg(0,"MT:7.3.1 - tunnel start\n");
3163 //draw_lines_count_2 = 0;
3164 //draw_lines_count_3 = 0;
3165 //draw_lines_count_4 = 0;
3166
3167 send_refresh = 1;
3168
3169 //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 run_type = 2;
3179 itms = lay->itemgras;
3180 while (itms)
3181 {
3182 // stop drawing is requested
3183 if (cancel_drawing_global == 1)
3184 {
3185 //DBG // dbg(0, "** STOP MD 002 **\n");
3186 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 }
3197
3198 //// 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 //draw_lines_count_2 = 0;
3202 //draw_lines_count_3 = 0;
3203 //draw_lines_count_4 = 0;
3204 //// dbg(0,"MT:7.3.2 - streets start\n");
3205
3206 run_type = 1;
3207 itms = lay->itemgras;
3208 while (itms)
3209 {
3210 // stop drawing is requested
3211 if (cancel_drawing_global == 1)
3212 {
3213 //DBG // dbg(0, "** STOP MD 002 **\n");
3214 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 }
3225
3226 /*
3227 // 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
3236 }
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 itms = lay->itemgras;
3253 while (itms)
3254 {
3255 // stop drawing is requested
3256 if (cancel_drawing_global == 1)
3257 {
3258 //DBG // dbg(0, "** STOP MD 002 **\n");
3259 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 // 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
3281 }
3282 else
3283 {
3284 run_type = 99;
3285 itms = lay->itemgras;
3286 while (itms)
3287 {
3288 // stop drawing is requested
3289 if (cancel_drawing_global == 1)
3290 {
3291 //DBG // dbg(0, "** STOP MD 002 **\n");
3292 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 }
3304
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 // dirty hack to draw "waypoint(s)" ---------------------------
3313 if (strncmp("Internal", lay->name, 8) == 0)
3314 {
3315 // if (global_routing_engine != 1)
3316 {
3317 if (global_navit->route)
3318 {
3319 if (global_navit->destination_valid == 1)
3320 {
3321 int count_ = 0;
3322 int curr_ = 0;
3323 count_ = g_list_length(global_navit->route->destinations);
3324 if (count_ > 1)
3325 {
3326 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
3332 // 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
3336 //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
3342 g_free(path2);
3343 }
3344
3345 struct point p2;
3346 struct coord pc77;
3347 GList *ldest = global_navit->route->destinations;
3348 while (ldest)
3349 {
3350 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 }
3367 }
3368 }
3369 }
3370 }
3371
3372
3373 #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
3383
3384 #ifdef NAVIT_TRACKING_SHOW_REAL_GPS_POS
3385
3386 if (global_tracking_show_real_gps_pos == 1)
3387 {
3388
3389 // -------- 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 #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 // ------ 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 }
3519
3520 #endif
3521
3522 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3523
3524 // -------- 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 // -------- DEBUG -------- draw winner track segment ---------
3575 // -------- DEBUG -------- draw winner track segment ---------
3576 // -------- DEBUG -------- draw winner track segment ---------
3577 #endif
3578
3579
3580 // ============================== debug lines ==============================
3581 // ============================== debug lines ==============================
3582 // ============================== debug lines ==============================
3583 #ifdef NAVIT_DEBUG_COORD_LIST
3584 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 // dbg(0,"global_debug_coord_list:LOOP:num=%d\n", global_debug_coord_list_items);
3599
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 }
3659 // dirty hack to draw "waypoint(s)" ---------------------------
3660 // 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
3668 #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
3673 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 {
3778 first3 = 1;
3779 item2 = map_rect_get_item(mr2);
3780 continue;
3781 }
3782
3783 // loop all coords of the route ----------------------
3784 if (first3 == 1)
3785 {
3786 first3 = 0;
3787 }
3788 else
3789 {
3790 if ( ((c2.x == c8.x) && (c2.y == c8.y)) || (found_seg == 1) )
3791 {
3792 //if (first2 == 1)
3793 //{
3794 // first2 = 0;
3795 //}
3796 //else
3797 {
3798 //dbg(0, "11draw:c2.x=%d c2.y=%d c2_prev.x=%d c2_prev.y=%d\n", c2.x, c2.y, c2_prev.x, c2_prev.y);
3799 if (found_seg == 1)
3800 {
3801 // draw arrow head at the end
3802
3803 route_line_length_sq = (float)transform_distance_sq(&c2_prev, &c2);
3804 if ((added_seg == 0) && (route_line_length_sq < MIN_ROUTE_ARROW_LINE_LENGTH_SQ))
3805 {
3806 // draw line
3807 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3808 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3809 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3810
3811 // add next coord to line/arrow
3812 found_seg = 0;
3813 added_seg = 1;
3814 }
3815 else
3816 {
3817 if (route_line_length_sq > MAX_ROUTE_ARROW_LINE_LENGTH_SQ)
3818 {
3819 route_line_length_sq = sqrt(route_line_length_sq);
3820 // make line shorter (move coord c2 backward)
3821 dx = ((float)(c2.x - c2_prev.x)) / route_line_length_sq;
3822 dy = ((float)(c2.y - c2_prev.y)) / route_line_length_sq;
3823 c2.x = c2_prev.x + (int)(dx * MAX_ROUTE_ARROW_LINE_LENGTH);
3824 c2.y = c2_prev.y + (int)(dy * MAX_ROUTE_ARROW_LINE_LENGTH);
3825 }
3826
3827 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3828 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3829 arrow_waiting = 1;
3830 p11_temp[0].x = p9_temp[0].x;
3831 p11_temp[0].y = p9_temp[0].y;
3832 p11_temp[1].x = p9_temp[1].x;
3833 p11_temp[1].y = p9_temp[1].y;
3834 c11.x = c2.x;
3835 c11.y = c2.y;
3836 // gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 4);
3837 }
3838 }
3839 else
3840 {
3841 route_line_length_sq = (float)transform_distance_sq(&c2_prev, &c2);
3842 if (route_line_length_sq > MAX_ROUTE_ARROW_LINE_LENGTH_SQ)
3843 {
3844 route_line_length_sq = sqrt(route_line_length_sq);
3845 // make line shorter (move coord c2_prev forward)
3846 dx = ((float)(c2.x - c2_prev.x)) / route_line_length_sq;
3847 dy = ((float)(c2.y - c2_prev.y)) / route_line_length_sq;
3848 c2_prev.x = c2.x - (int)(dx * MAX_ROUTE_ARROW_LINE_LENGTH);
3849 c2_prev.y = c2.y - (int)(dy * MAX_ROUTE_ARROW_LINE_LENGTH);
3850 }
3851
3852 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3853 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3854
3855 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3856
3857 if (arrow_waiting == 1)
3858 {
3859 arrow_waiting = 0;
3860 if (((abs(c2.x - c11.x)<4) && (abs(c2.y - c11.y)<4)) || ((abs(c2_prev.x - c11.x)<4) && (abs(c2_prev.y - c11.y)<4)))
3861 {
3862 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3863 }
3864 else
3865 {
3866 if (route_arrow_count == 2)
3867 {
3868 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, &route_arrrow_green_1, global_clinedrawing_active, 4);
3869 }
3870 else
3871 {
3872 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, &route_arrrow_green_2, global_clinedrawing_active, 4);
3873 }
3874 }
3875 }
3876
3877 }
3878 }
3879
3880 if (found_seg == 0)
3881 {
3882 found_seg++;
3883 }
3884 else if (found_seg == 1)
3885 {
3886 break;
3887 }
3888
3889 }
3890 }
3891 c2_prev.x = c2.x;
3892 c2_prev.y = c2.y;
3893
3894 // loop all coords of the route ----------------------
3895 }
3896 map_rect_destroy(mr2);
3897 }
3898 }
3899 }
3900 // --- find the segments for this maneuver ---
3901
3902 }
3903 }
3904 map_rect_destroy(mr);
3905
3906 if (arrow_waiting == 1)
3907 {
3908 // if there is still an arrow to be drawn, draw it now
3909 arrow_waiting = 0;
3910 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 4);
3911 }
3912
3913 }
3914 }
3915 }
3916
3917 #endif
3918
3919
3920
3921 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
3922 // ------- free text list ----------
3923 // ------- free text list ----------
3924
3925 struct color debug_blue2a = { 0x0000,0x0000,0xffff,0xffff }; // RR GG BB AA
3926 struct color debug_black2a = { 0x0000,0x0000,0x0000,0xffff }; // RR GG BB AA
3927 struct point *p_temp13a = g_alloca(sizeof(struct point));
3928 struct point *p9_temp13a = g_alloca(sizeof(struct point) * (2 + 1));
3929 enum projection pro4a = transform_get_projection(global_navit->trans_cursor);
3930 graphics_gc_set_linewidth(gra->gc[0], 8);
3931
3932 int ij1a;
3933 for (ij1a=0; ij1a < global_freetext_list_count; ij1a++)
3934 {
3935 transform(global_navit->trans, pro4a, &global_freetext_list[ij1a].c1, p_temp13a, 1, 0, 0, NULL);
3936 graphics_gc_set_foreground(gra->gc[0], &debug_blue2a);
3937 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, p_temp13a, 36);
3938
3939 // ------ text -------
3940 struct point p7a;
3941 struct graphics_font *font8a = get_font(gra, 10);
3942 graphics_gc_set_foreground(gra->gc[0], &debug_black2a);
3943 p7a.x = p_temp13a->x + 25; // move text label a bit to the right, so it does not overlap the circle
3944 p7a.y = p_temp13a->y + 25; // move label a bit down (y-axis)
3945 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8a->priv, global_freetext_list[ij1a].text, &p7a, 0x10000, 0);
3946 // ------ text -------
3947 }
3948
3949 // ------- free text list ----------
3950 // ------- free text list ----------
3951 #endif
3952
3953
3954
3955
3956
3957
3958 // ------- sharp turn angle list ----------
3959 // ------- sharp turn angle list ----------
3960 #ifdef NAVIT_ANGLE_LIST_DEBUG_PRINT_DRAW
3961 struct color debug_green2 = { 0x0000,0xffff,0x0000,0xffff }; // RR GG BB AA
3962 struct color debug_blue2 = { 0x0000,0x0000,0xffff,0xffff }; // RR GG BB AA
3963 struct color debug_red2 = { 0xffff,0x0000,0x0000,0xffff }; // RR GG BB AA
3964 struct point *p_temp13 = g_alloca(sizeof(struct point));
3965 struct point *p9_temp13 = g_alloca(sizeof(struct point) * (2 + 1));
3966 enum projection pro4 = transform_get_projection(global_navit->trans_cursor);
3967 graphics_gc_set_linewidth(gra->gc[0], 8);
3968
3969 int ij1;
3970 for (ij1=0; ij1 < global_sharp_turn_list_count;ij1++)
3971 {
3972 transform(global_navit->trans, pro4, &global_sharp_turn_list[ij1].c1, p_temp13, 1, 0, 0, NULL);
3973 if (global_sharp_turn_list[ij1].dir == 1)
3974 {
3975 graphics_gc_set_foreground(gra->gc[0], &debug_green2);
3976 }
3977 else
3978 {
3979 graphics_gc_set_foreground(gra->gc[0], &debug_blue2);
3980 }
3981 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, p_temp13, 36);
3982
3983
3984 // --- line of turn angle ---
3985 p9_temp13[0].x = p_temp13->x;
3986 p9_temp13[0].y = p_temp13->y;
3987 transform(global_navit->trans, pro3, &global_sharp_turn_list[ij1].cs, &p9_temp13[1], 1, 0, 0, NULL);
3988 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp13, 2, 15, 12, 0, &debug_red2, global_clinedrawing_active, 1);
3989 transform(global_navit->trans, pro3, &global_sharp_turn_list[ij1].ce, &p9_temp13[1], 1, 0, 0, NULL);
3990 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp13, 2, 15, 5, 0, &debug_green2, global_clinedrawing_active, 1);
3991 // --- line of turn angle ---
3992
3993
3994
3995 // ------ text -------
3996 // graphics_gc_set_foreground(gra->gc[0], &debug_red2);
3997 // graphics_gc_set_linewidth(gra->gc[0], 8);
3998 struct point p7;
3999 struct graphics_font *font8 = get_font(gra, 24);
4000 char *dir_label=g_strdup_printf("%d", global_sharp_turn_list[ij1].angle);
4001 // dbg(0, "st.angle(2)=%d\n", global_sharp_turn_list[ij1].angle);
4002
4003 if (global_sharp_turn_list[ij1].angle > 0)
4004 {
4005 p7.x = p_temp13->x + 25; // move text label a bit to the right, so it does not overlap the circle
4006 p7.y = p_temp13->y + 25;
4007 // p7.y = p_temp13->y + 25 + (int)((float)global_sharp_turn_list[ij1].angle / 2.0f); // move label a bit down (y-axis)
4008 }
4009 else
4010 {
4011 p7.x = p_temp13->x + 25; // move text label a bit to the right, so it does not overlap the circle
4012 p7.y = p_temp13->y + 0;
4013 // p7.y = p_temp13->y + 0 + (int)((float)global_sharp_turn_list[ij1].angle / 2.0f); // move label a bit down (y-axis)
4014 }
4015 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, dir_label, &p7, 0x10000, 0);
4016 g_free(dir_label);
4017 // ------ text -------
4018
4019 }
4020 #endif
4021 // ------- sharp turn angle list ----------
4022 // ------- sharp turn angle list ----------
4023
4024 }
4025 }
4026 }
4027 // dirty hack to draw "route arrows" ---------------------------
4028
4029
4030 if (send_refresh == 1)
4031 {
4032 // dummy "ready" signal ------------------------------------------
4033 // dbg(0, "dummy \"ready\" signal (layers)\n");
4034 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 96, 0, NULL, 1);
4035 // dummy "ready" signal ------------------------------------------
4036 }
4037
4038 }
4039
4040 /**
4041 * FIXME
4042 * @param <>
4043 * @returns <>
4044 * @author Martin Schaller (04/2008)
4045 */
4046 static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
4047 {
4048 __F_START__
4049
4050 GList *lays;
4051 struct layer *lay;
4052
4053 // int draw_vector_map = 1;
4054
4055 // if zoomed out too much then use prerendered map tiles
4056 //if (display_list->order < ORDER_USE_PRERENDERED_MAP)
4057 //{
4058 // draw_vector_map = 0;
4059 //}
4060
4061 #if 0
4062 if (!draw_vector_map)
4063 {
4064 // draw prerendered big mapimage --- HERE ---
4065 struct transformation *t;
4066 t = display_list->dc.trans;
4067 struct coord *cp;
4068 cp = transform_get_center(t);
4069 struct attr attr;
4070 struct config
4071 {
4072 struct attr **attrs;
4073 struct callback_list *cbl;
4074 }*config;
4075 struct point p;
4076 int valid = 0;
4077 if (global_navit)
4078 {
4079 if ((global_navit->vehicle) && (global_navit->vehicle->vehicle))
4080 {
4081 //int a, s;
4082 //struct point pnt2;
4083 //vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
4084
4085 //struct attr pos_attr;
4086 //if (vehicle_get_attr(global_navit->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL))
4087 //{
4088 // ////DBG // dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
4089 //}
4090
4091 valid = 1;
4092 }
4093 }
4094
4095 struct coord *c;
4096 c = &(t->map_center);
4097
4098 enum projection pro = transform_get_projection(global_navit->trans_cursor);
4099 struct coord_geo g22;
4100 struct coord *c22;
4101 struct point mcenter_pnt;
4102 c22 = &(t->map_center);
4103 transform_to_geo(projection_mg, c22, &g22);
4104 transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
4105
4106 struct coord c99;
4107 struct coord_geo g99;
4108 struct point cursor_pnt;
4109 struct point p99;
4110 long my_scale;
4111
4112 my_scale = transform_get_scale(global_navit->trans);
4113
4114 g99.lat = 0.0;
4115 g99.lng = 0.0;
4116 // g99.lat = 80.0;
4117 // g99.lng = -174.0;
4118 transform_from_geo(pro, &g99, &c99);
4119 transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
4120
4121 // now really draw it
4122 struct graphics *gra22 = display_list->dc.gra;
4123 struct graphics_gc *gc22 = display_list->dc.gc;
4124 if (!gc22)
4125 {
4126 gc22 = graphics_gc_new(gra22);
4127 }
4128 // graphics_draw_bigmap(gra22, gc22, -t->yaw, display_list->order, g22.lat, g22.lng, cursor_pnt.x, cursor_pnt.y, mcenter_pnt.x, mcenter_pnt.y, global_vehicle_pos_onscreen.x, global_vehicle_pos_onscreen.y, valid);
4129 graphics_draw_bigmap(gra22, gc22, -t->yaw, (int) (my_scale / 100), g22.lat, g22.lng, cursor_pnt.x, cursor_pnt.y, mcenter_pnt.x, mcenter_pnt.y, global_vehicle_pos_onscreen.x, global_vehicle_pos_onscreen.y, valid);
4130 }
4131 #endif
4132
4133 // reset value; --> not sure here, maybe it should NOT be reset here!!!???
4134 // cancel_drawing_global = 0;
4135
4136
4137
4138
4139
4140
4141
4142 // stop drawing is requested
4143 if (cancel_drawing_global != 1)
4144 {
4145
4146 if ((display_list->order >= ORDER_USE_PRERENDERED_MAP) || (global_show_maps_debug_view)) // ==5 , (4,3,2,1,0)--> no vector map
4147 {
4148 // MAPNIK -- MVT --
4149 // MAPNIK -- MVT --
4150 // MAPNIK -- MVT --
4151 int screen_width, screen_height;
4152 struct coord c_screen;
4153 struct point p_screen;
4154 struct coord_geo g_screen_lt;
4155 struct coord_geo g_screen_rt;
4156 struct coord_geo g_screen_rb;
4157
4158 transform_get_size(global_navit->trans, &screen_width, &screen_height);
4159 // dbg(0, "transform_get_size:w=%d h=%d\n", screen_width, screen_height);
4160 // dbg(0, "navit_maps_dir=%s\n", navit_maps_dir);
4161
4162 p_screen.x = 0;
4163 p_screen.y = 0;
4164 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4165 transform_to_geo(projection_mg, &c_screen, &g_screen_lt);
4166
4167 p_screen.x = screen_width;
4168 p_screen.y = 0;
4169 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4170 transform_to_geo(projection_mg, &c_screen, &g_screen_rt);
4171
4172 p_screen.x = screen_width;
4173 p_screen.y = screen_height;
4174 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4175 transform_to_geo(projection_mg, &c_screen, &g_screen_rb);
4176
4177 // dbg(0, "bbox=%f %f %f %f %f %f\n", g_screen_lt.lat, g_screen_lt.lng, g_screen_rt.lat, g_screen_rt.lng, g_screen_rb.lat, g_screen_rb.lng);
4178
4179
4180 if ((display_list->order > 5) || (global_show_maps_debug_view))
4181 {
4182 loop_mapnik_tiles(g_screen_lt.lat, g_screen_lt.lng, g_screen_rt.lat, g_screen_rt.lng, g_screen_rb.lat, g_screen_rb.lng, 12, navit_maps_dir, display_list);
4183 }
4184 /*
4185 else if (display_list->order > 4)
4186 {
4187 loop_mapnik_tiles(g_screen_lt.lat, g_screen_lt.lng, g_screen_rt.lat, g_screen_rt.lng, g_screen_rb.lat, g_screen_rb.lng, 6, navit_maps_dir, display_list);
4188 }
4189 else
4190 {
4191 loop_mapnik_tiles(g_screen_lt.lat, g_screen_lt.lng, g_screen_rt.lat, g_screen_rt.lng, g_screen_rb.lat, g_screen_rb.lng, 2, navit_maps_dir, display_list);
4192 }
4193 */
4194 // MAPNIK -- MVT --
4195 // MAPNIK -- MVT --
4196 // MAPNIK -- MVT --
4197 }
4198 }
4199
4200
4201
4202
4203
4204
4205 lays = l->layers;
4206 while (lays)
4207 {
4208 // stop drawing is requested
4209 if (cancel_drawing_global == 1)
4210 {
4211 break;
4212 }
4213
4214 lay = lays->data;
4215 if (lay->active)
4216 {
4217 //ZZZZZZZZZZZZZZZZZZZZZ//
4218 //ZZZZZZZZZZZZZZZZZZZZZ//
4219 //ZZZZZZZZZZZZZZZZZZZZZ//
4220 //ZZZZZZZZZZZZZZZZZZZZZ//
4221 //ZZZZZZZZZZZZZZZZZZZZZ//
4222 //ZZZZZZZZZZZZZZZZZZZZZ//
4223 //ZZZZZZZZZZZZZZZZZZZZZ//
4224 //ZZZZZZZZZZZZZZZZZZZZZ//
4225 xdisplay_draw_layer(display_list, gra, lay, order);
4226 //ZZZZZZZZZZZZZZZZZZZZZ//
4227 //ZZZZZZZZZZZZZZZZZZZZZ//
4228 //ZZZZZZZZZZZZZZZZZZZZZ//
4229 //ZZZZZZZZZZZZZZZZZZZZZ//
4230 //ZZZZZZZZZZZZZZZZZZZZZ//
4231 //ZZZZZZZZZZZZZZZZZZZZZ//
4232 //ZZZZZZZZZZZZZZZZZZZZZ//
4233 //ZZZZZZZZZZZZZZZZZZZZZ//
4234 }
4235 lays = g_list_next(lays);
4236 }
4237
4238
4239
4240 // reset value;
4241 // cancel_drawing_global = 0;
4242
4243 // dummy "start" signal ------------------------------------------
4244 // // dbg(0, "dummy \"start\" signal\n");
4245 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 97, 0);
4246 // dummy "start" signal ------------------------------------------
4247
4248 __F_END__
4249 }
4250
4251 /**
4252 * FIXME
4253 * @param <>
4254 * @returns <>
4255 * @author Martin Schaller (04/2008)
4256 */
4257 extern void *route_selection;
4258
4259 static void displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
4260 {
4261 ////DBG // dbg(0,"ooo enter ooo\n");
4262
4263 int order_corrected = order + shift_order;
4264 //int saved=displaylist->order;
4265 if (order < limit_order_corrected)
4266 {
4267 order_corrected = limit_order_corrected;
4268 // displaylist->order=0;
4269 }
4270
4271 while (layers)
4272 {
4273 struct layer *layer = layers->data;
4274 GList *itemgras = layer->itemgras;
4275 while (itemgras)
4276 {
4277 struct itemgra *itemgra = itemgras->data;
4278 GList *types = itemgra->type;
4279 if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
4280 {
4281 while (types)
4282 {
4283 enum item_type type = (enum item_type) types->data;
4284 set_hash_entry(displaylist, type);
4285 types = g_list_next(types);
4286 }
4287 }
4288 itemgras = g_list_next(itemgras);
4289 }
4290 layers = g_list_next(layers);
4291 }
4292 // displaylist->order=saved;
4293 }
4294
4295 static void displaylist_update_hash(struct displaylist *displaylist)
4296 {
4297 ////DBG // dbg(0,"ooo enter ooo\n");
4298
4299 displaylist->max_offset = 0;
4300 clear_hash(displaylist);
4301 displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
4302 // dbg(1, "max offset %d\n", displaylist->max_offset);
4303 }
4304
4305 static void do_draw(struct displaylist *displaylist, int cancel, int flags)
4306 {
4307
4308 __F_START__
4309
4310 // int rnd = rand();
4311 // dbg(0, "DO__DRAW:%d enter\n", rnd);
4312
4313 // try to cancel any previous drawing that might be going on ...
4314 // try to cancel any previous drawing that might be going on ...
4315 // try to cancel any previous drawing that might be going on ...
4316 // dbg(0, "DO__DRAW:%d cancel_drawing_global 1=%d\n", rnd, cancel_drawing_global);
4317 cancel_drawing_global = 1;
4318 // dbg(0, "DO__DRAW:%d cancel_drawing_global 2=%d\n", rnd, cancel_drawing_global);
4319 // try to cancel any previous drawing that might be going on ...
4320 // try to cancel any previous drawing that might be going on ...
4321 // try to cancel any previous drawing that might be going on ...
4322
4323
4324 // dbg(0, "DO__DRAW:%d lock mutex\n", rnd);
4325 pthread_mutex_lock(&uiConditionMutex);
4326 // dbg(0, "DO__DRAW:%d OK lock mutex\n", rnd);
4327
4328 // drawing is now starting ...
4329 // drawing is now starting ...
4330 // drawing is now starting ...
4331 // dbg(0, "DO__DRAW:%d cancel_drawing_global 3=%d\n", rnd, cancel_drawing_global);
4332 cancel_drawing_global = 0;
4333 // dbg(0, "DO__DRAW:%d cancel_drawing_global 4=%d\n", rnd, cancel_drawing_global);
4334 // drawing is now starting ...
4335 // drawing is now starting ...
4336 // drawing is now starting ...
4337
4338
4339 #ifdef HAVE_API_ANDROID
4340 // ---- disable map view -----
4341 // ---- disable map view -----
4342 // ---- disable map view -----
4343 if (disable_map_drawing == 1)
4344 {
4345 //android_return_generic_int(2, 0);
4346
4347 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4348 displaylist->busy = 0;
4349
4350 // dbg(0,"DO__DRAW:%d UN-lock mutex 001\n", rnd);
4351 pthread_mutex_unlock(&uiConditionMutex);
4352 // dbg(0,"DO__DRAW:%d OK UN-lock mutex 001\n", rnd);
4353
4354 // dbg(0,"DO__DRAW:%d return 001\n", rnd);
4355 return2;
4356 }
4357 // ---- disable map view -----
4358 // ---- disable map view -----
4359 // ---- disable map view -----
4360 #endif
4361
4362 clock_t s_;
4363 #ifdef NAVIT_MEASURE_TIME_DEBUG
4364 s_ = debug_measure_start();
4365 #endif
4366
4367 struct item *item;
4368 int count, max = displaylist->dc.maxlen, workload = 0;
4369 struct coord *ca = g_alloca(sizeof(struct coord) * max);
4370 struct attr attr, attr2;
4371 enum projection pro;
4372 int draw_vector_map = 1; // do we draw the vecotor map, or not? 0=false, 1=true
4373 int draw_tile_map = 1; // do we draw the prerendered tile map? 0=false, 1=true
4374 int mapset_counter = 0;
4375 int mapset_need_draw = 0;
4376 int only_labels = 0;
4377
4378 // int r_, g_, b_, a_;
4379 unsigned int col_int_value;
4380 struct attr attr_cc;
4381
4382 // // dbg(0,"ooo enter ooo %d\n",displaylist->order);
4383
4384 int order_corrected = displaylist->order + shift_order;
4385 int saved = displaylist->order;
4386 if (order_corrected < limit_order_corrected)
4387 {
4388 order_corrected = limit_order_corrected;
4389 }
4390
4391 if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
4392 {
4393 displaylist_update_hash(displaylist);
4394 displaylist->order_hashed = displaylist->order;
4395 displaylist->layout_hashed = displaylist->layout;
4396 }
4397
4398 pro = transform_get_projection(displaylist->dc.trans);
4399
4400 // if zoomed out too much then use prerendered map tiles
4401 if (global_clinedrawing_active)
4402 {
4403 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP__C)
4404 {
4405 draw_vector_map = 0;
4406 }
4407
4408 if (displaylist->order_hashed > ORDER_USE_NORMAL_MAP__C)
4409 {
4410 draw_tile_map = 0;
4411 }
4412 }
4413 else
4414 {
4415 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP) // ==5 , (4,3,2,1,0)--> no vector map
4416 {
4417 draw_vector_map = 0;
4418 }
4419
4420 if (displaylist->order_hashed > ORDER_USE_NORMAL_MAP) // ==6 , (7,8,9, ...)--> no tile map
4421 {
4422 draw_tile_map = 0;
4423 }
4424 }
4425
4426 if (global_show_maps_debug_view)
4427 {
4428 draw_vector_map = 1;
4429 draw_tile_map = 0;
4430 }
4431
4432 displaylist->order = order_corrected;
4433
4434 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 003\n");
4435
4436 // reset value;
4437 // cancel_drawing_global = 0;
4438
4439 char *ttt22 = NULL;
4440
4441
4442 while (!cancel)
4443 {
4444 if (!displaylist->msh)
4445 {
4446 displaylist->msh = mapset_open(displaylist->ms);
4447 }
4448
4449 if (!displaylist->m)
4450 {
4451 displaylist->m = mapset_next(displaylist->msh, 1);
4452 if (!displaylist->m)
4453 {
4454 mapset_close(displaylist->msh);
4455 displaylist->msh = NULL;
4456 break;
4457 }
4458
4459 mapset_counter++;
4460 mapset_need_draw = 1;
4461 only_labels = 0;
4462
4463 struct attr map_name_attr;
4464
4465 if (map_get_attr(displaylist->m, attr_name, &map_name_attr, NULL))
4466 {
4467 // dbg(0,"MAP:#+* start reading map file #+*=%s\n", map_name_attr.u.str);
4468 if (ttt22)
4469 {
4470 g_free(ttt22);
4471 }
4472 ttt22 = g_strdup(map_name_attr.u.str);
4473
4474 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
4475 {
4476 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
4477 {
4478 if (draw_tile_map == 1)
4479 {
4480 // if its the countryborder map
4481 mapset_need_draw = 0;
4482 }
4483 else if (displaylist->order_hashed >= ORDER_USE_BORDERS_MAP)
4484 {
4485 // on high detail -> dont draw bordermap anymore. it sometimes causes heavy slowdowns!!
4486 mapset_need_draw = 0;
4487 }
4488 }
4489
4490 /*
4491 else if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/coastline.bin", map_name_attr.u.str, 48) == 0)
4492 {
4493 if (draw_tile_map == 1)
4494 {
4495 // if its the countryborder map
4496 mapset_need_draw = 0;
4497 }
4498 }
4499 */
4500
4501
4502 #if 0
4503 else if (strncmp("_ms_sdcard_map:-special-:worldmap6.txt", map_name_attr.u.str, 38) == 0)
4504 {
4505 // if its a worldmapX.txt
4506 if (draw_vector_map == 1)
4507 {
4508 //dbg(0, "wm5: v=1");
4509 mapset_need_draw = 0;
4510 }
4511 else
4512 {
4513 //dbg(0, "wm5: v=0");
4514
4515 if (displaylist->order_hashed < 4)
4516 {
4517 //dbg(0, "wm5: nd=0");
4518 mapset_need_draw = 0;
4519 }
4520 else
4521 {
4522 //dbg(0, "wm5: nd=1");
4523 mapset_need_draw = 1;
4524 }
4525 }
4526 }
4527 #endif
4528 else if (strncmp("_ms_sdcard_map:-special-:worldmap5.txt", map_name_attr.u.str, 38) == 0)
4529 {
4530 // if its a worldmapX.txt
4531 if (draw_tile_map == 0)
4532 {
4533 mapset_need_draw = 0;
4534 }
4535 else
4536 {
4537 if (displaylist->order_hashed < 3)
4538 {
4539 mapset_need_draw = 0;
4540 }
4541 else
4542 {
4543 mapset_need_draw = 1;
4544 }
4545 }
4546 }
4547 else if (strncmp("_ms_sdcard_map:-special-:worldmap2.txt", map_name_attr.u.str, 38) == 0)
4548 {
4549 // if its a worldmapX.txt
4550 if (draw_tile_map == 0)
4551 {
4552 mapset_need_draw = 0;
4553 }
4554 else
4555 {
4556 if (displaylist->order_hashed < 3)
4557 {
4558 mapset_need_draw = 1;
4559 }
4560 else
4561 {
4562 mapset_need_draw = 0;
4563 }
4564 }
4565 }
4566 else
4567 {
4568 // if its an sdcard street map
4569 if (draw_vector_map == 1)
4570 {
4571 mapset_need_draw = 1;
4572 if (draw_tile_map == 1)
4573 {
4574 only_labels = 1;
4575 }
4576 }
4577 else
4578 {
4579 mapset_need_draw = 0;
4580 }
4581 }
4582 }
4583 }
4584
4585 ////DBG // dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
4586
4587 displaylist->dc.pro = map_projection(displaylist->m);
4588 displaylist->conv = map_requires_conversion(displaylist->m);
4589 if (route_selection)
4590 {
4591 displaylist->sel = route_selection;
4592 }
4593 else
4594 {
4595 displaylist->sel = transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
4596 }
4597 displaylist->mr = map_rect_new(displaylist->m, displaylist->sel);
4598 }
4599
4600
4601 if (displaylist->mr)
4602 {
4603 // dbg(0,"MAP:001:map=%s\n", ttt22);
4604 // draw vector map, or not?
4605 // dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
4606 // ****** if ((draw_vector_map) || (mapset_need_draw == 1))
4607 if (mapset_need_draw == 1)
4608 {
4609 //dbg(0,"MAP:002:map=%s\n", ttt22);
4610
4611 //// dbg(0, "XXXXXYYYYYYY Draw: A.01\n");
4612
4613
4614 // ------ READ all items in this map rectangle ---------
4615 // ------ READ all items in this map rectangle ---------
4616 // ------ READ all items in this map rectangle ---------
4617 // ------ READ all items in this map rectangle ---------
4618 // ------ READ all items in this map rectangle ---------
4619 // dbg(0,"#+* start reading map file #+*\n");
4620 int _item_counter_ = 0;
4621 while ((item = map_rect_get_item(displaylist->mr)))
4622 {
4623 //dbg(0,"MAP:003:map=%s\n", ttt22);
4624
4625 _item_counter_++;
4626
4627 int label_count = 0;
4628 char *labels[3];
4629 struct hash_entry *entry;
4630
4631 if (cancel_drawing_global == 1)
4632 {
4633 // stop drawing map is requested
4634 //DBG // dbg(0, "** STOP MD 001 **\n");
4635 break;
4636 }
4637
4638 if (item == &busy_item)
4639 {
4640 if (displaylist->workload)
4641 {
4642 // restore order :-)
4643 displaylist->order = saved;
4644
4645 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4646 displaylist->busy = 0;
4647
4648 // dbg(0, "DO__DRAW:%d UN-lock mutex 002\n", rnd);
4649 pthread_mutex_unlock(&uiConditionMutex);
4650 // dbg(0, "DO__DRAW:%d OK UN-lock mutex 002\n", rnd);
4651
4652 //// dbg(0,"return 002\n");
4653 // dbg(0, "DO__DRAW:%d return 002\n", rnd);
4654 return2;
4655 }
4656 else
4657 {
4658 continue;
4659 }
4660 }
4661
4662 if (only_labels == 1)
4663 {
4664 if ((!item_is_town(*item)) && (!item_is_district(*item)))
4665 {
4666 // if its not a label, dont draw it
4667 continue;
4668 }
4669 }
4670
4671 entry = get_hash_entry(displaylist, item->type);
4672
4673 //// dbg(0, "XXXXXYYYYYYY Draw: A.item1 %p %i\n", entry, item->type);
4674
4675 // DEBUG -------- zoffzoff
4676 // DEBUG -------- zoffzoff
4677 // DEBUG -------- zoffzoff
4678 //item_dump_attr_stdout(item, displaylist->m);
4679 // DEBUG -------- zoffzoff
4680 // DEBUG -------- zoffzoff
4681 // DEBUG -------- zoffzoff
4682
4683 if (!entry)
4684 {
4685 continue;
4686 }
4687
4688 count = item_coord_get_within_selection(item, ca, item->type < type_line ? 1 : max, displaylist->sel);
4689
4690 if (!count)
4691 {
4692 continue;
4693 }
4694
4695 //dbg(0,"MAP:004:map=%s\n", ttt22);
4696
4697 //// dbg(0, "XXXXXYYYYYYY Draw: A.item2\n");
4698
4699 if (displaylist->dc.pro != pro)
4700 {
4701 //dbg(0,"from to\n");
4702 transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
4703 }
4704
4705 if (count == max)
4706 {
4707 //DBG // dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
4708 displaylist->dc.maxlen = max * 2;
4709 }
4710
4711 //if (item_is_custom_poi(*item))
4712 //{
4713 // if (item_attr_get(item, attr_icon_src, &attr2))
4714 // {
4715 // labels[1] = map_convert_string(displaylist->m, attr2.u.str);
4716 // }
4717 // else
4718 // {
4719 // labels[1] = NULL;
4720 // }
4721 // label_count = 2;
4722 //}
4723 //else
4724 //{
4725 labels[0] = NULL;
4726 labels[1] = NULL;
4727 labels[2] = NULL;
4728 label_count = 0;
4729 //}
4730
4731 // DEBUG -------- zoffzoff
4732 // DEBUG -------- zoffzoff
4733 // DEBUG -------- zoffzoff
4734 // item_dump_attr_stdout(item, displaylist->m);
4735 // DEBUG -------- zoffzoff
4736 // DEBUG -------- zoffzoff
4737 // DEBUG -------- zoffzoff
4738
4739
4740
4741
4742
4743
4744 // --------======== LABELS ========--------
4745 // --------======== LABELS ========--------
4746 if (item_attr_get(item, attr_label, &attr))
4747 {
4748 if (global_show_english_labels < 2)
4749 {
4750 // NORMAL
4751 //dbg(0, "c:%d name=%s\n", label_count, attr.u.str);
4752 labels[label_count] = attr.u.str;
4753 label_count++;
4754 }
4755 }
4756
4757 if (item_attr_get(item, attr_street_name_match, &attr))
4758 {
4759 if ((global_show_english_labels == 1)||(global_show_english_labels == 2))
4760 {
4761 // ENGLISH or alternate
4762 //dbg(0, "c:%d street_en_name=%s\n", label_count, attr.u.str);
4763 labels[label_count] = attr.u.str;
4764 label_count++;
4765 }
4766 }
4767 else if (item_attr_get(item, attr_town_name_match, &attr))
4768 {
4769 if ((global_show_english_labels == 1)||(global_show_english_labels == 2))
4770 {
4771 // ENGLISH or alternate
4772 //dbg(0, "c:%d town_en_name=%s\n", label_count, attr.u.str);
4773 labels[label_count] = attr.u.str;
4774 label_count++;
4775 }
4776 }
4777 else
4778 {
4779 if (global_show_english_labels == 2)
4780 {
4781 // we want ENGLISH labels, but the item does not have it
4782 // --> so show normal label instead (item should not be nameless on map)
4783 if (item_attr_get(item, attr_label, &attr))
4784 {
4785 // NORMAL
4786 //dbg(0, "c:%d name=%s\n", label_count, attr.u.str);
4787 labels[label_count] = attr.u.str;
4788 label_count++;
4789 }
4790 }
4791 }
4792 // --------======== LABELS ========--------
4793 // --------======== LABELS ========--------
4794
4795
4796
4797
4798
4799
4800 // DEBUG -------- zoffzoff
4801 // DEBUG -------- zoffzoff
4802 // DEBUG -------- zoffzoff
4803 // item_dump_attr_stdout(item, displaylist->m);
4804 // DEBUG -------- zoffzoff
4805 // DEBUG -------- zoffzoff
4806 // DEBUG -------- zoffzoff
4807
4808 struct attr attr_77;
4809 if (item_attr_get(item, attr_flags, &attr_77))
4810 {
4811 // // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
4812 item->flags = attr_77.u.num;
4813 }
4814 else
4815 {
4816 item->flags = 0;
4817 }
4818
4819 //struct attr *attr88;
4820 //if (item_attr_get(item, attr_flags, &attr88))
4821 //{
4822 ////DBG // dbg(0,"item flags=%d\n",attr88->u.num);
4823 //}
4824 //attr88=NULL;
4825
4826
4827 /*
4828 if (item->flags & NAVIT_AF_UNDERGROUND)
4829 {
4830 // dbg(0,"is UNDERGROUND\n");
4831 }
4832 else if (item->flags & NAVIT_AF_BRIDGE)
4833 {
4834 // dbg(0,"is BRIDGE\n");
4835 }
4836 */
4837
4838 // a_=0;
4839 if (item_attr_get(item, attr_colour2, &attr_cc))
4840 {
4841
4842 col_int_value = (unsigned int)attr_cc.u.num;
4843 //dbg(0, "ccooll:1 c=%d\n", col_int_value);
4844
4845 //r_= (col_int_value >> 16) & 0xff;
4846 //g_= (col_int_value >> 8) & 0xff;
4847 //b_= col_int_value & 0xff;
4848
4849 //dbg(0, "ccooll:2 r=%d g=%d b=%d\n", r_,g_,b_);
4850
4851 //r_ = r_ << 8;
4852 //g_ = g_ << 8;
4853 //b_ = b_ << 8;
4854
4855 //dbg(0, "ccooll:3 r=%d g=%d b=%d\n", r_,g_,b_);
4856
4857 //a_ = 0xffff;
4858 }
4859 else
4860 {
4861 col_int_value = 0;
4862 }
4863
4864
4865 struct attr attr_88;
4866 if ((item->type == type_street_route) || (item->type == type_street_route_waypoint))
4867 {
4868 if (item_attr_get(item, attr_direction, &attr_88))
4869 {
4870 //dbg(0, "direction(1a1)=%d %x\n", attr_88.u.num, col_int_value);
4871 col_int_value = col_int_value & 0xffffff;
4872 //dbg(0, "direction(1a2)=%x %x\n", attr_88.u.num, col_int_value);
4873 //dbg(0, "direction(1a2.1)=%x %x\n", (attr_88.u.num & 3), ((attr_88.u.num & 3) << 24));
4874 col_int_value = col_int_value | ((attr_88.u.num & 3) << 24);
4875 //dbg(0, "direction(1a3)=%x %x\n", attr_88.u.num, col_int_value);
4876 }
4877 else
4878 {
4879 //dbg(0, "direction(1b1)=%x\n", col_int_value);
4880 col_int_value = col_int_value & 0xffffff;
4881 //dbg(0, "direction(1b2)=%x\n", col_int_value);
4882 }
4883
4884 if (item_attr_get(item, attr_details, &attr_88))
4885 {
4886 // dbg(0, "direction(0)=%x\n", attr_88.u.num);
4887
4888 // #define NAVIT_AF_ONEWAY (1<<0)
4889 // #define NAVIT_AF_ONEWAYREV (1<<1)
4890 // #define NAVIT_AF_ONEWAY_BICYCLE_NO (1<<16)
4891
4892 if (attr_88.u.num & NAVIT_AF_ONEWAY_BICYCLE_NO)
4893 {
4894 // dbg(0, "direction(0)=%x\n", (attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)));
4895 // dbg(0, "direction(0.1)=%x %x\n", col_int_value, (attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)) << 26 );
4896 col_int_value = col_int_value | ((attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)) << 26);
4897 }
4898 }
4899 }
4900
4901
4902 // --------======== LABELS ========--------
4903 // --------======== LABELS ========--------
4904 if (label_count > 0)
4905 {
4906 labels[0] = map_convert_string(displaylist->m, labels[0]);
4907 }
4908 if (label_count > 1)
4909 {
4910 labels[1] = map_convert_string(displaylist->m, labels[1]);
4911 }
4912 display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4913 if (label_count > 0)
4914 {
4915 map_convert_free(labels[0]);
4916 }
4917 if (label_count > 1)
4918 {
4919 map_convert_free(labels[1]);
4920 }
4921
4922 //if (displaylist->conv && label_count)
4923 //{
4924 // labels[0] = map_convert_string(displaylist->m, labels[0]);
4925 // display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4926 // map_convert_free(labels[0]);
4927 //}
4928 //else
4929 //{
4930 // display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4931 //}
4932 //if (labels[1])
4933 //{
4934 // map_convert_free(labels[1]);
4935 //}
4936 // --------======== LABELS ========--------
4937 // --------======== LABELS ========--------
4938
4939
4940 //workload++;
4941 /*
4942 if (workload == displaylist->workload)
4943 {
4944 // restore order :-)
4945 displaylist->order = saved;
4946 // reset value;
4947 cancel_drawing_global = 0;
4948
4949 // dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4950 displaylist->busy = 0;
4951
4952 // dbg(0,"return 003\n");
4953 return2;
4954 }
4955 */
4956
4957 } // while item=map_rect_get_item
4958 // ------ READ all items in this map rectangle ---------
4959 // ------ READ all items in this map rectangle ---------
4960 // ------ READ all items in this map rectangle ---------
4961 // ------ READ all items in this map rectangle ---------
4962 // ------ READ all items in this map rectangle ---------
4963
4964 //dbg(0,"MAP:013:map=%s\n", ttt22);
4965
4966 ////DBG // dbg(0, "XXXXXYYYYYYY Draw: A.02\n");
4967
4968 // ************** map_rect_destroy(displaylist->mr);
4969 }
4970
4971 map_rect_destroy(displaylist->mr);
4972 }
4973
4974
4975 if (!route_selection)
4976 {
4977 map_selection_destroy(displaylist->sel);
4978 }
4979
4980 displaylist->mr = NULL;
4981 displaylist->sel = NULL;
4982 displaylist->m = NULL;
4983 } // while ----
4984
4985
4986 // dbg(0, "DO__DRAW:%d load ready\n", rnd);
4987
4988 #ifdef NAVIT_MEASURE_TIME_DEBUG
4989 debug_mrp("do_draw:load", debug_measure_end(s_));
4990 #endif
4991 s_ = debug_measure_start();
4992
4993
4994
4995 // dbg(0, "DO__DRAW:%d dummy \"draw-start\" signal\n", rnd);
4996 #ifdef HAVE_API_ANDROID
4997 android_return_generic_int(2, 77);
4998 #endif
4999
5000 // remove the "wait" screen
5001 //#ifdef HAVE_API_ANDROID
5002 // android_return_generic_int(2, 0);
5003 //#endif
5004
5005 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 004\n");
5006
5007 // reset value;
5008 // cancel_drawing_global = 0;
5009
5010 // restore order :-)
5011 displaylist->order = saved;
5012
5013 // profile(1,"process_selection\n");
5014
5015
5016 if (displaylist->idle_ev)
5017 {
5018 event_remove_idle(displaylist->idle_ev);
5019 displaylist->idle_ev = NULL;
5020 }
5021
5022 if (displaylist->idle_cb)
5023 {
5024 callback_destroy(displaylist->idle_cb);
5025 displaylist->idle_cb = NULL;
5026 }
5027
5028 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
5029 //displaylist->busy = 0;
5030
5031 // graphics_process_selection(displaylist->dc.gra, displaylist);
5032
5033 //profile(1, "draw\n");
5034
5035 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 005\n");
5036
5037 if (!cancel)
5038 {
5039 int flags2 = flags;
5040 if (!(flags2 & 2))
5041 {
5042 // -- now always clean bg of screen!! 2013-07-08 Zoff
5043 //if (!draw_vector_map)
5044 //{
5045 // // dont clean bg of screen when drawing prerendered tiles
5046 // flags2 = flags2 + 2;
5047 //}
5048 }
5049 //DBG // dbg(0,"call graphics_displaylist_draw 3")
5050 //// dbg(0,"# MT:002 #\n");
5051
5052 // stop drawing is requested
5053 if (cancel_drawing_global != 1)
5054 {
5055 graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
5056 }
5057 //// dbg(0,"# MT:003 #\n");
5058 }
5059
5060 #ifdef NAVIT_MEASURE_TIME_DEBUG
5061 debug_mrp("do_draw:draw", debug_measure_end(s_));
5062 #endif
5063
5064 // dbg(0, "DO__DRAW:%d draw ready\n", rnd);
5065
5066 #ifdef HAVE_API_ANDROID
5067 if (cur_mapdraw_time_index < 11)
5068 {
5069 mapdraw_time[cur_mapdraw_time_index] = debug_measure_end_tsecs(s_);
5070 // // dbg(0,"maptime: %d\n", mapdraw_time[cur_mapdraw_time_index]);
5071 cur_mapdraw_time_index++;
5072 }
5073
5074 if (cur_mapdraw_time_index > 10)
5075 {
5076 cur_mapdraw_time_index = 0;
5077 int jk;
5078 int mean_time = 0;
5079 for (jk=0;jk<11;jk++)
5080 {
5081 mean_time = mean_time + mapdraw_time[jk];
5082 }
5083 android_return_generic_int(6, (int)((float)mean_time / (float)10));
5084 }
5085 #endif
5086
5087 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
5088 displaylist->busy = 0;
5089
5090 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 006\n");
5091
5092 map_rect_destroy(displaylist->mr);
5093 if (!route_selection)
5094 {
5095 map_selection_destroy(displaylist->sel);
5096 }
5097 mapset_close(displaylist->msh);
5098 displaylist->mr = NULL;
5099 displaylist->sel = NULL;
5100 displaylist->m = NULL;
5101 displaylist->msh = NULL;
5102
5103 //dbg(0, "callback\n");
5104
5105 // only some old crap need this!! ----------
5106 // only some old crap need this!! ----------
5107 /// **** callback_call_1(displaylist->cb, cancel);
5108 // only some old crap need this!! ----------
5109 // only some old crap need this!! ----------
5110
5111
5112 // dbg(0, "DO__DRAW:%d UN-lock mutex leave\n", rnd);
5113 pthread_mutex_unlock(&uiConditionMutex);
5114 // dbg(0, "DO__DRAW:%d OK UN-lock mutex leave\n", rnd);
5115
5116 // dbg(0, "DO__DRAW:%d cancel_drawing_global 99=%d\n", rnd, cancel_drawing_global);
5117
5118 if (cancel_drawing_global != 1)
5119 {
5120 // dummy "ready" signal ------------------------------------------
5121 // dbg(0, "DO__DRAW:%d dummy \"ready\" signal\n", rnd);
5122 // gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 99);
5123 #ifdef HAVE_API_ANDROID
5124 android_return_generic_int(2, 2);
5125 #endif
5126 // dummy "ready" signal ------------------------------------------
5127 }
5128 else
5129 {
5130 // dummy "cancel" signal ------------------------------------------
5131 // dbg(0, "DO__DRAW:%d dummy \"cancel\" signal\n", rnd);
5132 //gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 95);
5133 #ifdef HAVE_API_ANDROID
5134 android_return_generic_int(2, 3);
5135 #endif
5136 // dummy "ready" signal ------------------------------------------
5137 }
5138
5139 // dbg(0, "DO__DRAW:%d leave\n", rnd);
5140 // dbg(0, "DO__DRAW:%d __\n", rnd);
5141
5142 __F_END__
5143 }
5144
5145 /**
5146 * FIXME
5147 * @param <>
5148 * @returns <>
5149 * @author Martin Schaller (04/2008)
5150 */
5151 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
5152 {
5153 __F_START__
5154
5155 // // dbg(0,"ooo enter ooo flags=%d\n", flags);
5156
5157
5158 int order = transform_get_order(trans);
5159 displaylist->dc.trans = trans;
5160 displaylist->dc.gra = gra;
5161
5162 // *********DISABLED*******
5163 // *********DISABLED*******
5164 // *********DISABLED*******
5165 // set min. distancte of 2 points on line at which a point will be left out when zoomed out too much!!
5166 // *********DISABLED******* displaylist->dc.mindist = transform_get_scale(trans) / 2;
5167 //// dbg(0,"mindist would be:%d\n", (int)(transform_get_scale(trans) / 2));
5168 displaylist->dc.mindist = 0;
5169 if (order < 6)
5170 {
5171 displaylist->dc.mindist = transform_get_scale(trans) * 4;
5172 }
5173 else if (order < 9)
5174 {
5175 displaylist->dc.mindist = transform_get_scale(trans) * 3;
5176 }
5177 else if (order < 13)
5178 {
5179 displaylist->dc.mindist = transform_get_scale(trans) * 2;
5180 }
5181 // *********DISABLED*******
5182 // *********DISABLED*******
5183 // *********DISABLED*******
5184
5185
5186 // FIXME find a better place to set the background color
5187 if (l)
5188 {
5189
5190 if (global_night_mode == 1)
5191 {
5192 graphics_gc_set_background(gra->gc[0], &background_night_mode);
5193 graphics_gc_set_foreground(gra->gc[0], &background_night_mode);
5194 }
5195 else
5196 {
5197 graphics_gc_set_background(gra->gc[0], &l->color);
5198 graphics_gc_set_foreground(gra->gc[0], &l->color);
5199 }
5200 gra->default_font = g_strdup(l->font);
5201 }
5202
5203 graphics_background_gc(gra, gra->gc[0]);
5204
5205 if (flags & 1)
5206 {
5207 // calls -> navit.c navit_predraw --> draw all vehicles
5208 // *********++-- DISABLED --++******* // callback_list_call_attr_0(gra->cbl, attr_predraw);
5209 navit_predraw(global_navit);
5210 }
5211
5212 gra->meth.draw_mode(gra->priv, (flags & 8) ? draw_mode_begin_clear : draw_mode_begin);
5213
5214 if (!(flags & 2))
5215 {
5216 // clear the gfx object pipeline ------------------------------
5217 // // dbg(0, "clear the gfx object pipeline\n");
5218 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 98);
5219
5220 // clear the display/screen/whatever here
5221 // dbg(0, "clear the screen: rectangle=%d,%d - %d,%d\n", gra->r.lu.x, gra->r.lu.y, gra->r.rl.x, gra->r.rl.y);
5222 gra->meth.draw_rectangle(gra->priv, gra->gc[0]->priv, &gra->r.lu, gra->r.rl.x - gra->r.lu.x, gra->r.rl.y - gra->r.lu.y);
5223 }
5224
5225 if (l)
5226 {
5227 // draw the mapitems
5228 // // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
5229 xdisplay_draw(displaylist, gra, l, order + l->order_delta);
5230 }
5231
5232 if (flags & 1)
5233 {
5234 // calls: "graphics_displaylist_draw"
5235 // ***********++-- DISABLED --++*********** // callback_list_call_attr_0(gra->cbl, attr_postdraw);
5236 }
5237
5238 if (!(flags & 4))
5239 {
5240 gra->meth.draw_mode(gra->priv, draw_mode_end);
5241 }
5242
5243 __F_END__
5244 }
5245
5246 static void graphics_load_mapset(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags)
5247 {
5248 __F_START__
5249
5250 int order = transform_get_order(trans);
5251
5252 if (displaylist->busy)
5253 {
5254 if (async == 1)
5255 {
5256 return2;
5257 }
5258 return2;
5259 }
5260 xdisplay_free(displaylist);
5261
5262 displaylist->dc.gra = gra;
5263 displaylist->ms = mapset;
5264 displaylist->dc.trans = trans;
5265 displaylist->workload = async ? 100 : 0;
5266 displaylist->cb = cb;
5267 displaylist->seq++;
5268
5269 if (l)
5270 {
5271 order += l->order_delta;
5272 }
5273 displaylist->order = order;
5274 displaylist->busy = 1;
5275 displaylist->layout = l;
5276
5277 // ---------- DISABLED ------ no more async!!
5278 /*
5279 if (async)
5280 {
5281 //DBG // dbg(0,"§§async");
5282 if (!displaylist->idle_cb)
5283 {
5284 //DBG // dbg(0,"§§async --> callback");
5285 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
5286 }
5287 //DBG // dbg(0,"§§async --> add idle");
5288 displaylist->idle_ev = event_add_idle(50, displaylist->idle_cb);
5289 }
5290 else
5291 {
5292 //DBG // dbg(0,"@@sync");
5293 do_draw(displaylist, 0, flags);
5294 }
5295 */
5296
5297 if (async)
5298 {
5299 //if (!displaylist->idle_cb)
5300 //{
5301 // this calls "do_draw"
5302 // *++*-- DISABLED --*++* // displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
5303 // *++*-- DISABLED --*++* // callback_add_names(displaylist->idle_cb, "graphics_load_mapset", "do_draw");
5304 do_draw(displaylist, 0, flags);
5305 //}
5306 //dbg(0, "DO__DRAW:call 003 (async callback)\n");
5307 // *++*-- DISABLED --*++* // displaylist->idle_ev = event_add_idle(1000, displaylist->idle_cb);
5308 }
5309 else
5310 {
5311 //// dbg(0,"**draw 2.b5\n");
5312 // dbg(0, "DO__DRAW:call 001\n");
5313 do_draw(displaylist, 0, flags);
5314 }
5315
5316 __F_END__
5317 }
5318
5319 /**
5320 * FIXME
5321 * @param <>
5322 * @returns <>
5323 * @author Martin Schaller (04/2008)
5324 */
5325 void graphics_draw(struct graphics *gra, struct displaylist *displaylist, struct mapset *mapset, struct transformation *trans, struct layout *l, int async, struct callback *cb, int flags)
5326 {
5327 __F_START__
5328 //// dbg(0,"ooo enter ooo\n");
5329
5330 // dbg(0, "DO__DRAW:gras_draw enter\n");
5331 graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
5332 // dbg(0, "DO__DRAW:gras_draw leave\n");
5333 __F_END__
5334 }
5335
5336 int graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
5337 {
5338 __F_START__
5339
5340 if (!displaylist->busy)
5341 {
5342 return2 0;
5343 }
5344 // dbg(0, "DO__DRAW:call 002\n");
5345 do_draw(displaylist, 1, 0);
5346 return2 1;
5347
5348 __F_END__
5349 }
5350
5351 /**
5352 * FIXME
5353 * @param <>
5354 * @returns <>
5355 * @author Martin Schaller (04/2008)
5356 */
5357 struct displaylist_handle
5358 {
5359 struct displaylist *dl;
5360 struct displayitem *di;
5361 int hashidx;
5362 };
5363
5364 /**
5365 * FIXME
5366 * @param <>
5367 * @returns <>
5368 * @author Martin Schaller (04/2008)
5369 */
5370 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
5371 {
5372 struct displaylist_handle *ret;
5373
5374 ret=g_new0(struct displaylist_handle, 1);
5375 ret->dl = displaylist;
5376
5377 return ret;
5378 }
5379
5380 /**
5381 * FIXME
5382 * @param <>
5383 * @returns <>
5384 * @author Martin Schaller (04/2008)
5385 */
5386 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
5387 {
5388 struct displayitem *ret;
5389 if (!dlh)
5390 return NULL;
5391 for (;;)
5392 {
5393 if (dlh->di)
5394 {
5395 ret = dlh->di;
5396 dlh->di = ret->next;
5397 break;
5398 }
5399 if (dlh->hashidx == HASH_SIZE_GRAPHICS_)
5400 {
5401 ret = NULL;
5402 break;
5403 }
5404 if (dlh->dl->hash_entries[dlh->hashidx].type)
5405 dlh->di = dlh->dl->hash_entries[dlh->hashidx].di;
5406 dlh->hashidx++;
5407 }
5408 return ret;
5409 }
5410
5411 /**
5412 * FIXME
5413 * @param <>
5414 * @returns <>
5415 * @author Martin Schaller (04/2008)
5416 */
5417 void graphics_displaylist_close(struct displaylist_handle *dlh)
5418 {
5419 g_free(dlh);
5420 }
5421
5422 /**
5423 * FIXME
5424 * @param <>
5425 * @returns <>
5426 * @author Martin Schaller (04/2008)
5427 */
5428 struct displaylist * graphics_displaylist_new(void)
5429 {
5430 struct displaylist *ret=g_new0(struct displaylist, 1);
5431
5432 ret->dc.maxlen = 16384;
5433 ret->busy = 0;
5434
5435 return ret;
5436 }
5437
5438 /**
5439 * FIXME
5440 * @param <>
5441 * @returns <>
5442 * @author Martin Schaller (04/2008)
5443 */
5444 struct item * graphics_displayitem_get_item(struct displayitem *di)
5445 {
5446 return &di->item;
5447 }
5448
5449 int graphics_displayitem_get_coord_count(struct displayitem *di)
5450 {
5451 return di->count;
5452 }
5453
5454 /**
5455 * FIXME
5456 * @param <>
5457 * @returns <>
5458 * @author Martin Schaller (04/2008)
5459 */
5460 char * graphics_displayitem_get_label(struct displayitem *di)
5461 {
5462 return di->label;
5463 }
5464
5465 int graphics_displayitem_get_displayed(struct displayitem *di)
5466 {
5467 return 1;
5468 }
5469
5470 /**
5471 * FIXME
5472 * @param <>
5473 * @returns <>
5474 * @author Martin Schaller (04/2008)
5475 */
5476 static int within_dist_point(struct point *p0, struct point *p1, int dist)
5477 {
5478 if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
5479 return 0;
5480 if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
5481 return 0;
5482 if ((p0->x - p1->x) * (p0->x - p1->x) + (p0->y - p1->y) * (p0->y - p1->y) <= dist * dist)
5483 {
5484 return 1;
5485 }
5486 return 0;
5487 }
5488
5489 /**
5490 * FIXME
5491 * @param <>
5492 * @returns <>
5493 * @author Martin Schaller (04/2008)
5494 */
5495 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
5496 {
5497 int vx, vy, wx, wy;
5498 int c1, c2;
5499 struct point line_p;
5500
5501 if (line_p0->x < line_p1->x)
5502 {
5503 if (p->x < line_p0->x - dist)
5504 return 0;
5505 if (p->x > line_p1->x + dist)
5506 return 0;
5507 }
5508 else
5509 {
5510 if (p->x < line_p1->x - dist)
5511 return 0;
5512 if (p->x > line_p0->x + dist)
5513 return 0;
5514 }
5515 if (line_p0->y < line_p1->y)
5516 {
5517 if (p->y < line_p0->y - dist)
5518 return 0;
5519 if (p->y > line_p1->y + dist)
5520 return 0;
5521 }
5522 else
5523 {
5524 if (p->y < line_p1->y - dist)
5525 return 0;
5526 if (p->y > line_p0->y + dist)
5527 return 0;
5528 }
5529
5530 vx = line_p1->x - line_p0->x;
5531 vy = line_p1->y - line_p0->y;
5532 wx = p->x - line_p0->x;
5533 wy = p->y - line_p0->y;
5534
5535 c1 = vx * wx + vy * wy;
5536 if (c1 <= 0)
5537 return within_dist_point(p, line_p0, dist);
5538 c2 = vx * vx + vy * vy;
5539 if (c2 <= c1)
5540 return within_dist_point(p, line_p1, dist);
5541
5542 line_p.x = line_p0->x + vx * c1 / c2;
5543 line_p.y = line_p0->y + vy * c1 / c2;
5544 return within_dist_point(p, &line_p, dist);
5545 }
5546
5547 /**
5548 * FIXME
5549 * @param <>
5550 * @returns <>
5551 * @author Martin Schaller (04/2008)
5552 */
5553 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
5554 {
5555 int i;
5556 for (i = 0; i < count - 1; i++)
5557 {
5558 if (within_dist_line(p, line_pnt + i, line_pnt + i + 1, dist))
5559 {
5560 return 1;
5561 }
5562 }
5563 if (close)
5564 return (within_dist_line(p, line_pnt, line_pnt + count - 1, dist));
5565 return 0;
5566 }
5567
5568 /**
5569 * FIXME
5570 * @param <>
5571 * @returns <>
5572 * @author Martin Schaller (04/2008)
5573 */
5574 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
5575 {
5576 int i, j, c = 0;
5577 for (i = 0, j = count - 1; i < count; j = i++)
5578 {
5579 if ((((poly_pnt[i].y <= p->y) && (p->y < poly_pnt[j].y)) || ((poly_pnt[j].y <= p->y) && (p->y < poly_pnt[i].y))) && (p->x < (poly_pnt[j].x - poly_pnt[i].x) * (p->y - poly_pnt[i].y) / (poly_pnt[j].y - poly_pnt[i].y) + poly_pnt[i].x))
5580 c = !c;
5581 }
5582 if (!c)
5583 return within_dist_polyline(p, poly_pnt, count, dist, 1);
5584 return c;
5585 }
5586
5587 /**
5588 * FIXME
5589 * @param <>
5590 * @returns <>
5591 * @author Martin Schaller (04/2008)
5592 */
5593 int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
5594 {
5595 struct point *pa = g_alloca(sizeof(struct point) * displaylist->dc.maxlen);
5596 int count;
5597
5598 count = transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
5599
5600 if (di->item.type < type_line)
5601 {
5602 return within_dist_point(p, &pa[0], dist);
5603 }
5604 if (di->item.type < type_area)
5605 {
5606 return within_dist_polyline(p, pa, count, dist, 0);
5607 }
5608 return within_dist_polygon(p, pa, count, dist);
5609 }
5610
5611 static void graphics_process_selection_item(struct displaylist *dl, struct item *item)
5612 {
5613 #if 0 /* FIXME */
5614 struct displayitem di,*di_res;
5615 GHashTable *h;
5616 int count,max=dl->dc.maxlen;
5617 struct coord ca[max];
5618 struct attr attr;
5619 struct map_rect *mr;
5620
5621 di.item=*item;
5622 di.label=NULL;
5623 di.count=0;
5624 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
5625 if (h)
5626 {
5627 di_res=g_hash_table_lookup(h, &di);
5628 if (di_res)
5629 {
5630 di.item.type=(enum item_type)item->priv_data;
5631 display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
5632 return;
5633 }
5634 }
5635 mr=map_rect_new(item->map, NULL);
5636 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
5637 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
5638 if (!item_attr_get(item, attr_label, &attr))
5639 attr.u.str=NULL;
5640 if (dl->conv && attr.u.str && attr.u.str[0])
5641 {
5642 char *str=map_convert_string(item->map, attr.u.str);
5643 display_add(dl, item, count, ca, &str, 1);
5644 map_convert_free(str);
5645 }
5646 else
5647 display_add(dl, item, count, ca, &attr.u.str, 1);
5648 map_rect_destroy(mr);
5649 #endif
5650 }
5651
5652 void graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
5653 {
5654 struct item *item_dup=g_new(struct item, 1);
5655 *item_dup = *item;
5656 item_dup->priv_data = (void *) type;
5657 gra->selection = g_list_append(gra->selection, item_dup);
5658 if (dl)
5659 graphics_process_selection_item(dl, item_dup);
5660 }
5661
5662 void graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
5663 {
5664 GList *curr;
5665 int found;
5666
5667 for (;;)
5668 {
5669 curr = gra->selection;
5670 found = 0;
5671 while (curr)
5672 {
5673 struct item *sitem = curr->data;
5674 if (item_is_equal(*item, *sitem))
5675 {
5676 if (dl)
5677 {
5678 struct displayitem di;
5679 /* Unused Variable
5680 GHashTable *h; */
5681 di.item = *sitem;
5682 di.label = NULL;
5683 di.count = 0;
5684 di.item.type = type;
5685 #if 0 /* FIXME */
5686 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
5687 if (h)
5688 g_hash_table_remove(h, &di);
5689 #endif
5690 }
5691 g_free(sitem);
5692 gra->selection = g_list_remove(gra->selection, curr->data);
5693 found = 1;
5694 break;
5695 }
5696 }
5697 if (!found)
5698 return;
5699 }
5700 }
5701
5702 void graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
5703 {
5704 while (gra->selection)
5705 {
5706 struct item *item = (struct item *) gra->selection->data;
5707 graphics_remove_selection(gra, item, (enum item_type) item->priv_data, dl);
5708 }
5709 }
5710
5711 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl)
5712 {
5713 GList *curr;
5714
5715 curr = gra->selection;
5716 while (curr)
5717 {
5718 struct item *item = curr->data;
5719 graphics_process_selection_item(dl, item);
5720 curr = g_list_next(curr);
5721 }
5722 }

   
Visit the ZANavi Wiki