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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 54 - (show annotations) (download)
Mon Dec 12 13:41:30 2016 UTC (7 years, 4 months ago) by zoff99
File MIME type: text/plain
File size: 148300 byte(s)
v2.0.56
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 #define ORDER_LEVEL_TO_SHOW_ALL_POI 14 // order
140 #define ORDER2_LEVEL_TO_SHOW_ALL_POI 12 // global_scale
141
142 #define MAX_PLACE_LABELS_ON_MAP 13
143 #define MAX_DISTRICT_LABELS_ON_MAP 13
144 #define MAX_MAJOR_PLACE_LABELS_ON_MAP 9
145
146 #define ORDER_LEVEL_FOR_STREET_SIMPLIFY 9
147 #define STREET_SIMPLIFY 24
148
149 #define X_COLOR_BACKGROUND_NM 0x6666, 0x6666, 0x6666, 0xffff
150 struct color background_night_mode = { X_COLOR_BACKGROUND_NM };
151
152
153 struct graphics
154 {
155 struct graphics_priv *priv;
156 struct graphics_methods meth;
157 char *default_font;
158 int font_len;
159 struct graphics_font **font;
160 struct graphics_gc *gc[3];
161 struct attr **attrs;
162 struct callback_list *cbl;
163 struct point_rect r;
164 int gamma, brightness, contrast;
165 int colormgmt;
166 int font_size;
167 GList *selection;
168 };
169
170 /*
171 struct display_context
172 {
173 struct graphics *gra;
174 struct element *e;
175 struct graphics_gc *gc;
176 struct graphics_gc *gc_background;
177 struct graphics_image *img;
178 enum projection pro;
179 int mindist;
180 struct transformation *trans;
181 enum item_type type;
182 int maxlen;
183 };
184
185 #define HASH_SIZE 1024
186 */
187
188 /*
189 struct hash_entry
190 {
191 enum item_type type;
192 struct displayitem *di;
193 };
194 */
195
196 /*
197 struct displaylist {
198 int busy;
199 int workload;
200 struct callback *cb;
201 struct layout *layout, *layout_hashed;
202 struct display_context dc;
203 int order, order_hashed, max_offset;
204 struct mapset *ms;
205 struct mapset_handle *msh;
206 struct map *m;
207 int conv;
208 struct map_selection *sel;
209 struct map_rect *mr;
210 struct callback *idle_cb;
211 struct event_idle *idle_ev;
212 unsigned int seq;
213 struct hash_entry hash_entries[HASH_SIZE];
214 };
215 */
216
217 struct displaylist_icon_cache
218 {
219 unsigned int seq;
220
221 };
222
223 /**
224 * FIXME
225 * @param <>
226 * @returns <>
227 * @author Martin Schaller (04/2008)
228 */
229 struct displayitem
230 {
231 struct displayitem *next;
232 struct item item;
233 char *label;
234 // struct color color;
235 unsigned int col_int_value;
236 int count;
237 struct coord c[0];
238 };
239
240 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir);
241 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl);
242 static void graphics_gc_init(struct graphics *this_);
243 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in);
244
245
246 // ------------- TILES -------------
247 // ------------- TILES -------------
248 // ------------- TILES -------------
249 #include "mvt_tiles.h"
250 // ------------- TILES -------------
251 // ------------- TILES -------------
252 // ------------- TILES -------------
253
254
255
256 static void clear_hash(struct displaylist *dl)
257 {
258 int i;
259 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
260 {
261 dl->hash_entries[i].type = type_none;
262 }
263 }
264
265 static struct hash_entry *
266 get_hash_entry(struct displaylist *dl, enum item_type type)
267 {
268 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
269 int offset = dl->max_offset;
270 do
271 {
272 if (!dl->hash_entries[hashidx].type)
273 {
274 return NULL;
275 }
276 if (dl->hash_entries[hashidx].type == type)
277 {
278 return &dl->hash_entries[hashidx];
279 }
280 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
281 }
282 while (offset-- > 0);
283
284 return NULL;
285 }
286
287 static struct hash_entry *
288 set_hash_entry(struct displaylist *dl, enum item_type type)
289 {
290 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
291 int offset = 0;
292 for (;;)
293 {
294 if (!dl->hash_entries[hashidx].type)
295 {
296 dl->hash_entries[hashidx].type = type;
297 if (dl->max_offset < offset)
298 dl->max_offset = offset;
299 return &dl->hash_entries[hashidx];
300 }
301 if (dl->hash_entries[hashidx].type == type)
302 return &dl->hash_entries[hashidx];
303 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
304 offset++;
305 }
306 return NULL;
307 }
308
309 static int graphics_set_attr_do(struct graphics *gra, struct attr *attr)
310 {
311 switch (attr->type)
312 {
313 case attr_gamma:
314 gra->gamma = attr->u.num;
315 break;
316 case attr_brightness:
317 gra->brightness = attr->u.num;
318 break;
319 case attr_contrast:
320 gra->contrast = attr->u.num;
321 break;
322 case attr_font_size:
323 gra->font_size = attr->u.num;
324 return 1;
325 default:
326 return 0;
327 }
328 gra->colormgmt = (gra->gamma != 65536 || gra->brightness != 0 || gra->contrast != 65536);
329 graphics_gc_init(gra);
330 return 1;
331 }
332
333 int graphics_set_attr(struct graphics *gra, struct attr *attr)
334 {
335 int ret = 1;
336 // //DBG // dbg(0,"enter\n");
337 if (gra->meth.set_attr)
338 ret = gra->meth.set_attr(gra->priv, attr);
339 if (!ret)
340 ret = graphics_set_attr_do(gra, attr);
341 return ret != 0;
342 }
343
344 void graphics_set_rect(struct graphics *gra, struct point_rect *pr)
345 {
346 gra->r = *pr;
347 }
348
349 /**
350 * Creates a new graphics object
351 * attr type required
352 * @param <>
353 * @returns <>
354 * @author Martin Schaller (04/2008)
355 */
356 struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
357 {
358 // dbg(0, "EEnter\n");
359
360 int count = 0;
361 struct graphics *this_;
362 struct attr *type_attr;
363 struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl);
364
365 if (!(type_attr = attr_search(attrs, NULL, attr_type)))
366 {
367 return NULL;
368 }
369
370 // dbg(0, "plugins\n");
371
372 #ifdef PLUGSSS
373 graphicstype_new = plugin_get_graphics_type(type_attr->u.str);
374 if (!graphicstype_new)
375 {
376 return NULL;
377 }
378 #endif
379
380 // dbg(0, "g 003\n");
381
382 this_=g_new0(struct graphics, 1);
383 this_->cbl = callback_list_new("graphics_new:this_->cbl");
384
385 #ifdef PLUGSSS
386 this_->priv = (*graphicstype_new)(parent->u.navit, &this_->meth, attrs, this_->cbl);
387 #else
388 this_->priv = graphics_android_new(parent->u.navit, &this_->meth, attrs, this_->cbl);
389 #endif
390
391 this_->attrs = attr_list_dup(attrs);
392 this_->brightness = 0;
393 this_->contrast = 65536;
394 this_->gamma = 65536;
395 this_->font_size = 20;
396
397 // dbg(0, "g 004\n");
398
399 while (*attrs)
400 {
401 count++;
402 // dbg(0, "g 005 attr %d\n", count);
403 graphics_set_attr_do(this_, *attrs);
404 attrs++;
405 // dbg(0, "g 006 attr\n");
406 }
407
408 // dbg(0, "return\n");
409 return this_;
410 }
411
412 /**
413 * FIXME
414 * @param <>
415 * @returns <>
416 * @author Martin Schaller (04/2008)
417 */
418 int graphics_get_attr(struct graphics *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
419 {
420 return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
421 }
422
423 /**
424 * FIXME
425 * @param <>
426 * @returns <>
427 * @author Martin Schaller (04/2008)
428 */
429 struct graphics * graphics_overlay_new(const char* name, struct graphics *parent, struct point *p, int w, int h, int alpha, int wraparound)
430 {
431 struct graphics *this_;
432 struct point_rect pr;
433 if (!parent->meth.overlay_new)
434 return NULL;this_=g_new0(struct graphics, 1);
435 this_->priv = parent->meth.overlay_new(name, parent->priv, &this_->meth, p, w, h, alpha, wraparound);
436 pr.lu.x = 0;
437 pr.lu.y = 0;
438 pr.rl.x = w;
439 pr.rl.y = h;
440 this_->font_size = 20;
441 graphics_set_rect(this_, &pr);
442 if (!this_->priv)
443 {
444 g_free(this_);
445 this_ = NULL;
446 }
447 return this_;
448 }
449
450 /**
451 * @brief Alters the size, position, alpha and wraparound for an overlay
452 *
453 * @param this_ The overlay's graphics struct
454 * @param p The new position of the overlay
455 * @param w The new width of the overlay
456 * @param h The new height of the overlay
457 * @param alpha The new alpha of the overlay
458 * @param wraparound The new wraparound of the overlay
459 */
460 void graphics_overlay_resize(struct graphics *this_, struct point *p, int w, int h, int alpha, int wraparound)
461 {
462 if (!this_->meth.overlay_resize)
463 {
464 return;
465 }
466
467 this_->meth.overlay_resize(this_->priv, p, w, h, alpha, wraparound);
468 }
469
470 static void graphics_gc_init(struct graphics *this_)
471 {
472 // dbg(0, "EEnter\n");
473
474 struct color background = { COLOR_BACKGROUND_ };
475 struct color black = { COLOR_BLACK_ };
476 struct color white = { COLOR_WHITE_ };
477
478 if (!this_->gc[0] || !this_->gc[1] || !this_->gc[2])
479 {
480 return;
481 }
482
483 graphics_gc_set_background(this_->gc[0], &background);
484 graphics_gc_set_foreground(this_->gc[0], &background);
485
486 graphics_gc_set_background(this_->gc[1], &black);
487 graphics_gc_set_foreground(this_->gc[1], &white);
488 graphics_gc_set_background(this_->gc[2], &white);
489 graphics_gc_set_foreground(this_->gc[2], &black);
490
491 // dbg(0, "return\n");
492 }
493
494 /**
495 * FIXME
496 * @param <>
497 * @returns <>
498 * @author Martin Schaller (04/2008)
499 */
500 void graphics_init(struct graphics *this_)
501 {
502 if (this_->gc[0])
503 {
504 return;
505 }
506
507 this_->gc[0] = graphics_gc_new(this_);
508 this_->gc[1] = graphics_gc_new(this_);
509 this_->gc[2] = graphics_gc_new(this_);
510
511 graphics_gc_init(this_);
512
513 graphics_background_gc(this_, this_->gc[0]);
514 }
515
516 /**
517 * FIXME
518 * @param <>
519 * @returns <>
520 * @author Martin Schaller (04/2008)
521 */
522 void * graphics_get_data(struct graphics *this_, const char *type)
523 {
524 return (this_->meth.get_data(this_->priv, type));
525 }
526
527 void graphics_add_callback(struct graphics *this_, struct callback *cb)
528 {
529 callback_list_add(this_->cbl, cb);
530 }
531
532 void graphics_remove_callback(struct graphics *this_, struct callback *cb)
533 {
534 callback_list_remove(this_->cbl, cb);
535 }
536
537 /**
538 * FIXME
539 * @param <>
540 * @returns <>
541 * @author Martin Schaller (04/2008)
542 */
543 struct graphics_font * graphics_font_new(struct graphics *gra, int size, int flags)
544 {
545 struct graphics_font *this_;
546
547 this_=g_new0(struct graphics_font,1);
548 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, gra->default_font, size, flags);
549 return this_;
550 }
551
552 struct graphics_font * graphics_named_font_new(struct graphics *gra, char *font, int size, int flags)
553 {
554 struct graphics_font *this_;
555
556 this_=g_new0(struct graphics_font,1);
557 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, font, size, flags);
558 return this_;
559 }
560
561 /**
562 * Destroy graphics
563 * Called when navit exits
564 * @param gra The graphics instance
565 * @returns nothing
566 * @author David Tegze (02/2011)
567 */
568 void graphics_free(struct graphics *gra)
569 {
570 if (!gra)
571 {
572 return;
573 }
574
575 gra->meth.graphics_destroy(gra->priv);
576 g_free(gra->default_font);
577 graphics_font_destroy_all(gra);
578 g_free(gra);
579 }
580
581 /**
582 * Free all loaded fonts.
583 * Used when switching layouts.
584 * @param gra The graphics instance
585 * @returns nothing
586 * @author Sarah Nordstrom (05/2008)
587 */
588 void graphics_font_destroy_all(struct graphics *gra)
589 {
590 int i;
591 for (i = 0; i < gra->font_len; i++)
592 {
593 if (!gra->font[i])
594 {
595 continue;
596 }
597
598 gra->font[i]->meth.font_destroy(gra->font[i]->priv);
599 gra->font[i] = NULL;
600 }
601 }
602
603 /**
604 * FIXME
605 * @param <>
606 * @returns <>
607 * @author Martin Schaller (04/2008)
608 */
609 struct graphics_gc * graphics_gc_new(struct graphics *gra)
610 {
611 struct graphics_gc *this_;
612
613 this_=g_new0(struct graphics_gc,1);
614 this_->priv = gra->meth.gc_new(gra->priv, &this_->meth);
615 this_->gra = gra;
616 return this_;
617 }
618
619 /**
620 * FIXME
621 * @param <>
622 * @returns <>
623 * @author Martin Schaller (04/2008)
624 */
625 void graphics_gc_destroy(struct graphics_gc *gc)
626 {
627 gc->meth.gc_destroy(gc->priv);
628 g_free(gc);
629 }
630
631 static void graphics_convert_color(struct graphics *gra, struct color *in, struct color *out)
632 {
633 *out = *in;
634
635 if (gra->brightness)
636 {
637 out->r += gra->brightness;
638 out->g += gra->brightness;
639 out->b += gra->brightness;
640 }
641
642 if (gra->contrast != 65536)
643 {
644 out->r = out->r * gra->contrast / 65536;
645 out->g = out->g * gra->contrast / 65536;
646 out->b = out->b * gra->contrast / 65536;
647 }
648
649 if (out->r < 0)
650 out->r = 0;
651
652 if (out->r > 65535)
653 out->r = 65535;
654
655 if (out->g < 0)
656 out->g = 0;
657
658 if (out->g > 65535)
659 out->g = 65535;
660
661 if (out->b < 0)
662 out->b = 0;
663
664 if (out->b > 65535)
665 out->b = 65535;
666
667 if (gra->gamma != 65536)
668 {
669 out->r = pow(out->r / 65535.0, gra->gamma / 65536.0) * 65535.0;
670 out->g = pow(out->g / 65535.0, gra->gamma / 65536.0) * 65535.0;
671 out->b = pow(out->b / 65535.0, gra->gamma / 65536.0) * 65535.0;
672 }
673 }
674
675 /**
676 * FIXME
677 * @param <>
678 * @returns <>
679 * @author Martin Schaller (04/2008)
680 */
681 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
682 {
683 struct color cn;
684 if (gc->gra->colormgmt)
685 {
686 graphics_convert_color(gc->gra, c, &cn);
687 c = &cn;
688 }
689 gc->meth.gc_set_foreground(gc->priv, c);
690 }
691
692 /**
693 * FIXME
694 * @param <>
695 * @returns <>
696 * @author Martin Schaller (04/2008)
697 */
698 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
699 {
700 struct color cn;
701 if (gc->gra->colormgmt)
702 {
703 graphics_convert_color(gc->gra, c, &cn);
704 c = &cn;
705 }
706 gc->meth.gc_set_background(gc->priv, c);
707 }
708
709 /**
710 * FIXME
711 * @param <>
712 * @returns <>
713 * @author Martin Schaller (04/2008)
714 */
715 void graphics_gc_set_stipple(struct graphics_gc *gc, struct graphics_image *img)
716 {
717 gc->meth.gc_set_stipple(gc->priv, img ? img->priv : NULL);
718 }
719
720 /**
721 * FIXME
722 * @param <>
723 * @returns <>
724 * @author Martin Schaller (04/2008)
725 */
726 void graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
727 {
728 gc->meth.gc_set_linewidth(gc->priv, width);
729 }
730
731 /**
732 * FIXME
733 * @param <>
734 * @returns <>
735 * @author Martin Schaller (04/2008)
736 */
737 void graphics_gc_set_dashes(struct graphics *gra, struct graphics_gc *gc, int width, int offset, int dash_list[], int n, int order)
738 {
739 if (gc->meth.gc_set_dashes)
740 {
741 gc->meth.gc_set_dashes(gra->priv, gc->priv, width, offset, dash_list, order);
742 }
743 }
744
745 /**
746 * Create a new image from file path scaled to w and h pixels
747 * @param gra the graphics instance
748 * @param path path of the image to load
749 * @param w width to rescale to
750 * @param h height to rescale to
751 * @returns <>
752 * @author Martin Schaller (04/2008)
753 */
754 struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *path, int w, int h)
755 {
756 struct graphics_image *this_;
757
758 this_=g_new0(struct graphics_image,1);
759 this_->height = h;
760 this_->width = w;
761 this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, 0);
762 if (!this_->priv)
763 {
764 g_free(this_);
765 this_ = NULL;
766 }
767 return this_;
768 }
769
770 /**
771 * Create a new image from file path scaled to w and h pixels and possibly rotated
772 * @param gra the graphics instance
773 * @param path path of the image to load
774 * @param w width to rescale to
775 * @param h height to rescale to
776 * @param rotate angle to rotate the image. Warning, graphics might only support 90 degree steps here
777 * @returns <>
778 * @author Martin Schaller (04/2008)
779 */
780 struct graphics_image * graphics_image_new_scaled_rotated(struct graphics *gra, char *path, int w, int h, int rotate)
781 {
782 struct graphics_image *this_;
783
784 this_=g_new0(struct graphics_image,1);
785 this_->height = h;
786 this_->width = w;
787 this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, rotate);
788 if (!this_->priv)
789 {
790 g_free(this_);
791 this_ = NULL;
792 }
793 return this_;
794 }
795
796 /**
797 * Create a new image from file path
798 * @param gra the graphics instance
799 * @param path path of the image to load
800 * @returns <>
801 * @author Martin Schaller (04/2008)
802 */
803 struct graphics_image * graphics_image_new(struct graphics *gra, char *path)
804 {
805 return graphics_image_new_scaled(gra, path, -1, -1);
806 }
807
808 /**
809 * FIXME
810 * @param <>
811 * @returns <>
812 * @author Martin Schaller (04/2008)
813 */
814 void graphics_image_free(struct graphics *gra, struct graphics_image *img)
815 {
816 if (gra->meth.image_free)
817 gra->meth.image_free(gra->priv, img->priv);
818 g_free(img);
819 }
820
821 /**
822 * FIXME
823 * @param <>
824 * @returns <>
825 * @author Martin Schaller (04/2008)
826 */
827 void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
828 {
829 ////DBG // dbg(0,"ooo enter ooo\n");
830
831 this_->meth.draw_restore(this_->priv, p, w, h);
832 }
833
834 /**
835 * FIXME
836 * @param <>
837 * @returns <>
838 * @author Martin Schaller (04/2008)
839 */
840 void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
841 {
842 ////DBG // dbg(0,"ooo enter ooo\n");
843
844 this_->meth.draw_mode(this_->priv, mode);
845 }
846
847 /**
848 * FIXME
849 * @param <>
850 * @returns <>
851 * @author Martin Schaller (04/2008)
852 */
853 void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
854 {
855 this_->meth.draw_lines(this_->priv, gc->priv, p, count);
856 }
857
858 void graphics_draw_lines_dashed(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count, int order, int oneway)
859 {
860 this_->meth.draw_lines_dashed(this_->priv, gc->priv, p, count, order, oneway);
861 }
862
863 /**
864 * FIXME
865 * @param <>
866 * @returns <>
867 * @author Martin Schaller (04/2008)
868 */
869 void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
870 {
871 int i = 0;
872
873 if (this_->meth.draw_circle)
874 {
875 this_->meth.draw_circle(this_->priv, gc->priv, p, r);
876 }
877 else
878 {
879 struct point *pnt = g_alloca(sizeof(struct point) * (r * 4 + 64));
880 draw_circle(p, r, 0, -1, 1026, pnt, &i, 1);
881 pnt[i] = pnt[0];
882 i++;
883 this_->meth.draw_lines(this_->priv, gc->priv, pnt, i);
884 }
885 }
886
887 /**
888 * FIXME
889 * @param <>
890 * @returns <>
891 * @author Martin Schaller (04/2008)
892 */
893 void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
894 {
895 this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
896 }
897
898 void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, int r, int fill)
899 {
900 struct point *p = g_alloca(sizeof(struct point) * (r * 4 + 32));
901 struct point pi0 = { plu->x + r, plu->y + r };
902 struct point pi1 = { plu->x + w - r, plu->y + r };
903 struct point pi2 = { plu->x + w - r, plu->y + h - r };
904 struct point pi3 = { plu->x + r, plu->y + h - r };
905 int i = 0;
906
907 draw_circle(&pi2, r * 2, 0, -1, 258, p, &i, 1);
908 draw_circle(&pi1, r * 2, 0, 255, 258, p, &i, 1);
909 draw_circle(&pi0, r * 2, 0, 511, 258, p, &i, 1);
910 draw_circle(&pi3, r * 2, 0, 767, 258, p, &i, 1);
911 p[i] = p[0];
912 i++;
913 if (fill)
914 this_->meth.draw_polygon(this_->priv, gc->priv, p, i);
915 else
916 this_->meth.draw_lines(this_->priv, gc->priv, p, i);
917 }
918
919 /**
920 * FIXME
921 * @param <>
922 * @returns <>
923 * @author Martin Schaller (04/2008)
924 */
925 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)
926 {
927 this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy);
928 }
929
930 /**
931 * FIXME
932 * @param <>
933 * @returns <>
934 * @author Martin Schaller (04/2008)
935 */
936 void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret, int estimate)
937 {
938 this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret, estimate);
939 }
940
941 /**
942 * FIXME
943 * @param <>
944 * @returns <>
945 * @author Martin Schaller (04/2008)
946 */
947 void graphics_overlay_disable(struct graphics *this_, int disable)
948 {
949 if (this_->meth.overlay_disable)
950 this_->meth.overlay_disable(this_->priv, disable);
951 }
952
953 /**
954 * FIXME
955 * @param <>
956 * @returns <>
957 * @author Martin Schaller (04/2008)
958 */
959 void graphics_draw_image(struct graphics *this_, struct graphics_gc *gc, struct point *p, struct graphics_image *img)
960 {
961 this_->meth.draw_image(this_->priv, gc->priv, p, img->priv);
962 }
963
964 /**
965 *
966 *
967 * @author Zoff (2011)
968 */
969 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)
970 {
971 this_->meth.draw_bigmap(this_->priv, gc->priv, yaw, order, clat, clng, x, y, scx, scy, px, py, valid);
972 }
973
974 //##############################################################################################################
975 //# Description:
976 //# Comment:
977 //# Authors: Martin Schaller (04/2008)
978 //##############################################################################################################
979 int graphics_draw_drag(struct graphics *this_, struct point *p)
980 {
981 __F_START__
982
983 if (!this_->meth.draw_drag)
984 {
985 return2 0;
986 }
987 ////DBG // dbg(0,"draw DRAG start ...\n");
988 this_->meth.draw_drag(this_->priv, p);
989 ////DBG // dbg(0,"draw DRAG end ...\n");
990 return2 1;
991
992 __F_END__
993
994 }
995
996 void graphics_background_gc(struct graphics *this_, struct graphics_gc *gc)
997 {
998 ////DBG // dbg(0,"ooo enter ooo\n");
999
1000 this_->meth.background_gc(this_->priv, gc ? gc->priv : NULL);
1001 }
1002
1003 #include "attr.h"
1004 #include "popup.h"
1005 #include <stdio.h>
1006
1007 #if 0
1008 //##############################################################################################################
1009 //# Description:
1010 //# Comment:
1011 //# Authors: Martin Schaller (04/2008)
1012 //##############################################################################################################
1013 static void popup_view_html(struct popup_item *item, char *file)
1014 {
1015 char command[1024];
1016 sprintf(command,"firefox %s", file);
1017 system(command);
1018 }
1019
1020 struct transformatin *tg;
1021 enum projection pg;
1022
1023 //##############################################################################################################
1024 //# Description:
1025 //# Comment:
1026 //# Authors: Martin Schaller (04/2008)
1027 //##############################################################################################################
1028 static void graphics_popup(struct display_list *list, struct popup_item **popup)
1029 {
1030 struct item *item;
1031 struct attr attr;
1032 struct map_rect *mr;
1033 struct coord c;
1034 struct popup_item *curr_item,*last=NULL;
1035 item=list->data;
1036 mr=map_rect_new(item->map, NULL, NULL, 0);
1037 printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
1038 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
1039 if (item)
1040 {
1041 if (item_attr_get(item, attr_name, &attr))
1042 {
1043 curr_item=popup_item_new_text(popup,attr.u.str,1);
1044 if (item_attr_get(item, attr_info_html, &attr))
1045 {
1046 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
1047 }
1048 if (item_attr_get(item, attr_price_html, &attr))
1049 {
1050 popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
1051 }
1052 curr_item->submenu=last;
1053 }
1054 }
1055 map_rect_destroy(mr);
1056 }
1057 #endif
1058
1059 /**
1060 * FIXME
1061 * @param <>
1062 * @returns <>
1063 * @author Martin Schaller (04/2008)
1064 */
1065 static void xdisplay_free(struct displaylist *dl)
1066 {
1067 int i;
1068 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
1069 {
1070 struct displayitem *di = dl->hash_entries[i].di;
1071 while (di)
1072 {
1073 struct displayitem *next = di->next;
1074 g_free(di);
1075 di = next;
1076 }
1077 dl->hash_entries[i].di = NULL;
1078 }
1079 }
1080
1081 /**
1082 * FIXME
1083 * @param <>
1084 * @returns <>
1085 * @author Martin Schaller (04/2008)
1086 */
1087 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)
1088 {
1089 struct displayitem *di;
1090 int len, i;
1091 // int len2;
1092 char *p;
1093
1094 len = sizeof(*di) + count * sizeof(*c);
1095 if (label && label_count > 0)
1096 {
1097 for (i = 0; i < label_count; i++)
1098 {
1099 if (label[i])
1100 {
1101 //dbg(0, "label=X%sX\n", label[i]);
1102 len += strlen(label[i]);
1103 if (i < (label_count - 1))
1104 {
1105 len = len + 2; // put ', '(==2 chars) between labels!
1106 }
1107 }
1108 }
1109 len++; // NULL at the end
1110 }
1111
1112 p = g_malloc(len);
1113 //len2 = len - (sizeof(*di) + count * sizeof(*c));
1114 //dbg(0,"malloc len:%d len2:%d\n", len, len2);
1115
1116 di = (struct displayitem *) p;
1117 p += sizeof(*di) + count * sizeof(*c);
1118 di->item = *item;
1119
1120 if (color_yes_no)
1121 {
1122 //di->color.r = r;
1123 //di->color.g = g;
1124 //di->color.b = b;
1125 //di->color.a = a;
1126 di->col_int_value = color_int;
1127 }
1128 else
1129 {
1130 // 0 --> no custom color is set
1131 //di->color.a = 0;
1132 di->col_int_value = (unsigned int)0;
1133 }
1134
1135 if (label && label_count > 0)
1136 {
1137 di->label = p;
1138 for (i = 0; i < label_count; i++)
1139 {
1140 if (label[i])
1141 {
1142 strncpy(p, label[i], strlen(label[i])); // copy string without!! NULL byte at the end
1143 p += strlen(label[i]);
1144 if (i < (label_count - 1))
1145 {
1146 // put ', ' between labels!
1147 *p++ = ',';
1148 *p++ = ' ';
1149 }
1150 }
1151 }
1152 *p++ = '\0'; // add NULL at the end
1153 //p = di->label;
1154 //p = p + len2;
1155 //*p = '\0'; // for safety NULL at the real end!
1156 //dbg(0, "add:strlen=%d p=%s\n", strlen(di->label), di->label);
1157 }
1158 else
1159 {
1160 di->label = NULL;
1161 }
1162
1163 di->count = count;
1164 memcpy(di->c, c, count * sizeof(*c));
1165 di->next = entry->di;
1166 entry->di = di;
1167 }
1168
1169 /**
1170 * FIXME
1171 * @param <>
1172 * @returns <>
1173 * @author Martin Schaller (04/2008)
1174 */
1175 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)
1176 {
1177 int i, x, y, tl, tlm, th, thm, tlsq, l;
1178 float lsq;
1179 // double dx, dy;
1180 float dx, dy;
1181 struct point p_t;
1182 struct point pb[5];
1183
1184 if (gra->meth.get_text_bbox)
1185 {
1186 gra->meth.get_text_bbox(gra->priv, font->priv, label, 0x10000, 0x0, pb, 1);
1187 // tl -> text length
1188 tl = (pb[2].x - pb[0].x);
1189 // th -> text height
1190 th = (pb[0].y - pb[1].y);
1191 }
1192 else
1193 {
1194 // tl -> text length
1195 tl = strlen(label) * 4;
1196 // th -> text height
1197 th = 8;
1198 }
1199 tlm = tl * 32;
1200 thm = th * 36;
1201 // tlsq -> (text length * 32) squared
1202 tlsq = tlm * tlm;
1203 for (i = 0; i < count - 1; i++)
1204 {
1205 dx = p[i + 1].x - p[i].x;
1206 dx *= 32;
1207 dy = p[i + 1].y - p[i].y;
1208 dy *= 32;
1209 // lsq -> (line length * 32) squared
1210 lsq = dx * dx + dy * dy;
1211 if (lsq > tlsq)
1212 {
1213
1214
1215 // warning: suggest parentheses around '&&' within '||' [-Wparentheses]
1216 if (((int) lsq > MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2) || (((i == 0) || (i == (count - 2)) && ((int) lsq > (int) MIN_LINE_LENGTH_FOR_TEXT_2))))
1217 {
1218
1219
1220 // segments in the middle of the "way" need to be longer for streetname to be drawn
1221 // l -> line length
1222 l = (int) sqrtf_fast2(lsq);
1223 x = p[i].x;
1224 y = p[i].y;
1225 if (dx < 0)
1226 {
1227 dx = -dx;
1228 dy = -dy;
1229 x = p[i + 1].x;
1230 y = p[i + 1].y;
1231 }
1232 x += (l - tlm) * dx / l / 64;
1233 y += (l - tlm) * dy / l / 64;
1234 x -= dy * thm / l / 64;
1235 y += dx * thm / l / 64;
1236 p_t.x = x;
1237 p_t.y = y;
1238 #if 0
1239 //DBG // dbg(0,"display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
1240 #endif
1241 if (x < gra->r.rl.x && x + tl > gra->r.lu.x && y + tl > gra->r.lu.y && y - tl < gra->r.rl.y)
1242 {
1243 gra->meth.draw_text(gra->priv, fg->priv, bg ? bg->priv : NULL, font->priv, label, &p_t, dx * 0x10000 / l, dy * 0x10000 / l);
1244 }
1245 }
1246 }
1247 }
1248 }
1249
1250 static void display_draw_arrow(struct point *p, int dx, int dy, int l, struct graphics_gc *gc, struct graphics *gra)
1251 {
1252 struct point pnt[3];
1253 pnt[0] = pnt[1] = pnt[2] = *p;
1254 pnt[0].x += -dx * l / 65536 + dy * l / 65536;
1255 pnt[0].y += -dy * l / 65536 - dx * l / 65536;
1256 pnt[2].x += -dx * l / 65536 - dy * l / 65536;
1257 pnt[2].y += -dy * l / 65536 + dx * l / 65536;
1258 gra->meth.draw_lines(gra->priv, gc->priv, pnt, 3);
1259 }
1260
1261 static void display_draw_arrows(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count)
1262 {
1263
1264 int i, dx, dy, l;
1265 struct point p;
1266 for (i = 0; i < count - 1; i++)
1267 {
1268 dx = pnt[i + 1].x - pnt[i].x;
1269 dy = pnt[i + 1].y - pnt[i].y;
1270 l = sqrt(dx * dx + dy * dy);
1271 if (l)
1272 {
1273 dx = dx * 65536 / l;
1274 dy = dy * 65536 / l;
1275 p = pnt[i];
1276 p.x += dx * 15 / 65536;
1277 p.y += dy * 15 / 65536;
1278 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1279 p = pnt[i + 1];
1280 p.x -= dx * 15 / 65536;
1281 p.y -= dy * 15 / 65536;
1282 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1283 }
1284 }
1285 }
1286
1287 static int intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy, struct point * res)
1288 {
1289 int n, a, b;
1290 n = bdy * adx - bdx * ady;
1291 a = bdx * (a1->y - b1->y) - bdy * (a1->x - b1->x);
1292 b = adx * (a1->y - b1->y) - ady * (a1->x - b1->x);
1293 if (n < 0)
1294 {
1295 n = -n;
1296 a = -a;
1297 b = -b;
1298 }
1299 #if 0
1300 if (a < 0 || b < 0)
1301 return 0;
1302 if (a > n || b > n)
1303 return 0;
1304 #endif
1305 if (n == 0)
1306 return 0;
1307 res->x = a1->x + a * adx / n;
1308 res->y = a1->y + a * ady / n;
1309 return 1;
1310 }
1311
1312 struct circle
1313 {
1314 short x, y, fowler;
1315 }
1316 circle64[] =
1317 { { 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 }, };
1318
1319 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir)
1320 {
1321 struct circle *c;
1322
1323 #if 0
1324 //DBG // dbg(0,"diameter=%d start=%d len=%d pos=%d dir=%d\n", diameter, start, len, *pos, dir);
1325 #endif
1326 int count = 64;
1327 int end = start + len;
1328 int i, step;
1329 c = circle64;
1330 if (diameter > 128)
1331 step = 1;
1332 else if (diameter > 64)
1333 step = 2;
1334 else if (diameter > 24)
1335 step = 4;
1336 else if (diameter > 8)
1337 step = 8;
1338 else
1339 step = 16;
1340 if (len > 0)
1341 {
1342 while (start < 0)
1343 {
1344 start += 1024;
1345 end += 1024;
1346 }
1347 while (end > 0)
1348 {
1349 i = 0;
1350 while (i < count && c[i].fowler <= start)
1351 {
1352 i += step;
1353 }
1354 while (i < count && c[i].fowler < end)
1355 {
1356 if (1 < *pos || 0 < dir)
1357 {
1358 res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1359 res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1360 (*pos) += dir;
1361 }
1362 i += step;
1363 }
1364 end -= 1024;
1365 start -= 1024;
1366 }
1367 }
1368 else
1369 {
1370 while (start > 1024)
1371 {
1372 start -= 1024;
1373 end -= 1024;
1374 }
1375 while (end < 1024)
1376 {
1377 i = count - 1;
1378 while (i >= 0 && c[i].fowler >= start)
1379 i -= step;
1380 while (i >= 0 && c[i].fowler > end)
1381 {
1382 if (1 < *pos || 0 < dir)
1383 {
1384 res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1385 res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1386 (*pos) += dir;
1387 }
1388 i -= step;
1389 }
1390 start += 1024;
1391 end += 1024;
1392 }
1393 }
1394 }
1395
1396 static int fowler(int dy, int dx)
1397 {
1398 int adx, ady; /* Absolute Values of Dx and Dy */
1399 int code; /* Angular Region Classification Code */
1400
1401 adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
1402 ady = (dy < 0) ? -dy : dy;
1403
1404 code = (adx < ady) ? 1 : 0;
1405 if (dx < 0)
1406 code += 2;
1407 if (dy < 0)
1408 code += 4;
1409
1410 switch (code)
1411 {
1412 case 0:
1413 return (dx == 0) ? 0 : 128 * ady / adx; /* [ 0, 45] */
1414 case 1:
1415 return (256 - (128 * adx / ady)); /* ( 45, 90] */
1416 case 3:
1417 return (256 + (128 * adx / ady)); /* ( 90,135) */
1418 case 2:
1419 return (512 - (128 * ady / adx)); /* [135,180] */
1420 case 6:
1421 return (512 + (128 * ady / adx)); /* (180,225] */
1422 case 7:
1423 return (768 - (128 * adx / ady)); /* (225,270) */
1424 case 5:
1425 return (768 + (128 * adx / ady)); /* [270,315) */
1426 case 4:
1427 return (1024 - (128 * ady / adx));/* [315,360) */
1428 }
1429 return 0;
1430 }
1431
1432 static int int_sqrt(unsigned int n)
1433 {
1434 unsigned int h, p = 0, q = 1, r = n;
1435
1436 /* avoid q rollover */
1437 if (n >= (1 << (sizeof(n) * 8 - 2)))
1438 {
1439 q = 1 << (sizeof(n) * 8 - 2);
1440 }
1441 else
1442 {
1443 while (q <= n)
1444 {
1445 q <<= 2;
1446 }
1447 q >>= 2;
1448 }
1449
1450 while (q != 0)
1451 {
1452 h = p + q;
1453 p >>= 1;
1454 if (r >= h)
1455 {
1456 p += q;
1457 r -= h;
1458 }
1459 q >>= 2;
1460 }
1461 return p;
1462 }
1463
1464 struct offset
1465 {
1466 int px, py, nx, ny;
1467 };
1468
1469 static void calc_offsets(int wi, int l, int dx, int dy, struct offset *res)
1470 {
1471 int x, y;
1472
1473 x = (dx * wi) / l;
1474 y = (dy * wi) / l;
1475 if (x < 0)
1476 {
1477 res->nx = -x / 2;
1478 res->px = (x - 1) / 2;
1479 }
1480 else
1481 {
1482 res->nx = -(x + 1) / 2;
1483 res->px = x / 2;
1484 }
1485 if (y < 0)
1486 {
1487 res->ny = -y / 2;
1488 res->py = (y - 1) / 2;
1489 }
1490 else
1491 {
1492 res->ny = -(y + 1) / 2;
1493 res->py = y / 2;
1494 }
1495 }
1496
1497 // this func. is now obsolete!! and unused!!!!
1498 // this func. is now obsolete!! and unused!!!!
1499 // this func. is now obsolete!! and unused!!!!
1500 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)
1501 {
1502 int maxpoints = 200;
1503 struct point *res = g_alloca(sizeof(struct point) * maxpoints);
1504 struct point pos, poso, neg, nego;
1505 int i, dx = 0, dy = 0, l = 0, dxo = 0, dyo = 0;
1506 struct offset o, oo = { 0, 0, 0, 0 };
1507 int fow = 0, fowo = 0, delta;
1508 int wi, ppos = maxpoints / 2, npos = maxpoints / 2;
1509 int state, prec = 5;
1510 int max_circle_points = 20;
1511 int lscale = 16;
1512 i = 0;
1513 for (;;)
1514 {
1515 wi = *width;
1516 width += step;
1517 if (i < count - 1)
1518 {
1519 int dxs, dys, lscales;
1520
1521 dx = (pnt[i + 1].x - pnt[i].x);
1522 dy = (pnt[i + 1].y - pnt[i].y);
1523 #if 0
1524 l = int_sqrt(dx * dx * lscale * lscale + dy * dy * lscale * lscale);
1525 #else
1526 dxs = dx * dx;
1527 dys = dy * dy;
1528 lscales = lscale * lscale;
1529 if (dxs + dys > lscales)
1530 l = int_sqrt(dxs + dys) * lscale;
1531 else
1532 l = int_sqrt((dxs + dys) * lscales);
1533 #endif
1534 fow = fowler(-dy, dx);
1535 }
1536 if (!l)
1537 l = 1;
1538 if (wi * lscale > 10000)
1539 lscale = 10000 / wi;
1540 dbg_assert(wi * lscale <= 10000);
1541 calc_offsets(wi * lscale, l, dx, dy, &o);
1542 pos.x = pnt[i].x + o.ny;
1543 pos.y = pnt[i].y + o.px;
1544 neg.x = pnt[i].x + o.py;
1545 neg.y = pnt[i].y + o.nx;
1546 if (!i)
1547 state = 0;
1548 else if (i == count - 1)
1549 state = 2;
1550 else if (npos < max_circle_points || ppos >= maxpoints - max_circle_points)
1551 state = 3;
1552 else
1553 state = 1;
1554 switch (state)
1555 {
1556 case 1:
1557 if (fowo != fow)
1558 {
1559 poso.x = pnt[i].x + oo.ny;
1560 poso.y = pnt[i].y + oo.px;
1561 nego.x = pnt[i].x + oo.py;
1562 nego.y = pnt[i].y + oo.nx;
1563 delta = fowo - fow;
1564 if (delta < 0)
1565 delta += 1024;
1566 if (delta < 512)
1567 {
1568 if (intersection(&pos, dx, dy, &poso, dxo, dyo, &res[ppos]))
1569 {
1570 ppos++;
1571 }
1572 res[--npos] = nego;
1573 --npos;
1574 if (fill == 1)
1575 {
1576 if (draw_polylines_fast == 0)
1577 {
1578 draw_circle(&pnt[i], wi, prec, fowo - 512, -delta, res, &npos, -1);
1579 }
1580 }
1581 res[npos] = neg;
1582 }
1583 else
1584 {
1585 res[ppos++] = poso;
1586 if (fill == 1)
1587 {
1588 if (draw_polylines_fast == 0)
1589 {
1590 draw_circle(&pnt[i], wi, prec, fowo, 1024 - delta, res, &ppos, 1);
1591 }
1592 }
1593 res[ppos++] = pos;
1594 if (intersection(&neg, dx, dy, &nego, dxo, dyo, &res[npos - 1]))
1595 {
1596 npos--;
1597 }
1598 }
1599 }
1600 break;
1601 case 2:
1602 case 3:
1603 res[--npos] = neg;
1604 --npos;
1605 if (fill == 1)
1606 {
1607 if (draw_polylines_fast == 0)
1608 {
1609 draw_circle(&pnt[i], wi, prec, fow - 512, -512, res, &npos, -1);
1610 }
1611 }
1612 res[npos] = pos;
1613 res[ppos++] = pos;
1614 dbg_assert(npos > 0);
1615 dbg_assert(ppos < maxpoints);
1616 if (fill == 1)
1617 {
1618 gra->meth.draw_polygon2(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1619 }
1620 else
1621 {
1622 gra->meth.draw_lines_dashed(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1623 }
1624 if (state == 2)
1625 break;
1626 npos = maxpoints / 2;
1627 ppos = maxpoints / 2;
1628 case 0:
1629 res[ppos++] = neg;
1630 if (fill == 1)
1631 {
1632 if (draw_polylines_fast == 0)
1633 {
1634 draw_circle(&pnt[i], wi, prec, fow + 512, 512, res, &ppos, 1);
1635 }
1636 }
1637 res[ppos++] = pos;
1638 break;
1639 }
1640
1641 i++;
1642
1643 if (i >= count)
1644 {
1645 break;
1646 }
1647
1648 if (step)
1649 {
1650 wi = *width;
1651 calc_offsets(wi * lscale, l, dx, dy, &oo);
1652 }
1653 else
1654 {
1655 oo = o;
1656 }
1657
1658 dxo = -dx;
1659 dyo = -dy;
1660 fowo = fow;
1661 }
1662 }
1663 // this func. is now obsolete!! and unused!!!!
1664 // this func. is now obsolete!! and unused!!!!
1665 // this func. is now obsolete!! and unused!!!!
1666
1667
1668 struct wpoint
1669 {
1670 int x, y, w;
1671 };
1672
1673 static int clipcode(struct wpoint *p, struct point_rect *r)
1674 {
1675 int code = 0;
1676 if (p->x < r->lu.x)
1677 code = 1;
1678 if (p->x > r->rl.x)
1679 code = 2;
1680 if (p->y < r->lu.y)
1681 code |= 4;
1682 if (p->y > r->rl.y)
1683 code |= 8;
1684 return code;
1685 }
1686
1687 #define DONT_INTERSECT 0
1688 #define DO_INTERSECT 1
1689 #define COLLINEAR 2
1690 #define SAME_SIGNS( a, b ) \
1691 (((long) ((unsigned long) a ^ (unsigned long) b)) >= 0 )
1692
1693 static int lines_intersect(int x1, int y1, /* First line segment */
1694 int x2, int y2,
1695
1696 int x3, int y3, /* Second line segment */
1697 int x4, int y4,
1698
1699 int *x, int *y /* Output value:
1700 * point of intersection */
1701 )
1702 {
1703 int a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
1704 int r1, r2, r3, r4; /* 'Sign' values */
1705 int denom, offset, num; /* Intermediate values */
1706
1707 /* Compute a1, b1, c1, where line joining points 1 and 2
1708 * is "a1 x + b1 y + c1 = 0".
1709 */
1710
1711 a1 = y2 - y1;
1712 b1 = x1 - x2;
1713 c1 = x2 * y1 - x1 * y2;
1714
1715 /* Compute r3 and r4.
1716 */
1717 r3 = a1 * x3 + b1 * y3 + c1;
1718 r4 = a1 * x4 + b1 * y4 + c1;
1719
1720 /* Check signs of r3 and r4. If both point 3 and point 4 lie on
1721 * same side of line 1, the line segments do not intersect.
1722 */
1723 if (r3 != 0 && r4 != 0 && SAME_SIGNS( r3, r4 ))
1724 {
1725 return (DONT_INTERSECT);
1726 }
1727
1728 /* Compute a2, b2, c2 */
1729 a2 = y4 - y3;
1730 b2 = x3 - x4;
1731 c2 = x4 * y3 - x3 * y4;
1732
1733 /* Compute r1 and r2 */
1734 r1 = a2 * x1 + b2 * y1 + c2;
1735 r2 = a2 * x2 + b2 * y2 + c2;
1736
1737 /* Check signs of r1 and r2. If both point 1 and point 2 lie
1738 * on same side of second line segment, the line segments do
1739 * not intersect.
1740 */
1741 if (r1 != 0 && r2 != 0 && SAME_SIGNS( r1, r2 ))
1742 {
1743 return (DONT_INTERSECT);
1744 }
1745
1746 /* Line segments intersect: compute intersection point.
1747 */
1748
1749 denom = a1 * b2 - a2 * b1;
1750 if (denom == 0)
1751 {
1752 return (COLLINEAR);
1753 }
1754 offset = denom < 0 ? -denom / 2 : denom / 2;
1755
1756 /* The denom/2 is to get rounding instead of truncating. It
1757 * is added or subtracted to the numerator, depending upon the
1758 * sign of the numerator.
1759 */
1760 /*
1761 num = b1 * c2 - b2 * c1;
1762 *x = ( num < 0 ? num - offset : num + offset ) / denom;
1763 num = a2 * c1 - a1 * c2;
1764 *y = ( num < 0 ? num - offset : num + offset ) / denom;
1765 */
1766
1767 return (DO_INTERSECT);
1768 } /* lines_intersect */
1769
1770 static int clip_line_aprox(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1771 {
1772 int code1, code2;
1773 code1 = clipcode(p1, r);
1774 code2 = clipcode(p2, r);
1775 if (code1 & code2)
1776 {
1777 // line completely invisible!
1778 return 0;
1779 }
1780 else if ((code1 == 0) && (code2 == 0))
1781 {
1782 // line completely visible!
1783 return 1;
1784 }
1785 else if ((code1 == 0) || (code2 == 0))
1786 {
1787 // at least 1 point of line is visible
1788 return 2;
1789 }
1790 else
1791 {
1792 int xx;
1793 int yy;
1794 // top
1795 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);
1796 if (ret_ == DO_INTERSECT)
1797 {
1798 return 3;
1799 }
1800 // bottom
1801 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);
1802 if (ret_ == DO_INTERSECT)
1803 {
1804 return 3;
1805 }
1806 // left
1807 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);
1808 if (ret_ == DO_INTERSECT)
1809 {
1810 return 3;
1811 }
1812 // right
1813 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);
1814 if (ret_ == DO_INTERSECT)
1815 {
1816 return 3;
1817 }
1818 }
1819 // not visible
1820 return 0;
1821 }
1822
1823 static int clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1824 {
1825 int code1, code2, ret = 1;
1826 int dx, dy, dw;
1827 code1 = clipcode(p1, r);
1828 if (code1)
1829 ret |= 2;
1830 code2 = clipcode(p2, r);
1831 if (code2)
1832 ret |= 4;
1833 dx = p2->x - p1->x;
1834 dy = p2->y - p1->y;
1835 dw = p2->w - p1->w;
1836 while (code1 || code2)
1837 {
1838 if (code1 & code2)
1839 {
1840 return 0;
1841 }
1842 if (code1 & 1)
1843 {
1844 p1->y += (r->lu.x - p1->x) * dy / dx;
1845 p1->w += (r->lu.x - p1->x) * dw / dx;
1846 p1->x = r->lu.x;
1847 }
1848 else if (code1 & 2)
1849 {
1850 p1->y += (r->rl.x - p1->x) * dy / dx;
1851 p1->w += (r->rl.x - p1->x) * dw / dx;
1852 p1->x = r->rl.x;
1853 }
1854 else if (code1 & 4)
1855 {
1856 p1->x += (r->lu.y - p1->y) * dx / dy;
1857 p1->w += (r->lu.y - p1->y) * dw / dy;
1858 p1->y = r->lu.y;
1859 }
1860 else if (code1 & 8)
1861 {
1862 p1->x += (r->rl.y - p1->y) * dx / dy;
1863 p1->w += (r->rl.y - p1->y) * dw / dy;
1864 p1->y = r->rl.y;
1865 }
1866 code1 = clipcode(p1, r);
1867 if (code1 & code2)
1868 return 0;
1869 if (code2 & 1)
1870 {
1871 p2->y += (r->lu.x - p2->x) * dy / dx;
1872 p2->w += (r->lu.x - p2->x) * dw / dx;
1873 p2->x = r->lu.x;
1874 }
1875 else if (code2 & 2)
1876 {
1877 p2->y += (r->rl.x - p2->x) * dy / dx;
1878 p2->w += (r->rl.x - p2->x) * dw / dx;
1879 p2->x = r->rl.x;
1880 }
1881 else if (code2 & 4)
1882 {
1883 p2->x += (r->lu.y - p2->y) * dx / dy;
1884 p2->w += (r->lu.y - p2->y) * dw / dy;
1885 p2->y = r->lu.y;
1886 }
1887 else if (code2 & 8)
1888 {
1889 p2->x += (r->rl.y - p2->y) * dx / dy;
1890 p2->w += (r->rl.y - p2->y) * dw / dy;
1891 p2->y = r->rl.y;
1892 }
1893 code2 = clipcode(p2, r);
1894 }
1895 return ret;
1896 }
1897
1898
1899
1900 // --------------- COLORs ---------------
1901 static struct color bicycle_blue = { 0x0000,0x0000,0xf9f9,0xffff }; // RR GG BB AA
1902 static struct color bicycle_green = { 0x0808,0x8a8a,0x0808,0xffff }; // RR GG BB AA
1903 // --------------- COLORs ---------------
1904
1905
1906 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)
1907 {
1908
1909 struct point *p = g_alloca(sizeof(struct point) * (count + 1));
1910 struct wpoint p1, p2;
1911 int i;
1912 int code;
1913 int wmax;
1914 int out = 0;
1915 // const int max_segs = 2000;
1916 int max_segs = 20; // send max this many segments to java with one single call
1917 struct point_rect r = gra->r;
1918
1919
1920 if (order < global_order_level_for_fast_draw)
1921 {
1922 max_segs = 100;
1923 }
1924
1925 //if (count > 30)
1926 //{
1927 // dbg(0,"segment count=%d\n", count);
1928 //}
1929
1930 #if 0
1931 // check if whole line is within a 2x2 pixel square
1932 if (order < 11)
1933 {
1934 const int max_dist = 2*2;
1935 int need_draw = 0;
1936 int diff;
1937 for (i = 0; i < count; i++)
1938 {
1939 if (i > 0)
1940 {
1941 p2.x = pa[i].x;
1942 p2.y = pa[i].y;
1943 diff = (p2.x - p1.x) * (p2.y - p1.y);
1944 if (diff < 0)
1945 {
1946 diff = -diff;
1947 }
1948
1949 if (diff > max_dist)
1950 {
1951 // line is bigger, so we need to draw it
1952 need_draw = 1;
1953 break;
1954 }
1955 }
1956 else
1957 {
1958 p1.x = pa[i - 1].x;
1959 p1.y = pa[i - 1].y;
1960 }
1961 }
1962
1963 if (need_draw == 0)
1964 {
1965 // dont draw this line
1966 return;
1967 }
1968 }
1969 #endif
1970
1971 // calc visible area on screen
1972 wmax = width[0];
1973 r.lu.x -= wmax;
1974 r.lu.y -= wmax;
1975 r.rl.x += wmax;
1976 r.rl.y += wmax;
1977
1978 for (i = 0; i < count; i++)
1979 {
1980 if (i > 0)
1981 {
1982 p1.x = pa[i - 1].x;
1983 p1.y = pa[i - 1].y;
1984 p2.x = pa[i].x;
1985 p2.y = pa[i].y;
1986 /* 0 = invisible, 1 = completely visible, 2,3 = at least part of line visible */
1987 code = clip_line_aprox(&p1, &p2, &r);
1988 // code = 1;
1989
1990 if (code > 0)
1991 {
1992 if (out == 0)
1993 {
1994 p[out].x = p1.x;
1995 p[out].y = p1.y;
1996 out++;
1997 }
1998 p[out].x = p2.x;
1999 p[out].y = p2.y;
2000 out++;
2001
2002 if ((out <= max_segs) && (i < (count - 1)))
2003 {
2004 // ok gather more line segs
2005 continue;
2006 }
2007 }
2008 else // (code == 0)
2009 {
2010 if (out == 0)
2011 {
2012 // first visible line seg not yet found, search on ...
2013 continue;
2014 }
2015 }
2016
2017 // PAINT --- LINE SEGMENTS ------------
2018 // PAINT --- LINE SEGMENTS ------------
2019
2020 if ((poly == 1) || (poly == 0))
2021 {
2022 // normal street
2023 //if (1 == 0)
2024 //{
2025 // // draw as polygon --> OLD method
2026 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 1, order, 0);
2027 //}
2028 //else
2029 //{
2030 // draw as line
2031 if (mark_way == 1)
2032 {
2033 // dbg(0, "CYCLE LANE:001\n");
2034 // mark way with bicycle lanes
2035 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i] + 4, dashes, &bicycle_green, global_clinedrawing_active, 0);
2036 }
2037 else if (mark_way == 2)
2038 {
2039 // dbg(0, "CYCLE LANE:001\n");
2040 // mark way with bicycle tracks
2041 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i] + 4, dashes, &bicycle_blue, global_clinedrawing_active, 0);
2042 }
2043 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c, global_clinedrawing_active, 1);
2044 //draw_lines_count_3++;
2045 //}
2046
2047 // one way arrow
2048 if ((oneway > 0) && (order > 13))
2049 {
2050 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
2051 //draw_lines_count_2++;
2052 }
2053 }
2054 else if (poly == 2)
2055 {
2056 // ******* street is underground ********
2057 // ******* street is underground ********
2058 // ******* street is underground ********
2059
2060 //if (1 == 0)
2061 //{
2062 // // draw as polygon --> OLD method
2063 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 0, order, 0);
2064 //}
2065 //else
2066 //{
2067
2068 if (mark_way == 1)
2069 {
2070 // mark way with bicycle lanes
2071 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i] + 4, 1, dashes, &bicycle_green, 0);
2072 }
2073 else if (mark_way == 2)
2074 {
2075 // mark way with bicycle track
2076 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i] + 4, 1, dashes, &bicycle_blue, 0);
2077 }
2078
2079 // draw as line
2080 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 1, dashes, c, 1);
2081 //draw_lines_count_4++;
2082 //}
2083
2084 // one way arrow
2085 if ((oneway > 0) && (order > 13))
2086 {
2087 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
2088 //draw_lines_count_2++;
2089 }
2090 }
2091 else if (poly == 3)
2092 {
2093 // ******* street has bridge ********
2094 // ******* street has bridge ********
2095 // ******* street has bridge ********
2096
2097 if (mark_way == 1)
2098 {
2099 // mark way with bicycle lanes
2100 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i] + 4, 2, dashes, &bicycle_green, 0);
2101 }
2102 else if (mark_way == 2)
2103 {
2104 // mark way with bicycle track
2105 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i] + 4, 2, dashes, &bicycle_blue, 0);
2106 }
2107
2108 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 2, dashes, c, 1);
2109 //draw_lines_count_4++;
2110
2111 // one way arrow
2112 if ((oneway > 0) && (order > 13))
2113 {
2114 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
2115 //draw_lines_count_2++;
2116 }
2117 }
2118 // --> now NOT used anymore!!
2119 else // poly==0 -> street that is only a line (width=1)
2120 {
2121 // OLD // gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, 0);
2122
2123 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c, global_clinedrawing_active, 1);
2124 //draw_lines_count_3++;
2125
2126 // one way arrow
2127 if ((oneway > 0) && (order > 13))
2128 {
2129 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
2130 //draw_lines_count_2++;
2131 }
2132 }
2133
2134 out = 0; // reset point counter after painting
2135 // PAINT --- LINE SEGMENTS ------------
2136 // PAINT --- LINE SEGMENTS ------------
2137 // PAINT --- LINE SEGMENTS ------------
2138 }
2139 }
2140 }
2141
2142 static int is_inside(struct point *p, struct point_rect *r, int edge)
2143 {
2144 switch (edge)
2145 {
2146 case 0:
2147 return p->x >= r->lu.x;
2148 case 1:
2149 return p->x <= r->rl.x;
2150 case 2:
2151 return p->y >= r->lu.y;
2152 case 3:
2153 return p->y <= r->rl.y;
2154 default:
2155 return 0;
2156 }
2157 }
2158
2159 static void poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
2160 {
2161 int dx = p2->x - p1->x;
2162 int dy = p2->y - p1->y;
2163 switch (edge)
2164 {
2165 case 0:
2166 ret->y = p1->y + (r->lu.x - p1->x) * dy / dx;
2167 ret->x = r->lu.x;
2168 break;
2169 case 1:
2170 ret->y = p1->y + (r->rl.x - p1->x) * dy / dx;
2171 ret->x = r->rl.x;
2172 break;
2173 case 2:
2174 ret->x = p1->x + (r->lu.y - p1->y) * dx / dy;
2175 ret->y = r->lu.y;
2176 break;
2177 case 3:
2178 ret->x = p1->x + (r->rl.y - p1->y) * dx / dy;
2179 ret->y = r->rl.y;
2180 break;
2181 }
2182 }
2183
2184 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
2185 {
2186 struct point_rect r = gra->r;
2187 struct point *pout, *p, *s, pi, *p1, *p2;
2188 int limit = 10000;
2189 struct point *pa1 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2190 struct point *pa2 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2191 int count_out, edge = 3;
2192 int i;
2193 #if 0
2194 r.lu.x+=20;
2195 r.lu.y+=20;
2196 r.rl.x-=20;
2197 r.rl.y-=20;
2198 #endif
2199 if (count_in < limit)
2200 {
2201 p1 = pa1;
2202 p2 = pa2;
2203 }
2204 else
2205 {
2206 p1 = g_new0(struct point, count_in*8+1);
2207 p2 = g_new0(struct point, count_in*8+1);
2208 }
2209
2210 pout=p1;
2211 for (edge = 0; edge < 4; edge++)
2212 {
2213 p=pin;
2214 s=pin+count_in-1;
2215 count_out=0;
2216 for (i = 0; i < count_in; i++)
2217 {
2218 if (is_inside(p, &r, edge))
2219 {
2220 if (! is_inside(s, &r, edge))
2221 {
2222 poly_intersection(s,p,&r,edge,&pi);
2223 pout[count_out++]=pi;
2224 }
2225 pout[count_out++]=*p;
2226 }
2227 else
2228 {
2229 if (is_inside(s, &r, edge))
2230 {
2231 poly_intersection(p,s,&r,edge,&pi);
2232 pout[count_out++]=pi;
2233 }
2234 }
2235 s=p;
2236 p++;
2237 }
2238 count_in=count_out;
2239 if (pin == p1)
2240 {
2241 pin=p2;
2242 pout=p1;
2243 }
2244 else
2245 {
2246 pin=p1;
2247 pout=p2;
2248 }
2249 }
2250
2251
2252
2253 gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
2254 if (count_in >= limit)
2255 {
2256 g_free(p1);
2257 g_free(p2);
2258 }
2259 }
2260
2261 static void display_context_free(struct display_context *dc)
2262 {
2263 if (dc->gc)
2264 graphics_gc_destroy(dc->gc);
2265 if (dc->gc_background)
2266 graphics_gc_destroy(dc->gc_background);
2267 if (dc->img)
2268 graphics_image_free(dc->gra, dc->img);
2269 dc->gc = NULL;
2270 dc->gc_background = NULL;
2271 dc->img = NULL;
2272 }
2273
2274 static struct graphics_font *
2275 get_font(struct graphics *gra, int size)
2276 {
2277 if (size > 64)
2278 {
2279 size = 64;
2280 }
2281
2282 if (size >= gra->font_len)
2283 {
2284 gra->font=g_renew(struct graphics_font *, gra->font, size+1);
2285 while (gra->font_len <= size)
2286 {
2287 gra->font[gra->font_len++] = NULL;
2288 }
2289 }
2290
2291 if (!gra->font[size])
2292 {
2293 gra->font[size] = graphics_font_new(gra, size * gra->font_size, 0);
2294 }
2295
2296 return gra->font[size];
2297 }
2298
2299 void graphics_draw_text_std(struct graphics *this_, int text_size, char *text, struct point *p)
2300 {
2301 struct graphics_font *font = get_font(this_, text_size);
2302 struct point bbox[4];
2303 int i;
2304
2305 graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
2306 for (i = 0; i < 4; i++)
2307 {
2308 bbox[i].x += p->x;
2309 bbox[i].y += p->y;
2310 }
2311 graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x - bbox[0].x, bbox[0].y - bbox[1].y + 5);
2312 graphics_draw_text(this_, this_->gc[1], this_->gc[2], font, text, p, 0x10000, 0);
2313 }
2314
2315 char *
2316 graphics_icon_path(char *icon)
2317 {
2318 static char *navit_sharedir;
2319 char *ret = NULL;
2320 struct file_wordexp *wordexp = NULL;
2321 // dbg(1, "enter %s\n", icon);
2322 if (strchr(icon, '$'))
2323 {
2324 wordexp = file_wordexp_new(icon);
2325 if (file_wordexp_get_count(wordexp))
2326 {
2327 icon = file_wordexp_get_array(wordexp)[0];
2328 }
2329 }
2330
2331 if (strchr(icon, '/'))
2332 {
2333 ret = g_strdup(icon);
2334 }
2335 else
2336 {
2337 #ifdef HAVE_API_ANDROID
2338 // get resources for the correct screen density
2339 //
2340 // this part not needed, android unpacks only the correct version into res/drawable dir!
2341 // // dbg(1,"android icon_path %s\n",icon);
2342 // static char *android_density;
2343 // android_density = getenv("ANDROID_DENSITY");
2344 // ret=g_strdup_printf("res/drawable-%s/%s",android_density ,icon);
2345 ret=g_strdup_printf("res/drawable/%s" ,icon);
2346 #else
2347 if (!navit_sharedir)
2348 {
2349 navit_sharedir = getenv("NAVIT_SHAREDIR");
2350 }
2351 ret = g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
2352 #endif
2353 }
2354
2355 if (wordexp)
2356 {
2357 file_wordexp_destroy(wordexp);
2358 }
2359
2360 return ret;
2361 }
2362
2363 static int limit_count(struct coord *c, int count)
2364 {
2365 int i;
2366 for (i = 1; i < count; i++)
2367 {
2368 if (c[i].x == c[0].x && c[i].y == c[0].y)
2369 return i + 1;
2370 }
2371 return count;
2372 }
2373
2374 static void displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc, int order, int allow_dashed, int run_type, int is_first)
2375 {
2376
2377 int *width = g_alloca(sizeof(int) * dc->maxlen);
2378 struct point *pa = g_alloca(sizeof(struct point) * dc->maxlen);
2379 struct graphics *gra = dc->gra;
2380 struct graphics_gc *gc = dc->gc;
2381 struct element *e = dc->e;
2382 struct graphics_image *img = dc->img;
2383 struct point p;
2384 char *path;
2385 struct color custom_color;
2386 int dont_draw = 0;
2387
2388 int oneway;
2389 int mark_way;
2390
2391 //if (run_type > 100) // dbg(0,"enter\n");
2392
2393 while (di)
2394 {
2395
2396 // stop drawing is requested
2397 if (cancel_drawing_global == 1)
2398 {
2399 break;
2400 }
2401
2402 if (run_type != 99)
2403 {
2404 if (run_type == 1)
2405 {
2406 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2407 {
2408 // next item
2409 di = di->next;
2410 continue;
2411 }
2412 else if (di->item.flags & NAVIT_AF_BRIDGE)
2413 {
2414 // next item
2415 di = di->next;
2416 continue;
2417 }
2418 }
2419 else if (run_type == 2)
2420 {
2421 // tunnel
2422 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2423 {
2424 }
2425 else
2426 {
2427 // next item
2428 di = di->next;
2429 continue;
2430 }
2431 }
2432 else if (run_type == 3)
2433 {
2434 // bridge
2435 if (di->item.flags & NAVIT_AF_BRIDGE)
2436 {
2437 }
2438 else
2439 {
2440 // next item
2441 di = di->next;
2442 continue;
2443 }
2444 }
2445 }
2446
2447 int i, count = di->count, mindist = dc->mindist;
2448
2449 if (!gc)
2450 {
2451 gc = graphics_gc_new(gra);
2452
2453 if (dc->e->type == element_polyline)
2454 {
2455 if (global_night_mode == 1)
2456 {
2457 graphics_gc_set_foreground(gc, &e->u.polyline.nightcol);
2458 // 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);
2459 }
2460 else
2461 {
2462 graphics_gc_set_foreground(gc, &e->color);
2463 }
2464 }
2465 else
2466 {
2467 graphics_gc_set_foreground(gc, &e->color);
2468 }
2469 dc->gc = gc;
2470 }
2471
2472 if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
2473 {
2474 count = limit_count(di->c, count);
2475 }
2476
2477 if (dc->type == type_poly_water_tiled)
2478 {
2479 mindist = 0;
2480 if (order < 12)
2481 {
2482 mindist = 4;
2483 }
2484 }
2485 else if (dc->type == type_border_country)
2486 {
2487 if (order < 10)
2488 {
2489 mindist = 4;
2490 }
2491 }
2492 else if (dc->type == type_poly_wood_from_triang)
2493 {
2494 if (order > 11)
2495 {
2496 mindist = 0;
2497 }
2498 }
2499 else if (dc->type == type_poly_water_from_triang)
2500 {
2501 if (order > 10)
2502 {
2503 mindist = 0;
2504 }
2505 }
2506 #if 0
2507 else
2508 {
2509 if (order < global_order_level_for_fast_draw)
2510 {
2511 dbg(0, "else: mindist_old=%d\n", mindist);
2512 mindist = 5;
2513 dbg(0, "else: mindist_new=%d\n", mindist);
2514 }
2515 }
2516 #endif
2517 //dbg(0, "mindist now=%d\n", mindist);
2518
2519
2520 if (dc->e->type == element_polyline)
2521 {
2522 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
2523 }
2524 else
2525 {
2526 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
2527 }
2528
2529 //dbg(0,"**dc->type=%s count=%d\n", item_to_name(dc->type), count);
2530 //dbg(0,"** e->type=%s\n", item_to_name(e->type));
2531
2532
2533 // system_log(0,"**dc->type=%s count=%d\n", item_to_name(dc->type), count);
2534 // system_log(0,"** e->type=%s int=%d\n", item_to_name(e->type), e->type);
2535
2536 switch (e->type)
2537 {
2538 case element_polygon:
2539 graphics_draw_polygon_clipped(gra, gc, pa, count);
2540 break;
2541 case element_polyline:
2542 {
2543 gc->meth.gc_set_linewidth(gc->priv, 1);
2544
2545 int poly = e->u.polyline.width > 1;
2546
2547 // detect underground streets/lines/etc ...
2548 //if ((allow_dashed) && (di->item.flags & NAVIT_AF_UNDERGROUND))
2549 if (di->item.flags & NAVIT_AF_UNDERGROUND)
2550 {
2551 poly = 2;
2552 }
2553 else if (di->item.flags & NAVIT_AF_BRIDGE)
2554 {
2555 poly = 3;
2556 }
2557
2558 oneway = 0;
2559 if (di->item.flags & NAVIT_AF_ONEWAYREV)
2560 {
2561 oneway = 2;
2562 if (di->item.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)
2563 {
2564 oneway = oneway + 4; // oneway does not apply to bicycles here
2565 }
2566 }
2567 else if (di->item.flags & NAVIT_AF_ONEWAY)
2568 {
2569 oneway = 1;
2570 if (di->item.flags & NAVIT_AF_ONEWAY_BICYCLE_NO)
2571 {
2572 oneway = oneway + 4; // oneway does not apply to bicycles here
2573 }
2574 }
2575
2576 mark_way = 0;
2577 // dbg(0, "CYCLE LANE:002 is_first=%d\n", is_first);
2578 if ((dc->type != type_cycleway) && (is_first == 1) && ((global_vehicle_profile == 1) || (global_vehicle_profile == 2)))
2579 {
2580 if (di->item.flags & NAVIT_AF_BICYCLE_LANE)
2581 {
2582 mark_way = 1; // way with cycle lane
2583 }
2584 else if (di->item.flags & NAVIT_AF_BICYCLE_TRACK)
2585 {
2586 mark_way = 2; // way with cycle track (sperate bicycle lane)
2587 }
2588 }
2589
2590 // -------- apply dashes -------
2591 //if (e->u.polyline.dash_num > 0)
2592 //{
2593 // 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);
2594 //}
2595 // -------- apply dashes -------
2596
2597 //for (i = 0; i < count; i++)
2598 //{
2599 // if (width[i] < 1)
2600 // {
2601 // width[i] = 1;
2602 // }
2603 //}
2604
2605 if (dc->type == type_border_country)
2606 {
2607 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway, e->u.polyline.dash_num, &e->color, 0);
2608 }
2609 else
2610 {
2611 // use custom color for underground trains
2612 if (dc->type == type_rail_subway)
2613 {
2614 //dbg(0, "colour1=r:%d g:%d b:%d a:%d\n", e->color.r, e->color.g, e->color.b, e->color.a);
2615 if (di->col_int_value != 0)
2616 {
2617 //dbg(0, "colour2=r:%d g:%d b:%d a:%d\n", di->color.r, di->color.g, di->color.b, di->color.a);
2618 //e->color.r = di->color.r;
2619 //e->color.g = di->color.g;
2620 //e->color.b = di->color.b;
2621 //e->color.a = di->color.a;
2622 custom_color.r = (di->col_int_value >> 16) & 0xff;
2623 custom_color.g = (di->col_int_value >> 8) & 0xff;
2624 custom_color.b = di->col_int_value & 0xff;
2625
2626 custom_color.r = custom_color.r << 8;
2627 custom_color.g = custom_color.g << 8;
2628 custom_color.b = custom_color.b << 8;
2629
2630 custom_color.a = 0xffff;
2631
2632 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &custom_color, 0);
2633 }
2634 else
2635 {
2636 if (global_night_mode == 1)
2637 {
2638 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->u.polyline.nightcol, 0);
2639 }
2640 else
2641 {
2642 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->color, 0);
2643 }
2644 }
2645 }
2646 // change color of route if in bicycle-route-mode and we want to drive against the oneway street
2647 else if ((dc->type == type_street_route || dc->type == type_street_route_waypoint) && (global_vehicle_profile == 1) && ((di->col_int_value >> 26) & 3))
2648 {
2649 // if oneway and route goes against it
2650 if ( ((di->col_int_value >> 24) & 2) && ((di->col_int_value >> 26) & 1) )
2651 {
2652 //struct attr attr_98;
2653 //if (item_attr_get(&(di->item), attr_direction, &attr_98))
2654 //{
2655
2656 // custom_color.a = ((di->col_int_value >> 24) & 3); // "1" == 1 , "-1" == 3 , "0" == 0 direction of route on street
2657 // ((di->col_int_value >> 26) & 3) // 1 == NAVIT_AF_ONEWAY, 2 == NAVIT_AF_ONEWAYREV
2658
2659 // dbg(0, "direction(2).0=%x\n", di->col_int_value);
2660 // dbg(0, "direction(2)=%x oneway bicycle=%d\n", custom_color.a, ((di->col_int_value >> 26) & 3));
2661 //}
2662
2663 // mark route in ORANGE here
2664 custom_color.r = 0xff << 8;
2665 custom_color.g = 0x80 << 8;
2666 custom_color.b = 0x00 << 8;
2667
2668 custom_color.a = 0xffff;
2669
2670 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &custom_color, 0);
2671 }
2672 else
2673 {
2674 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->color, 0);
2675 }
2676 }
2677 else // all other ways
2678 {
2679 if (global_night_mode == 1)
2680 {
2681 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->u.polyline.nightcol, mark_way);
2682 }
2683 else
2684 {
2685 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->color, mark_way);
2686 }
2687 }
2688 }
2689
2690 // -------- cancel dashes -------
2691 //if (e->u.polyline.dash_num > 0)
2692 //{
2693 // int dummy_1[1];
2694 // dummy_1[0] = 0;
2695 // graphics_gc_set_dashes(gra, gc, e->u.polyline.width, e->u.polyline.offset, dummy_1, e->u.polyline.dash_num, order);
2696 //}
2697 //if (run_type > 100) // dbg(0,"gg005\n");
2698 // -------- cancel dashes -------
2699 }
2700 break;
2701 case element_circle:
2702 if (count)
2703 {
2704 //// dbg(0, "graphics_draw_circle\n");
2705
2706 if (di->label)
2707 {
2708 dont_draw = 0;
2709 // 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));
2710 // count labels and poi-texts and stop after drawing more than n of those
2711 if (item_is_poi(dc->type))
2712 {
2713 if (
2714 (poi_on_map_count > MAX_POI_ICON_TEXTS_ON_MAP) &&
2715 ((long)global_scale > (long)ORDER2_LEVEL_TO_SHOW_ALL_POI)
2716 )
2717 {
2718 dont_draw = 1;
2719 }
2720 else
2721 {
2722 poi_on_map_count++;
2723 }
2724 }
2725 else if (item_is_town_label_no_major(dc->type))
2726 {
2727 if (label_on_map_count > MAX_PLACE_LABELS_ON_MAP)
2728 {
2729 dont_draw = 1;
2730 }
2731 else
2732 {
2733 label_on_map_count++;
2734 }
2735 }
2736 else if (item_is_town_label_major(dc->type))
2737 {
2738 if (label_major_on_map_count > MAX_MAJOR_PLACE_LABELS_ON_MAP)
2739 {
2740 dont_draw = 1;
2741 }
2742 else
2743 {
2744 label_major_on_map_count++;
2745 }
2746 }
2747 else if (item_is_district_label(dc->type))
2748 {
2749 // dbg(0, "district:%s\n", di->label);
2750
2751 if (label_district_on_map_count > MAX_DISTRICT_LABELS_ON_MAP)
2752 {
2753 dont_draw = 1;
2754 }
2755 else
2756 {
2757 //dbg(0, "district *DRAW*\n");
2758 label_district_on_map_count++;
2759 }
2760 }
2761
2762
2763 if (dont_draw == 0)
2764 {
2765 if (e->u.circle.width > 1)
2766 {
2767 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
2768 }
2769 graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
2770
2771 // -----------------------------
2772
2773 if (e->text_size)
2774 {
2775 struct graphics_font *font = get_font(gra, e->text_size);
2776 struct graphics_gc *gc_background = dc->gc_background;
2777 if (!gc_background && e->u.circle.background_color.a)
2778 {
2779 gc_background = graphics_gc_new(gra);
2780 graphics_gc_set_foreground(gc_background, &e->u.circle.background_color);
2781 dc->gc_background = gc_background;
2782 }
2783 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
2784 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)
2785
2786 if (font)
2787 {
2788 gra->meth.draw_text(gra->priv, gc->priv, gc_background ? gc_background->priv : NULL, font->priv, di->label, &p, 0x10000, 0);
2789 }
2790 else
2791 {
2792 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2793 }
2794
2795 }
2796 }
2797 }
2798 else // circle without label
2799 {
2800 if (dont_draw == 0)
2801 {
2802 if (e->u.circle.width > 1)
2803 {
2804 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
2805 }
2806 graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
2807 }
2808 }
2809 }
2810 break;
2811 case element_text:
2812 if (count && di->label)
2813 {
2814 //if (run_type > 100) // dbg(0,"gg006\n");
2815
2816 struct graphics_font *font = get_font(gra, e->text_size);
2817 struct graphics_gc *gc_background = dc->gc_background;
2818
2819 if (!gc_background && e->u.text.background_color.a)
2820 {
2821 gc_background = graphics_gc_new(gra);
2822 graphics_gc_set_foreground(gc_background, &e->u.text.background_color);
2823 dc->gc_background = gc_background;
2824 }
2825
2826 if (font)
2827 {
2828 if (order > 8)
2829 {
2830 label_line(gra, gc, gc_background, font, pa, count, di->label);
2831 }
2832 }
2833 else
2834 {
2835 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2836 }
2837 }
2838 break;
2839 case element_icon:
2840 if (count)
2841 {
2842 dont_draw = 0;
2843
2844 // dbg(0,"MAP:poi-on_map:#%d:%s\n", poi_icon_on_map_count, item_to_name(dc->type));
2845
2846 if (item_is_poi(dc->type))
2847 {
2848 if (
2849 (poi_icon_on_map_count > MAX_POI_ICONS_ON_MAP) &&
2850 ((long)global_scale > (long)ORDER2_LEVEL_TO_SHOW_ALL_POI)
2851 )
2852 {
2853 // send_alert_to_java(99, "POI-filter:002:dont draw POI icon");
2854 dont_draw = 1;
2855 }
2856 else
2857 {
2858 poi_icon_on_map_count++;
2859 }
2860 }
2861
2862 if (dont_draw == 0)
2863 {
2864 if (!img || item_is_custom_poi(di->item))
2865 {
2866 if (item_is_custom_poi(di->item))
2867 {
2868 char *icon;
2869 char *src;
2870 if (img)
2871 {
2872 graphics_image_free(dc->gra, img);
2873 }
2874 src = e->u.icon.src;
2875 if (!src || !src[0])
2876 {
2877 src = "%s";
2878 }
2879 icon = g_strdup_printf(src, di->label + strlen(di->label) + 1);
2880
2881 path = graphics_icon_path(icon);
2882 g_free(icon);
2883 }
2884 else
2885 {
2886 path = graphics_icon_path(e->u.icon.src);
2887
2888 // dbg(0,"MAP:icon=%s\n", path);
2889 }
2890
2891 img = graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
2892 if (img)
2893 {
2894 dc->img = img;
2895
2896 // compensate for streched images on high dpi devices
2897 img->hot.x = (int)((float)(img->hot.x) / (float)global_dpi_factor);
2898 img->hot.y = (int)((float)(img->hot.y) / (float)global_dpi_factor);
2899
2900 // dbg(0, "POI_ICON:img2_factor=%f\n", (float)global_dpi_factor);
2901 // dbg(0, "POI_ICON:img2_h=%d\n", img->height);
2902 // dbg(0, "POI_ICON:img2_w=%d\n", img->width);
2903 // dbg(0, "POI_ICON:img2_hotx=%d\n", img->hot.x);
2904 // dbg(0, "POI_ICON:img2_hoty=%d\n", img->hot.y);
2905 // dbg(0, "POI_ICON:img2_icon: '%s'\n", path);
2906
2907 }
2908 else
2909 {
2910 // missing icon //
2911 dbg(0, "-- ICON MISSING -- failed to load icon '%s'\n", path);
2912 }
2913
2914 g_free(path);
2915 }
2916
2917 if (img)
2918 {
2919 p.x = pa[0].x - img->hot.x;
2920 p.y = pa[0].y - img->hot.y;
2921
2922 //// dbg(0,"hot: %d %d\n", img->hot.x, img->hot.y);
2923 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
2924 }
2925 }
2926 }
2927 break;
2928 case element_image:
2929 //dbg(0, "***image***: '%s'\n", di->label);
2930 if (gra->meth.draw_image_warp)
2931 {
2932 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2933 }
2934 //else
2935 //{
2936 // dbg(0,"draw_image_warp not supported by graphics driver drawing: image='%s' count=%d\n",di->label, count);
2937 //}
2938 break;
2939 case element_maptile: // same as image, just has a diferent name in the mapfile, so we can do cool things with it!
2940 //dbg(0, "***maptile***: '%s'\n", di->label);
2941 if (gra->meth.draw_image_warp)
2942 {
2943 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2944 }
2945 //else
2946 //{
2947 // dbg(0,"draw_image_warp not supported by graphics driver drawing: image='%s' count=%d\n",di->label, count);
2948 //}
2949 break;
2950 case element_arrows:
2951 display_draw_arrows(gra, gc, pa, count);
2952 break;
2953 //default:
2954 // dbg(0, "Unhandled element type %d\n", e->type);
2955 // printf("Unhandled element type %d\n", e->type);
2956 // system_log(0, "Unhandled element type %d\n", e->type);
2957 }
2958 di = di->next;
2959 }
2960
2961 //if (run_type > 100) // dbg(0,"gg099\n");
2962 }
2963
2964
2965
2966
2967
2968 /**
2969 * FIXME
2970 * @param <>
2971 * @returns <>
2972 * @author Martin Schaller (04/2008)
2973 */
2974 static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, int run_type)
2975 {
2976
2977 struct element *e;
2978 GList *es, *types;
2979 struct display_context *dc = &display_list->dc;
2980 struct hash_entry *entry;
2981 int draw_it = 1;
2982 int is_first_item = 1;
2983
2984 #ifdef NAVIT_MEASURE_TIME_DEBUG
2985 clock_t s_ = debug_measure_start();
2986 #endif
2987
2988 is_first_item = 1;
2989
2990 es = itm->elements;
2991 while (es)
2992 {
2993 //// dbg(0,"*es\n");
2994 e = es->data;
2995 dc->e = e;
2996 types = itm->type;
2997 while (types)
2998 {
2999 draw_it = 1;
3000
3001 // stop drawing is requested
3002 if (cancel_drawing_global == 1)
3003 {
3004 break;
3005 }
3006
3007 dc->type = GPOINTER_TO_INT(types->data);
3008 // dbg(0,"**type=%s\n", item_to_name(dc->type));
3009 // system_log(0,"**type=%s\n", item_to_name(dc->type));
3010
3011 if (global_draw_multipolygons == 0)
3012 {
3013 if (dc->type == type_poly_water_from_relations)
3014 {
3015 // ok "poly_water_from_relations" is found, now what?
3016 draw_it = 0;
3017 }
3018 else if (dc->type == type_poly_water_from_triang)
3019 {
3020 draw_it = 0;
3021 }
3022 else if (dc->type == type_wood_from_relations)
3023 {
3024 draw_it = 0;
3025 }
3026 else if (dc->type == type_poly_wood_from_triang)
3027 {
3028 draw_it = 0;
3029 }
3030 else if (dc->type == type_poly_building_from_triang)
3031 {
3032 draw_it = 0;
3033 }
3034 }
3035
3036 if (draw_it == 1)
3037 {
3038 entry = get_hash_entry(display_list, dc->type);
3039 if (entry && entry->di)
3040 {
3041 //dbg(0,"++type=%s\n", item_to_name(dc->type));
3042
3043 // system_log(0,"++type=%s\n", item_to_name(dc->type));
3044
3045 //dbg(0, "is_first_item=%d run_type=%d\n", is_first_item, run_type);
3046 //if (!strcmp(item_to_name(dc->type), "border_country"))
3047 //{
3048 // displayitem_draw(entry->di, NULL, dc, display_list->order, 1, 101);
3049 //}
3050 //else
3051 //{
3052 displayitem_draw(entry->di, NULL, dc, display_list->order, 1, run_type, is_first_item);
3053 is_first_item = 0;
3054 //}
3055 // // dbg(0,"**+gc free\n");
3056 display_context_free(dc);
3057 }
3058 }
3059 types = g_list_next(types);
3060 draw_it = 1;
3061 }
3062 es = g_list_next(es);
3063 }
3064
3065 #ifdef NAVIT_MEASURE_TIME_DEBUG
3066 debug_mrp("xdisplay_draw_elements:", debug_measure_end(s_));
3067 #endif
3068
3069
3070 }
3071
3072 void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
3073 {
3074 // dbg(0, "EEnter\n");
3075
3076 // HINT: seems to only be called from vehicle.c (draw the vehicle on screen)
3077
3078 GList *es;
3079 struct display_context dc;
3080 int max_coord = 32;
3081 char *buffer = g_alloca(sizeof(struct displayitem) + max_coord * sizeof(struct coord));
3082 struct displayitem *di = (struct displayitem *) buffer;
3083 es = itm->elements;
3084 di->item.type = type_none;
3085 di->item.id_hi = 0;
3086 di->item.id_lo = 0;
3087 di->item.map = NULL;
3088 di->label = label;
3089 dc.gra = gra;
3090 dc.gc = NULL;
3091 dc.gc_background = NULL;
3092 dc.img = NULL;
3093 dc.pro = projection_screen;
3094 dc.mindist = 0;
3095 dc.trans = t;
3096 dc.type = type_none;
3097 dc.maxlen = max_coord;
3098 while (es)
3099 {
3100 // dbg(0, "while loop\n");
3101 struct element *e = es->data;
3102 if (e->coord_count)
3103 {
3104 if (e->coord_count > max_coord)
3105 {
3106 //DBG // dbg(0, "maximum number of coords reached: %d > %d\n", e->coord_count, max_coord);
3107 di->count = max_coord;
3108 }
3109 else
3110 {
3111 di->count = e->coord_count;
3112 }
3113 memcpy(di->c, e->coord, di->count * sizeof(struct coord));
3114 }
3115 else
3116 {
3117 di->c[0].x = 0;
3118 di->c[0].y = 0;
3119 di->count = 1;
3120 }
3121 dc.e = e;
3122 di->next = NULL;
3123 displayitem_draw(di, NULL, &dc, transform_get_scale(t), 0, 99, 0);
3124 display_context_free(&dc);
3125 es = g_list_next(es);
3126 }
3127 }
3128
3129 /**
3130 * FIXME
3131 * @param <>
3132 * @returns <>
3133 * @author Martin Schaller (04/2008)
3134 */
3135 static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order)
3136 {
3137
3138 GList *itms;
3139 struct itemgra *itm;
3140
3141 int run_type = 0; // 99 -> normal
3142 // 1 -> normal streets (except tunnels and bridges)
3143 // 2 -> tunnel
3144 // 3 -> bridge
3145
3146 int send_refresh = 0;
3147
3148 int order_corrected = order + shift_order;
3149 if (order_corrected < limit_order_corrected)
3150 {
3151 order_corrected = limit_order_corrected;
3152 }
3153
3154 int order_corrected_2 = order + shift_order;
3155 if (order < 0)
3156 {
3157 order_corrected_2 = 0;
3158 }
3159
3160 int fast_draw_mode = 0;
3161 //dbg(0,"orderlevel=%d\n", order);
3162 if (order < global_order_level_for_fast_draw)
3163 {
3164 //dbg(0,"fast_draw_mode=1\n");
3165 fast_draw_mode = 1;
3166 run_type = 99; // draw only 1 pass, bridges and tunnels will be drawn in any order
3167 }
3168
3169 // dbg(0,"layer name=%s\n", lay->name);
3170 // system_log(0,"layer name=%s\n", lay->name);
3171
3172 // reset max drawing counters ----------------------
3173 poi_on_map_count = 0;
3174 label_on_map_count = 0;
3175 label_district_on_map_count = 0;
3176 label_major_on_map_count = 0;
3177 poi_icon_on_map_count = 0;
3178 // reset max drawing counters ----------------------
3179
3180
3181 if ((strncmp("streets_1", lay->name, 9) == 0))
3182 {
3183 //// dbg(0,"MT:7.3.1 - tunnel start\n");
3184 //draw_lines_count_2 = 0;
3185 //draw_lines_count_3 = 0;
3186 //draw_lines_count_4 = 0;
3187
3188 send_refresh = 1;
3189
3190 //dbg(0,"a1 fast_draw_mode=%d run_type=%d\n", fast_draw_mode, run_type);
3191
3192
3193 if (fast_draw_mode == 0)
3194 {
3195
3196 //dbg(0,"fast_draw_mode===0 ?\n");
3197
3198
3199 run_type = 2;
3200 itms = lay->itemgras;
3201 while (itms)
3202 {
3203 // stop drawing is requested
3204 if (cancel_drawing_global == 1)
3205 {
3206 //DBG // dbg(0, "** STOP MD 002 **\n");
3207 break;
3208 }
3209
3210 itm = itms->data;
3211 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
3212 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
3213 {
3214 xdisplay_draw_elements(gra, display_list, itm, run_type);
3215 }
3216 itms = g_list_next(itms);
3217 }
3218
3219 //// dbg(0,"lines count2=%lld\n", draw_lines_count_2);
3220 //// dbg(0,"lines count3=%lld\n", draw_lines_count_3);
3221 //// dbg(0,"lines count4=%lld\n", draw_lines_count_4);
3222 //draw_lines_count_2 = 0;
3223 //draw_lines_count_3 = 0;
3224 //draw_lines_count_4 = 0;
3225 //// dbg(0,"MT:7.3.2 - streets start\n");
3226
3227 run_type = 1;
3228 itms = lay->itemgras;
3229 while (itms)
3230 {
3231 // stop drawing is requested
3232 if (cancel_drawing_global == 1)
3233 {
3234 //DBG // dbg(0, "** STOP MD 002 **\n");
3235 break;
3236 }
3237
3238 itm = itms->data;
3239 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
3240 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
3241 {
3242 xdisplay_draw_elements(gra, display_list, itm, run_type);
3243 }
3244 itms = g_list_next(itms);
3245 }
3246
3247 /*
3248 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
3249 // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
3250 // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
3251 draw_lines_count_2 = 0;
3252 draw_lines_count_3 = 0;
3253 draw_lines_count_4 = 0;
3254 // dbg(0,"MT:7.3.3 - bridges start\n");
3255 */
3256
3257 }
3258
3259 //dbg(0,"a2 fast_draw_mode=%d run_type=%d\n", fast_draw_mode, run_type);
3260
3261
3262 if (fast_draw_mode == 0)
3263 {
3264 run_type = 3;
3265 }
3266 else
3267 {
3268 run_type = 99;
3269 }
3270
3271 //dbg(0,"a3 fast_draw_mode=%d run_type=%d\n", fast_draw_mode, run_type);
3272
3273 itms = lay->itemgras;
3274 while (itms)
3275 {
3276 // stop drawing is requested
3277 if (cancel_drawing_global == 1)
3278 {
3279 //DBG // dbg(0, "** STOP MD 002 **\n");
3280 break;
3281 }
3282
3283 itm = itms->data;
3284 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
3285 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
3286 {
3287 xdisplay_draw_elements(gra, display_list, itm, run_type);
3288 }
3289 itms = g_list_next(itms);
3290 }
3291
3292 /*
3293 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
3294 // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
3295 // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
3296 draw_lines_count_2 = 0;
3297 draw_lines_count_3 = 0;
3298 draw_lines_count_4 = 0;
3299 // dbg(0,"MT:7.3.4 - ready\n");
3300 */
3301
3302 }
3303 else
3304 {
3305 run_type = 99;
3306 itms = lay->itemgras;
3307 while (itms)
3308 {
3309 // stop drawing is requested
3310 if (cancel_drawing_global == 1)
3311 {
3312 //DBG // dbg(0, "** STOP MD 002 **\n");
3313 break;
3314 }
3315
3316 itm = itms->data;
3317 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
3318 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
3319 {
3320 xdisplay_draw_elements(gra, display_list, itm, run_type);
3321 }
3322 itms = g_list_next(itms);
3323 }
3324 }
3325
3326 //if (strncmp("streets__tunnel", lay->name, 15) == 0)
3327 //{
3328 //}
3329 //else if (strncmp("streets__bridge", lay->name, 15) == 0)
3330 //{
3331 //}
3332
3333 // dirty hack to draw "waypoint(s)" ---------------------------
3334 if (strncmp("Internal", lay->name, 8) == 0)
3335 {
3336 // if (global_routing_engine != 1)
3337 {
3338 if (global_navit->route)
3339 {
3340 if (global_navit->destination_valid == 1)
3341 {
3342 int count_ = 0;
3343 int curr_ = 0;
3344 count_ = g_list_length(global_navit->route->destinations);
3345 if (count_ > 1)
3346 {
3347 if (!global_img_waypoint)
3348 {
3349 char *path2;
3350 path2 = graphics_icon_path("nav_waypoint_bk_center.png");
3351 global_img_waypoint = graphics_image_new_scaled_rotated(gra, path2, 59, 59, 0);
3352
3353 // compensate for streched images on high dpi devices
3354 global_img_waypoint->hot.x = (int)((float)global_img_waypoint->width / 2.0f / (float)global_dpi_factor);
3355 global_img_waypoint->hot.y = (int)((float)global_img_waypoint->height / 2.0f / (float)global_dpi_factor);
3356
3357 //dbg(0, "img_factor=%f\n", (float)global_dpi_factor);
3358 //dbg(0, "img_h=%d\n", global_img_waypoint->height);
3359 //dbg(0, "img_w=%d\n", global_img_waypoint->width);
3360 //dbg(0, "img_hotx=%d\n", global_img_waypoint->hot.x);
3361 //dbg(0, "img_hoty=%d\n", global_img_waypoint->hot.y);
3362
3363 g_free(path2);
3364 }
3365
3366 struct point p2;
3367 struct coord pc77;
3368 GList *ldest = global_navit->route->destinations;
3369 while (ldest)
3370 {
3371 curr_++;
3372 if (curr_ < count_)
3373 {
3374 struct route_info *dst = ldest->data;
3375 pc77.x = dst->c.x;
3376 pc77.y = dst->c.y;
3377 //// dbg(0, "draw1 curr=%d x y: %d %d\n", curr_, dst->c.x, dst->c.y);
3378 enum projection pro = transform_get_projection(global_navit->trans_cursor);
3379 transform(global_navit->trans, pro, &pc77, &p2, 1, 0, 0, NULL);
3380 // transform(global_navit->trans, projection_mg, &pc77, &p2, 1, 0, 0, NULL);
3381 p2.x = p2.x - global_img_waypoint->hot.x; // hot = 29
3382 p2.y = p2.y - global_img_waypoint->hot.y; // hot = 29
3383 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p2, global_img_waypoint->priv);
3384 }
3385 // next dest. / waypoint
3386 ldest = g_list_next(ldest);
3387 }
3388 }
3389 }
3390 }
3391 }
3392
3393
3394 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3395 enum projection pro3 = transform_get_projection(global_navit->trans_cursor);
3396 struct point *p_temp = g_alloca(sizeof(struct point) * (2 + 1));
3397 #else
3398 #ifdef NAVIT_DEBUG_COORD_LIST
3399 enum projection pro3 = transform_get_projection(global_navit->trans_cursor);
3400 struct point *p_temp = g_alloca(sizeof(struct point) * (2 + 1));
3401 #endif
3402 #endif
3403
3404
3405 #ifdef NAVIT_TRACKING_SHOW_REAL_GPS_POS
3406
3407 if (global_tracking_show_real_gps_pos == 1)
3408 {
3409
3410 // -------- DEBUG -------- draw real GPS position ---------
3411 // -------- DEBUG -------- draw real GPS position ---------
3412 // -------- DEBUG -------- draw real GPS position ---------
3413 if (!global_img_waypoint)
3414 {
3415 char *path2;
3416 path2 = graphics_icon_path("nav_waypoint_bk_center.png");
3417 global_img_waypoint = graphics_image_new_scaled_rotated(gra, path2, 59, 59, 0);
3418
3419 // compensate for streched images on high dpi devices
3420 global_img_waypoint->hot.x = (int)((float)global_img_waypoint->width / 2.0f / (float)global_dpi_factor);
3421 global_img_waypoint->hot.y = (int)((float)global_img_waypoint->height / 2.0f / (float)global_dpi_factor);
3422
3423 g_free(path2);
3424 }
3425
3426 struct coord_geo g33;
3427 struct coord c33;
3428 struct point p2;
3429 g33.lat = global_v_pos_lat;
3430 g33.lng = global_v_pos_lng;
3431
3432 transform_from_geo(projection_mg, &g33, &c33);
3433 enum projection pro = transform_get_projection(global_navit->trans_cursor);
3434
3435
3436 // cos = x
3437 // sin = y
3438 struct point *p_temp3 = g_alloca(sizeof(struct point) * (2 + 1));
3439 struct color debug_red2 = { 0xfafa,0x1010,0x0000,0xffff }; // RR GG BB AA
3440
3441 transform(global_navit->trans, pro, &c33, &p2, 1, 0, 0, NULL);
3442 p_temp3[0].x = p2.x;
3443 p_temp3[0].y = p2.y;
3444
3445 double dd = tracking_get_direction(global_navit->tracking);
3446 double temp_4 = (global_v_pos_dir - dd) - 90.0f;
3447
3448 p_temp3[0].x = p_temp3[0].x + 36 * (navit_cos(temp_4 * M_PI / 180));
3449 p_temp3[0].y = p_temp3[0].y + 36 * (navit_sin(temp_4 * M_PI / 180));
3450
3451 p_temp3[1].x = p_temp3[0].x;
3452 p_temp3[1].y = p_temp3[0].y;
3453
3454 p_temp3[1].x = p_temp3[1].x + 35 * (navit_cos(temp_4 * M_PI / 180));
3455 p_temp3[1].y = p_temp3[1].y + 35 * (navit_sin(temp_4 * M_PI / 180));
3456
3457 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp3, 2, 15, 14, 0, &debug_red2, global_clinedrawing_active, 1);
3458
3459
3460 #if 0
3461 // WINNER Segment on route segment --------------
3462 struct point *p_temp_win_3 = g_alloca(sizeof(struct point) * (2 + 1));
3463 struct color debug_win_blue2 = { 0x0000,0x0000,0xfafa,0xffff }; // RR GG BB AA
3464 struct point p_win2;
3465
3466 transform(global_navit->trans, pro, &global_debug_route_seg_winner_p_start, &p_win2, 1, 0, 0, NULL);
3467 p_temp_win_3[0].x = p_win2.x - 140;
3468 p_temp_win_3[0].y = p_win2.y;
3469
3470 p_temp_win_3[1].x = p_win2.x + 140;
3471 p_temp_win_3[1].y = p_win2.y;
3472
3473 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);
3474
3475 p_temp_win_3[0].x = p_win2.x;
3476 p_temp_win_3[0].y = p_win2.y - 140;
3477
3478 p_temp_win_3[1].x = p_win2.x;
3479 p_temp_win_3[1].y = p_win2.y + 140;
3480
3481 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);
3482
3483 // WINNER Segment on route segment --------------
3484 #endif
3485
3486 #if 0
3487 // WINNER route segment direction --------------
3488
3489 struct color debug_win_green2 = { 0x0000,0xfafa,0x0000,0xffff }; // RR GG BB AA
3490
3491 transform(global_navit->trans, pro, &global_debug_route_seg_winner_start, &p_win2, 1, 0, 0, NULL);
3492
3493 p_temp_win_3[0].x = p_win2.x - 90;
3494 p_temp_win_3[0].y = p_win2.y;
3495
3496 p_temp_win_3[1].x = p_win2.x + 90;
3497 p_temp_win_3[1].y = p_win2.y;
3498
3499 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);
3500
3501
3502
3503 p_temp_win_3[0].x = p_win2.x;
3504 p_temp_win_3[0].y = p_win2.y;
3505
3506 transform(global_navit->trans, pro, &global_debug_route_seg_winner_end, &p_win2, 1, 0, 0, NULL);
3507
3508 p_temp_win_3[1].x = p_win2.x;
3509 p_temp_win_3[1].y = p_win2.y;
3510
3511 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);
3512
3513 // WINNER route segment direction --------------
3514 #endif
3515
3516
3517
3518 // ------ text -------
3519 graphics_gc_set_foreground(gra->gc[0], &debug_red2);
3520 graphics_gc_set_linewidth(gra->gc[0], 8);
3521 struct point p7;
3522 struct graphics_font *font8 = get_font(gra, 21);
3523 char *dir_label=g_strdup_printf("%4.1f : %4.1f", (float)global_v_pos_dir, (float)dd);
3524 p7.x = p2.x + 25; // move text label a bit to the right, so it does not overlap the circle
3525 p7.y = p2.y - 160; // move label a bit up (y-axis)
3526 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, dir_label, &p7, 0x10000, 0);
3527 g_free(dir_label);
3528 // ------ text -------
3529
3530
3531 p2.x = p2.x - global_img_waypoint->hot.x; // hot = 29
3532 p2.y = p2.y - global_img_waypoint->hot.y; // hot = 29
3533 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p2, global_img_waypoint->priv);
3534
3535 // -------- DEBUG -------- draw real GPS position ---------
3536 // -------- DEBUG -------- draw real GPS position ---------
3537 // -------- DEBUG -------- draw real GPS position ---------
3538
3539 }
3540
3541 #endif
3542
3543 #ifdef NAVIT_ROUTING_DEBUG_PRINT
3544
3545 // -------- DEBUG -------- draw winner track segment ---------
3546 // -------- DEBUG -------- draw winner track segment ---------
3547 // -------- DEBUG -------- draw winner track segment ---------
3548 struct color debug_orange = { 0xffff,0x4040,0x0000,0xffff }; // RR GG BB AA
3549
3550 if (global_navit->route)
3551 {
3552 if (global_navit->destination_valid == 1)
3553 {
3554 transform(global_navit->trans, pro3, &global_debug_route_seg_winner_start, &p_temp[0], 1, 0, 0, NULL);
3555 transform(global_navit->trans, pro3, &global_debug_route_seg_winner_end, &p_temp[1], 1, 0, 0, NULL);
3556 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp, 2, 15, 30, 0, &debug_orange, global_clinedrawing_active, 1);
3557 }
3558 }
3559
3560 struct color debug_turkoise = { 0x0404,0xb4b4,0xaeae,0xffff }; // RR GG BB AA
3561 transform(global_navit->trans, pro3, &global_debug_seg_winner_start, &p_temp[0], 1, 0, 0, NULL);
3562 transform(global_navit->trans, pro3, &global_debug_seg_winner_end, &p_temp[1], 1, 0, 0, NULL);
3563 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp, 2, 15, 20, 0, &debug_turkoise, global_clinedrawing_active, 1);
3564
3565
3566 if (global_navit->route)
3567 {
3568 if (global_navit->destination_valid == 1)
3569 {
3570 struct color debug_red = { 0xffff,0x0000,0x0000,0xffff }; // RR GG BB AA
3571 graphics_gc_set_foreground(gra->gc[0], &debug_red);
3572 graphics_gc_set_linewidth(gra->gc[0], 10);
3573 transform(global_navit->trans, pro3, &global_debug_route_seg_winner_p_start, &p_temp[0], 1, 0, 0, NULL);
3574 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, &p_temp[0], 44);
3575 }
3576 }
3577
3578 struct color debug_green = { 0x0000,0xffff,0x0000,0xffff }; // RR GG BB AA
3579 graphics_gc_set_foreground(gra->gc[0], &debug_green);
3580 graphics_gc_set_linewidth(gra->gc[0], 8);
3581 transform(global_navit->trans, pro3, &global_debug_seg_winner_p_start, &p_temp[0], 1, 0, 0, NULL);
3582 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, &p_temp[0], 36);
3583
3584 if (global_navit->route)
3585 {
3586 if (global_navit->destination_valid == 1)
3587 {
3588 struct color debug_yellow = { 0xf7f7,0xfefe,0x2e2e,0xffff }; // RR GG BB AA
3589 transform(global_navit->trans, pro3, &global_debug_seg_route_start, &p_temp[0], 1, 0, 0, NULL);
3590 transform(global_navit->trans, pro3, &global_debug_seg_route_end, &p_temp[1], 1, 0, 0, NULL);
3591 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp, 2, 15, 8, 0, &debug_yellow, global_clinedrawing_active, 1);
3592 }
3593 }
3594
3595 // -------- DEBUG -------- draw winner track segment ---------
3596 // -------- DEBUG -------- draw winner track segment ---------
3597 // -------- DEBUG -------- draw winner track segment ---------
3598 #endif
3599
3600
3601 // ============================== debug lines ==============================
3602 // ============================== debug lines ==============================
3603 // ============================== debug lines ==============================
3604 #ifdef NAVIT_DEBUG_COORD_LIST
3605 struct color debug_purple = { 0xffff,0x0000,0xffff,0xffff }; // RR GG BB AA
3606 transform(global_navit->trans, pro3, &global_debug_trlast_start, &p_temp[0], 1, 0, 0, NULL);
3607 transform(global_navit->trans, pro3, &global_debug_trlast_end, &p_temp[1], 1, 0, 0, NULL);
3608 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp, 2, 15, 18, 0, &debug_purple, global_clinedrawing_active, 1);
3609
3610
3611 struct color debug_purple0 = { 0x1010,0xfefe,0xefef,0xffff }; // RR GG BB AA
3612 struct color debug_purple1 = { 0x3030,0xaeae,0x4f4f,0xffff }; // RR GG BB AA
3613 struct color debug_purple2 = { 0x1010,0x7878,0x3030,0xffff }; // RR GG BB AA
3614 struct color debug_red3 = { 0xffff,0x0000,0x0000,0xffff }; // RR GG BB AA
3615 struct color *debug_color_pp;
3616 int ii2;
3617 int jj;
3618
3619 // dbg(0,"global_debug_coord_list:LOOP:num=%d\n", global_debug_coord_list_items);
3620
3621 for (ii2 = 0; ii2 < global_debug_coord_list_items; ii2++)
3622 {
3623
3624 //dbg(0,"global_debug_coord_list:LOOP:coord_list=%d\n", ii2);
3625
3626 transform(global_navit->trans, pro3, &global_debug_coord_list[ii2], &p_temp[0], 1, 0, 0, NULL);
3627 ii2++;
3628 transform(global_navit->trans, pro3, &global_debug_coord_list[ii2], &p_temp[1], 1, 0, 0, NULL);
3629
3630 jj = ((ii2 - 1) % 3);
3631 if (jj == 0)
3632 {
3633 debug_color_pp = &debug_purple0;
3634 }
3635 else if (jj == 1)
3636 {
3637 debug_color_pp = &debug_purple1;
3638 }
3639 else
3640 {
3641 debug_color_pp = &debug_purple2;
3642 }
3643
3644
3645 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p_temp, 2, 15, 6, 0, debug_color_pp, global_clinedrawing_active, 1);
3646
3647 // ------ text -------
3648 graphics_gc_set_foreground(gra->gc[0], &debug_red3);
3649 graphics_gc_set_linewidth(gra->gc[0], 6);
3650 struct point p7;
3651 struct graphics_font *font8 = get_font(gra, 21);
3652 char *dir_label=g_strdup_printf("%d", (ii2 - 1));
3653 p7.x = p_temp[0].x + 0; // move text label a bit to the right, so it does not overlap the circle
3654 p7.y = p_temp[0].y + 0; // move label a bit down (y-axis)
3655 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, dir_label, &p7, 0x10000, 0);
3656 g_free(dir_label);
3657 // ------ text -------
3658
3659 // ------ text -------
3660 //graphics_gc_set_foreground(gra->gc[0], &debug_red3);
3661 //graphics_gc_set_linewidth(gra->gc[0], 6);
3662 //struct point p7;
3663 //struct graphics_font *font8 = get_font(gra, 21);
3664 dir_label=g_strdup_printf("%d", ii2);
3665 p7.x = p_temp[1].x + 8; // move text label a bit to the right, so it does not overlap the circle
3666 p7.y = p_temp[1].y + 8; // move label a bit down (y-axis)
3667 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, dir_label, &p7, 0x10000, 0);
3668 g_free(dir_label);
3669 // ------ text -------
3670
3671 }
3672 #endif
3673 // ============================== debug lines ==============================
3674 // ============================== debug lines ==============================
3675 // ============================== debug lines ==============================
3676
3677
3678
3679 }
3680 // dirty hack to draw "waypoint(s)" ---------------------------
3681 // dirty hack to draw "route arrows" ---------------------------
3682 else if (strncmp("RouteArrows", lay->name, 11) == 0)
3683 {
3684 if (global_navit->route)
3685 {
3686 if (global_navit->destination_valid == 1)
3687 {
3688
3689 #define MAX_ROUTE_ARROW_LINE_LENGTH 50.0f
3690 #define MAX_ROUTE_ARROW_LINE_LENGTH_SQ 2500
3691 #define MIN_ROUTE_ARROW_LINE_LENGTH_SQ 2000
3692 #define MAX_ROUTE_ARROW_TO_SHOW 2 // default 2
3693
3694 struct navigation *nav = NULL;
3695 struct map *map=NULL;
3696 struct map_rect *mr=NULL;
3697 struct item *item8 =NULL;
3698 struct attr attr8;
3699 struct coord c8;
3700 struct coord c11;
3701 struct color route_arrrow_green_1 = { 0x0404,0xb4b4,0xaeae,0xffff }; // RR GG BB AA first line and arrow
3702 struct color route_arrrow_green_2 = { 0x0909,0x8484,0x7f7f,0xffff }; // RR GG BB AA all the next lines and arrows
3703 struct color *route_arrrow_green = &route_arrrow_green_1;
3704 struct point *p8 = g_alloca(sizeof(struct point));
3705 struct point *p9_temp = g_alloca(sizeof(struct point) * (2 + 1));
3706 struct point *p11_temp = g_alloca(sizeof(struct point) * (2 + 1));
3707 enum projection pro3 = transform_get_projection(global_navit->trans_cursor);
3708 int route_arrow_count = 0;
3709 int arrow_waiting = 0;
3710
3711
3712 #ifdef NAVIT_SHOW_ROUTE_ARROWS
3713
3714 graphics_gc_set_foreground(gra->gc[0], route_arrrow_green);
3715 graphics_gc_set_linewidth(gra->gc[0], 8);
3716
3717 nav = navit_get_navigation(global_navit);
3718 if (nav)
3719 {
3720 map = navigation_get_map(nav);
3721 if (map)
3722 {
3723 mr = map_rect_new(map,NULL);
3724 if (mr)
3725 {
3726 while ((item8 = map_rect_get_item(mr)))
3727 {
3728
3729 if (item8->type == type_nav_destination)
3730 {
3731 break;
3732 }
3733
3734 if (item_attr_get(item8, attr_navigation_long, &attr8))
3735 {
3736 route_arrow_count++;
3737
3738 if (route_arrow_count > MAX_ROUTE_ARROW_TO_SHOW)
3739 {
3740 break;
3741 }
3742 else if (route_arrow_count == 2)
3743 {
3744 route_arrrow_green = &route_arrrow_green_2;
3745 }
3746
3747 item_coord_get(item8, &c8, 1);
3748
3749 #if 0
3750 graphics_gc_set_foreground(gra->gc[0], &route_arrrow_green);
3751 graphics_gc_set_linewidth(gra->gc[0], 8);
3752 transform(global_navit->trans, pro3, &c8, p8, 1, 0, 0, NULL);
3753 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, p8, 45);
3754
3755 struct graphics_font *font8 = get_font(gra, 25);
3756 char *arrow_label=g_strdup_printf("%d", route_arrow_count);
3757
3758 p8->x = p8->x + 45; // move text label a bit to the right, so it does not overlap the circle
3759 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)
3760
3761 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, arrow_label, p8, 0x10000, 0);
3762 g_free(arrow_label);
3763 #endif
3764
3765
3766 // --- find the segments for this maneuver ---
3767 struct route *route2 = NULL;
3768 struct map *route_map2 = NULL;
3769 struct map_rect *mr2 = NULL;
3770 struct item *item2 = NULL;
3771 struct coord c2;
3772 struct coord c2_prev;
3773 float route_line_length_sq;
3774 int first2 = 1;
3775 int first3 = 0;
3776 int found_seg = 0;
3777 float dx, dy;
3778 int added_seg = 0;
3779
3780 c2.x = 0;
3781 c2.y = 0;
3782 c2_prev.x = c2.x;
3783 c2_prev.y = c2.y;
3784
3785 route2 = navit_get_route(global_navit);
3786 if (route2)
3787 {
3788 route_map2 = route_get_map(route2);
3789 if (route_map2)
3790 {
3791 mr2 = map_rect_new(route_map2, NULL);
3792 if (mr2)
3793 {
3794 item2 = map_rect_get_item(mr2);
3795 while (item2)
3796 {
3797 if (!item_coord_get(item2, &c2, 1))
3798 {
3799 first3 = 1;
3800 item2 = map_rect_get_item(mr2);
3801 continue;
3802 }
3803
3804 // loop all coords of the route ----------------------
3805 if (first3 == 1)
3806 {
3807 first3 = 0;
3808 }
3809 else
3810 {
3811 if ( ((c2.x == c8.x) && (c2.y == c8.y)) || (found_seg == 1) )
3812 {
3813 //if (first2 == 1)
3814 //{
3815 // first2 = 0;
3816 //}
3817 //else
3818 {
3819 //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);
3820 if (found_seg == 1)
3821 {
3822 // draw arrow head at the end
3823
3824 route_line_length_sq = (float)transform_distance_sq(&c2_prev, &c2);
3825 if ((added_seg == 0) && (route_line_length_sq < MIN_ROUTE_ARROW_LINE_LENGTH_SQ))
3826 {
3827 // draw line
3828 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3829 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3830 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3831
3832 // add next coord to line/arrow
3833 found_seg = 0;
3834 added_seg = 1;
3835 }
3836 else
3837 {
3838 if (route_line_length_sq > MAX_ROUTE_ARROW_LINE_LENGTH_SQ)
3839 {
3840 route_line_length_sq = sqrt(route_line_length_sq);
3841 // make line shorter (move coord c2 backward)
3842 dx = ((float)(c2.x - c2_prev.x)) / route_line_length_sq;
3843 dy = ((float)(c2.y - c2_prev.y)) / route_line_length_sq;
3844 c2.x = c2_prev.x + (int)(dx * MAX_ROUTE_ARROW_LINE_LENGTH);
3845 c2.y = c2_prev.y + (int)(dy * MAX_ROUTE_ARROW_LINE_LENGTH);
3846 }
3847
3848 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3849 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3850 arrow_waiting = 1;
3851 p11_temp[0].x = p9_temp[0].x;
3852 p11_temp[0].y = p9_temp[0].y;
3853 p11_temp[1].x = p9_temp[1].x;
3854 p11_temp[1].y = p9_temp[1].y;
3855 c11.x = c2.x;
3856 c11.y = c2.y;
3857 // gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 4);
3858 }
3859 }
3860 else
3861 {
3862 route_line_length_sq = (float)transform_distance_sq(&c2_prev, &c2);
3863 if (route_line_length_sq > MAX_ROUTE_ARROW_LINE_LENGTH_SQ)
3864 {
3865 route_line_length_sq = sqrt(route_line_length_sq);
3866 // make line shorter (move coord c2_prev forward)
3867 dx = ((float)(c2.x - c2_prev.x)) / route_line_length_sq;
3868 dy = ((float)(c2.y - c2_prev.y)) / route_line_length_sq;
3869 c2_prev.x = c2.x - (int)(dx * MAX_ROUTE_ARROW_LINE_LENGTH);
3870 c2_prev.y = c2.y - (int)(dy * MAX_ROUTE_ARROW_LINE_LENGTH);
3871 }
3872
3873 transform(global_navit->trans, pro3, &c2_prev, &p9_temp[0], 1, 0, 0, NULL);
3874 transform(global_navit->trans, pro3, &c2, &p9_temp[1], 1, 0, 0, NULL);
3875
3876 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3877
3878 if (arrow_waiting == 1)
3879 {
3880 arrow_waiting = 0;
3881 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)))
3882 {
3883 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 1);
3884 }
3885 else
3886 {
3887 if (route_arrow_count == 2)
3888 {
3889 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, &route_arrrow_green_1, global_clinedrawing_active, 4);
3890 }
3891 else
3892 {
3893 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, &route_arrrow_green_2, global_clinedrawing_active, 4);
3894 }
3895 }
3896 }
3897
3898 }
3899 }
3900
3901 if (found_seg == 0)
3902 {
3903 found_seg++;
3904 }
3905 else if (found_seg == 1)
3906 {
3907 break;
3908 }
3909
3910 }
3911 }
3912 c2_prev.x = c2.x;
3913 c2_prev.y = c2.y;
3914
3915 // loop all coords of the route ----------------------
3916 }
3917 map_rect_destroy(mr2);
3918 }
3919 }
3920 }
3921 // --- find the segments for this maneuver ---
3922
3923 }
3924 }
3925 map_rect_destroy(mr);
3926
3927 if (arrow_waiting == 1)
3928 {
3929 // if there is still an arrow to be drawn, draw it now
3930 arrow_waiting = 0;
3931 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p11_temp, 2, 15, 28, 0, route_arrrow_green, global_clinedrawing_active, 4);
3932 }
3933
3934 }
3935 }
3936 }
3937
3938 #endif
3939
3940
3941
3942 #ifdef NAVIT_FREE_TEXT_DEBUG_PRINT
3943 // ------- free text list ----------
3944 // ------- free text list ----------
3945
3946 struct color debug_blue2a = { 0x0000,0x0000,0xffff,0xffff }; // RR GG BB AA
3947 struct color debug_black2a = { 0x0000,0x0000,0x0000,0xffff }; // RR GG BB AA
3948 struct point *p_temp13a = g_alloca(sizeof(struct point));
3949 struct point *p9_temp13a = g_alloca(sizeof(struct point) * (2 + 1));
3950 enum projection pro4a = transform_get_projection(global_navit->trans_cursor);
3951 graphics_gc_set_linewidth(gra->gc[0], 8);
3952
3953 int ij1a;
3954 for (ij1a=0; ij1a < global_freetext_list_count; ij1a++)
3955 {
3956 transform(global_navit->trans, pro4a, &global_freetext_list[ij1a].c1, p_temp13a, 1, 0, 0, NULL);
3957 graphics_gc_set_foreground(gra->gc[0], &debug_blue2a);
3958 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, p_temp13a, 36);
3959
3960 // ------ text -------
3961 struct point p7a;
3962 struct graphics_font *font8a = get_font(gra, 10);
3963 graphics_gc_set_foreground(gra->gc[0], &debug_black2a);
3964 p7a.x = p_temp13a->x + 25; // move text label a bit to the right, so it does not overlap the circle
3965 p7a.y = p_temp13a->y + 25; // move label a bit down (y-axis)
3966 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8a->priv, global_freetext_list[ij1a].text, &p7a, 0x10000, 0);
3967 // ------ text -------
3968 }
3969
3970 // ------- free text list ----------
3971 // ------- free text list ----------
3972 #endif
3973
3974
3975
3976
3977
3978
3979 // ------- sharp turn angle list ----------
3980 // ------- sharp turn angle list ----------
3981 #ifdef NAVIT_ANGLE_LIST_DEBUG_PRINT_DRAW
3982 struct color debug_green2 = { 0x0000,0xffff,0x0000,0xffff }; // RR GG BB AA
3983 struct color debug_blue2 = { 0x0000,0x0000,0xffff,0xffff }; // RR GG BB AA
3984 struct color debug_red2 = { 0xffff,0x0000,0x0000,0xffff }; // RR GG BB AA
3985 struct point *p_temp13 = g_alloca(sizeof(struct point));
3986 struct point *p9_temp13 = g_alloca(sizeof(struct point) * (2 + 1));
3987 enum projection pro4 = transform_get_projection(global_navit->trans_cursor);
3988 graphics_gc_set_linewidth(gra->gc[0], 8);
3989
3990 int ij1;
3991 for (ij1=0; ij1 < global_sharp_turn_list_count;ij1++)
3992 {
3993 transform(global_navit->trans, pro4, &global_sharp_turn_list[ij1].c1, p_temp13, 1, 0, 0, NULL);
3994 if (global_sharp_turn_list[ij1].dir == 1)
3995 {
3996 graphics_gc_set_foreground(gra->gc[0], &debug_green2);
3997 }
3998 else
3999 {
4000 graphics_gc_set_foreground(gra->gc[0], &debug_blue2);
4001 }
4002 gra->meth.draw_circle(gra->priv, gra->gc[0]->priv, p_temp13, 36);
4003
4004
4005 // --- line of turn angle ---
4006 p9_temp13[0].x = p_temp13->x;
4007 p9_temp13[0].y = p_temp13->y;
4008 transform(global_navit->trans, pro3, &global_sharp_turn_list[ij1].cs, &p9_temp13[1], 1, 0, 0, NULL);
4009 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp13, 2, 15, 12, 0, &debug_red2, global_clinedrawing_active, 1);
4010 transform(global_navit->trans, pro3, &global_sharp_turn_list[ij1].ce, &p9_temp13[1], 1, 0, 0, NULL);
4011 gra->meth.draw_lines3(gra->priv, gra->gc[0]->priv, p9_temp13, 2, 15, 5, 0, &debug_green2, global_clinedrawing_active, 1);
4012 // --- line of turn angle ---
4013
4014
4015
4016 // ------ text -------
4017 // graphics_gc_set_foreground(gra->gc[0], &debug_red2);
4018 // graphics_gc_set_linewidth(gra->gc[0], 8);
4019 struct point p7;
4020 struct graphics_font *font8 = get_font(gra, 24);
4021 char *dir_label=g_strdup_printf("%d", global_sharp_turn_list[ij1].angle);
4022 // dbg(0, "st.angle(2)=%d\n", global_sharp_turn_list[ij1].angle);
4023
4024 if (global_sharp_turn_list[ij1].angle > 0)
4025 {
4026 p7.x = p_temp13->x + 25; // move text label a bit to the right, so it does not overlap the circle
4027 p7.y = p_temp13->y + 25;
4028 // p7.y = p_temp13->y + 25 + (int)((float)global_sharp_turn_list[ij1].angle / 2.0f); // move label a bit down (y-axis)
4029 }
4030 else
4031 {
4032 p7.x = p_temp13->x + 25; // move text label a bit to the right, so it does not overlap the circle
4033 p7.y = p_temp13->y + 0;
4034 // p7.y = p_temp13->y + 0 + (int)((float)global_sharp_turn_list[ij1].angle / 2.0f); // move label a bit down (y-axis)
4035 }
4036 gra->meth.draw_text(gra->priv, gra->gc[0]->priv, NULL, font8->priv, dir_label, &p7, 0x10000, 0);
4037 g_free(dir_label);
4038 // ------ text -------
4039
4040 }
4041 #endif
4042 // ------- sharp turn angle list ----------
4043 // ------- sharp turn angle list ----------
4044
4045 }
4046 }
4047 }
4048 // dirty hack to draw "route arrows" ---------------------------
4049
4050
4051 if (send_refresh == 1)
4052 {
4053 // dummy "ready" signal ------------------------------------------
4054 // dbg(0, "dummy \"ready\" signal (layers)\n");
4055 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 96, 0, NULL, 1);
4056 // dummy "ready" signal ------------------------------------------
4057 }
4058
4059 }
4060
4061 /**
4062 * FIXME
4063 * @param <>
4064 * @returns <>
4065 * @author Martin Schaller (04/2008)
4066 */
4067 static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
4068 {
4069 __F_START__
4070
4071 GList *lays;
4072 struct layer *lay;
4073
4074 // int draw_vector_map = 1;
4075
4076 // if zoomed out too much then use prerendered map tiles
4077 //if (display_list->order < ORDER_USE_PRERENDERED_MAP)
4078 //{
4079 // draw_vector_map = 0;
4080 //}
4081
4082 #if 0
4083 if (!draw_vector_map)
4084 {
4085 // draw prerendered big mapimage --- HERE ---
4086 struct transformation *t;
4087 t = display_list->dc.trans;
4088 struct coord *cp;
4089 cp = transform_get_center(t);
4090 struct attr attr;
4091 struct config
4092 {
4093 struct attr **attrs;
4094 struct callback_list *cbl;
4095 }*config;
4096 struct point p;
4097 int valid = 0;
4098 if (global_navit)
4099 {
4100 if ((global_navit->vehicle) && (global_navit->vehicle->vehicle))
4101 {
4102 //int a, s;
4103 //struct point pnt2;
4104 //vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
4105
4106 //struct attr pos_attr;
4107 //if (vehicle_get_attr(global_navit->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL))
4108 //{
4109 // ////DBG // dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
4110 //}
4111
4112 valid = 1;
4113 }
4114 }
4115
4116 struct coord *c;
4117 c = &(t->map_center);
4118
4119 enum projection pro = transform_get_projection(global_navit->trans_cursor);
4120 struct coord_geo g22;
4121 struct coord *c22;
4122 struct point mcenter_pnt;
4123 c22 = &(t->map_center);
4124 transform_to_geo(projection_mg, c22, &g22);
4125 transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
4126
4127 struct coord c99;
4128 struct coord_geo g99;
4129 struct point cursor_pnt;
4130 struct point p99;
4131 long my_scale;
4132
4133 my_scale = transform_get_scale(global_navit->trans);
4134
4135 g99.lat = 0.0;
4136 g99.lng = 0.0;
4137 // g99.lat = 80.0;
4138 // g99.lng = -174.0;
4139 transform_from_geo(pro, &g99, &c99);
4140 transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
4141
4142 // now really draw it
4143 struct graphics *gra22 = display_list->dc.gra;
4144 struct graphics_gc *gc22 = display_list->dc.gc;
4145 if (!gc22)
4146 {
4147 gc22 = graphics_gc_new(gra22);
4148 }
4149 // 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);
4150 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);
4151 }
4152 #endif
4153
4154 // reset value; --> not sure here, maybe it should NOT be reset here!!!???
4155 // cancel_drawing_global = 0;
4156
4157
4158
4159
4160
4161
4162
4163 // stop drawing is requested
4164 if (cancel_drawing_global != 1)
4165 {
4166
4167 if ((display_list->order >= ORDER_USE_PRERENDERED_MAP) || (global_show_maps_debug_view)) // ==5 , (4,3,2,1,0)--> no vector map
4168 {
4169 // MAPNIK -- MVT --
4170 // MAPNIK -- MVT --
4171 // MAPNIK -- MVT --
4172 int screen_width, screen_height;
4173 struct coord c_screen;
4174 struct point p_screen;
4175 struct coord_geo g_screen_lt;
4176 struct coord_geo g_screen_rt;
4177 struct coord_geo g_screen_rb;
4178
4179 transform_get_size(global_navit->trans, &screen_width, &screen_height);
4180 // dbg(0, "transform_get_size:w=%d h=%d\n", screen_width, screen_height);
4181 // dbg(0, "navit_maps_dir=%s\n", navit_maps_dir);
4182
4183 p_screen.x = 0;
4184 p_screen.y = 0;
4185 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4186 transform_to_geo(projection_mg, &c_screen, &g_screen_lt);
4187
4188 p_screen.x = screen_width;
4189 p_screen.y = 0;
4190 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4191 transform_to_geo(projection_mg, &c_screen, &g_screen_rt);
4192
4193 p_screen.x = screen_width;
4194 p_screen.y = screen_height;
4195 transform_reverse(global_navit->trans, &p_screen, &c_screen);
4196 transform_to_geo(projection_mg, &c_screen, &g_screen_rb);
4197
4198 // 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);
4199
4200
4201 if ((display_list->order > 5) || (global_show_maps_debug_view))
4202 {
4203 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);
4204 }
4205 /*
4206 else if (display_list->order > 4)
4207 {
4208 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);
4209 }
4210 else
4211 {
4212 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);
4213 }
4214 */
4215 // MAPNIK -- MVT --
4216 // MAPNIK -- MVT --
4217 // MAPNIK -- MVT --
4218 }
4219 }
4220
4221
4222
4223
4224
4225
4226 lays = l->layers;
4227 while (lays)
4228 {
4229 // stop drawing is requested
4230 if (cancel_drawing_global == 1)
4231 {
4232 break;
4233 }
4234
4235 lay = lays->data;
4236 if (lay->active)
4237 {
4238 //ZZZZZZZZZZZZZZZZZZZZZ//
4239 //ZZZZZZZZZZZZZZZZZZZZZ//
4240 //ZZZZZZZZZZZZZZZZZZZZZ//
4241 //ZZZZZZZZZZZZZZZZZZZZZ//
4242 //ZZZZZZZZZZZZZZZZZZZZZ//
4243 //ZZZZZZZZZZZZZZZZZZZZZ//
4244 //ZZZZZZZZZZZZZZZZZZZZZ//
4245 //ZZZZZZZZZZZZZZZZZZZZZ//
4246 xdisplay_draw_layer(display_list, gra, lay, order);
4247 //ZZZZZZZZZZZZZZZZZZZZZ//
4248 //ZZZZZZZZZZZZZZZZZZZZZ//
4249 //ZZZZZZZZZZZZZZZZZZZZZ//
4250 //ZZZZZZZZZZZZZZZZZZZZZ//
4251 //ZZZZZZZZZZZZZZZZZZZZZ//
4252 //ZZZZZZZZZZZZZZZZZZZZZ//
4253 //ZZZZZZZZZZZZZZZZZZZZZ//
4254 //ZZZZZZZZZZZZZZZZZZZZZ//
4255 }
4256 lays = g_list_next(lays);
4257 }
4258
4259
4260
4261 // reset value;
4262 // cancel_drawing_global = 0;
4263
4264 // dummy "start" signal ------------------------------------------
4265 // // dbg(0, "dummy \"start\" signal\n");
4266 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 97, 0);
4267 // dummy "start" signal ------------------------------------------
4268
4269 __F_END__
4270 }
4271
4272 /**
4273 * FIXME
4274 * @param <>
4275 * @returns <>
4276 * @author Martin Schaller (04/2008)
4277 */
4278 extern void *route_selection;
4279
4280 static void displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
4281 {
4282 ////DBG // dbg(0,"ooo enter ooo\n");
4283
4284 int order_corrected = order + shift_order;
4285 //int saved=displaylist->order;
4286 if (order < limit_order_corrected)
4287 {
4288 order_corrected = limit_order_corrected;
4289 // displaylist->order=0;
4290 }
4291
4292 while (layers)
4293 {
4294 struct layer *layer = layers->data;
4295 GList *itemgras = layer->itemgras;
4296 while (itemgras)
4297 {
4298 struct itemgra *itemgra = itemgras->data;
4299 GList *types = itemgra->type;
4300 if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
4301 {
4302 while (types)
4303 {
4304 enum item_type type = (enum item_type) types->data;
4305 set_hash_entry(displaylist, type);
4306 types = g_list_next(types);
4307 }
4308 }
4309 itemgras = g_list_next(itemgras);
4310 }
4311 layers = g_list_next(layers);
4312 }
4313 // displaylist->order=saved;
4314 }
4315
4316 static void displaylist_update_hash(struct displaylist *displaylist)
4317 {
4318 ////DBG // dbg(0,"ooo enter ooo\n");
4319
4320 displaylist->max_offset = 0;
4321 clear_hash(displaylist);
4322 displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
4323 // dbg(1, "max offset %d\n", displaylist->max_offset);
4324 }
4325
4326 static void do_draw(struct displaylist *displaylist, int cancel, int flags)
4327 {
4328
4329 __F_START__
4330
4331 // int rnd = rand();
4332 // dbg(0, "DO__DRAW:%d enter\n", rnd);
4333
4334 // try to cancel any previous drawing that might be going on ...
4335 // try to cancel any previous drawing that might be going on ...
4336 // try to cancel any previous drawing that might be going on ...
4337 // dbg(0, "DO__DRAW:%d cancel_drawing_global 1=%d\n", rnd, cancel_drawing_global);
4338 cancel_drawing_global = 1;
4339 // dbg(0, "DO__DRAW:%d cancel_drawing_global 2=%d\n", rnd, cancel_drawing_global);
4340 // try to cancel any previous drawing that might be going on ...
4341 // try to cancel any previous drawing that might be going on ...
4342 // try to cancel any previous drawing that might be going on ...
4343
4344
4345 // dbg(0, "DO__DRAW:%d lock mutex\n", rnd);
4346 pthread_mutex_lock(&uiConditionMutex);
4347 // dbg(0, "DO__DRAW:%d OK lock mutex\n", rnd);
4348
4349 // drawing is now starting ...
4350 // drawing is now starting ...
4351 // drawing is now starting ...
4352 // dbg(0, "DO__DRAW:%d cancel_drawing_global 3=%d\n", rnd, cancel_drawing_global);
4353 cancel_drawing_global = 0;
4354 // dbg(0, "DO__DRAW:%d cancel_drawing_global 4=%d\n", rnd, cancel_drawing_global);
4355 // drawing is now starting ...
4356 // drawing is now starting ...
4357 // drawing is now starting ...
4358
4359
4360 #ifdef HAVE_API_ANDROID
4361 // ---- disable map view -----
4362 // ---- disable map view -----
4363 // ---- disable map view -----
4364 if (disable_map_drawing == 1)
4365 {
4366 //android_return_generic_int(2, 0);
4367
4368 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4369 displaylist->busy = 0;
4370
4371 // dbg(0,"DO__DRAW:%d UN-lock mutex 001\n", rnd);
4372 pthread_mutex_unlock(&uiConditionMutex);
4373 // dbg(0,"DO__DRAW:%d OK UN-lock mutex 001\n", rnd);
4374
4375 // dbg(0,"DO__DRAW:%d return 001\n", rnd);
4376 return2;
4377 }
4378 // ---- disable map view -----
4379 // ---- disable map view -----
4380 // ---- disable map view -----
4381 #endif
4382
4383 clock_t s_;
4384 #ifdef NAVIT_MEASURE_TIME_DEBUG
4385 s_ = debug_measure_start();
4386 #endif
4387
4388 struct item *item;
4389 int count, max = displaylist->dc.maxlen, workload = 0;
4390 struct coord *ca = g_alloca(sizeof(struct coord) * max);
4391 struct attr attr, attr2;
4392 enum projection pro;
4393 int draw_vector_map = 1; // do we draw the vecotor map, or not? 0=false, 1=true
4394 int draw_tile_map = 1; // do we draw the prerendered tile map? 0=false, 1=true
4395 int mapset_counter = 0;
4396 int mapset_need_draw = 0;
4397 int only_labels = 0;
4398
4399 // int r_, g_, b_, a_;
4400 unsigned int col_int_value;
4401 struct attr attr_cc;
4402
4403 // // dbg(0,"ooo enter ooo %d\n",displaylist->order);
4404
4405 int order_corrected = displaylist->order + shift_order;
4406 int saved = displaylist->order;
4407 if (order_corrected < limit_order_corrected)
4408 {
4409 order_corrected = limit_order_corrected;
4410 }
4411
4412 if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
4413 {
4414 displaylist_update_hash(displaylist);
4415 displaylist->order_hashed = displaylist->order;
4416 displaylist->layout_hashed = displaylist->layout;
4417 }
4418
4419 pro = transform_get_projection(displaylist->dc.trans);
4420
4421 // if zoomed out too much then use prerendered map tiles
4422 if (global_clinedrawing_active)
4423 {
4424 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP__C)
4425 {
4426 draw_vector_map = 0;
4427 }
4428
4429 if (displaylist->order_hashed > ORDER_USE_NORMAL_MAP__C)
4430 {
4431 draw_tile_map = 0;
4432 }
4433 }
4434 else
4435 {
4436 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP) // ==5 , (4,3,2,1,0)--> no vector map
4437 {
4438 draw_vector_map = 0;
4439 }
4440
4441 if (displaylist->order_hashed > ORDER_USE_NORMAL_MAP) // ==6 , (7,8,9, ...)--> no tile map
4442 {
4443 draw_tile_map = 0;
4444 }
4445 }
4446
4447 if (global_show_maps_debug_view)
4448 {
4449 draw_vector_map = 1;
4450 draw_tile_map = 0;
4451 }
4452
4453 displaylist->order = order_corrected;
4454
4455 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 003\n");
4456
4457 // reset value;
4458 // cancel_drawing_global = 0;
4459
4460 char *ttt22 = NULL;
4461
4462
4463 while (!cancel)
4464 {
4465 if (!displaylist->msh)
4466 {
4467 displaylist->msh = mapset_open(displaylist->ms);
4468 }
4469
4470 if (!displaylist->m)
4471 {
4472 displaylist->m = mapset_next(displaylist->msh, 1);
4473 if (!displaylist->m)
4474 {
4475 mapset_close(displaylist->msh);
4476 displaylist->msh = NULL;
4477 break;
4478 }
4479
4480 mapset_counter++;
4481 mapset_need_draw = 1;
4482 only_labels = 0;
4483
4484 struct attr map_name_attr;
4485
4486 if (map_get_attr(displaylist->m, attr_name, &map_name_attr, NULL))
4487 {
4488 // dbg(0,"MAP:#+* start reading map file #+*=%s\n", map_name_attr.u.str);
4489 if (ttt22)
4490 {
4491 g_free(ttt22);
4492 }
4493 ttt22 = g_strdup(map_name_attr.u.str);
4494
4495 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
4496 {
4497 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
4498 {
4499 if (draw_tile_map == 1)
4500 {
4501 // if its the countryborder map
4502 mapset_need_draw = 0;
4503 }
4504 else if (displaylist->order_hashed >= ORDER_USE_BORDERS_MAP)
4505 {
4506 // on high detail -> dont draw bordermap anymore. it sometimes causes heavy slowdowns!!
4507 mapset_need_draw = 0;
4508 }
4509 }
4510
4511 /*
4512 else if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/coastline.bin", map_name_attr.u.str, 48) == 0)
4513 {
4514 if (draw_tile_map == 1)
4515 {
4516 // if its the countryborder map
4517 mapset_need_draw = 0;
4518 }
4519 }
4520 */
4521
4522
4523 #if 0
4524 else if (strncmp("_ms_sdcard_map:-special-:worldmap6.txt", map_name_attr.u.str, 38) == 0)
4525 {
4526 // if its a worldmapX.txt
4527 if (draw_vector_map == 1)
4528 {
4529 //dbg(0, "wm5: v=1");
4530 mapset_need_draw = 0;
4531 }
4532 else
4533 {
4534 //dbg(0, "wm5: v=0");
4535
4536 if (displaylist->order_hashed < 4)
4537 {
4538 //dbg(0, "wm5: nd=0");
4539 mapset_need_draw = 0;
4540 }
4541 else
4542 {
4543 //dbg(0, "wm5: nd=1");
4544 mapset_need_draw = 1;
4545 }
4546 }
4547 }
4548 #endif
4549 else if (strncmp("_ms_sdcard_map:-special-:worldmap5.txt", map_name_attr.u.str, 38) == 0)
4550 {
4551 // if its a worldmapX.txt
4552 if (draw_tile_map == 0)
4553 {
4554 mapset_need_draw = 0;
4555 }
4556 else
4557 {
4558 if (displaylist->order_hashed < 3)
4559 {
4560 mapset_need_draw = 0;
4561 }
4562 else
4563 {
4564 mapset_need_draw = 1;
4565 }
4566 }
4567 }
4568 else if (strncmp("_ms_sdcard_map:-special-:worldmap2.txt", map_name_attr.u.str, 38) == 0)
4569 {
4570 // if its a worldmapX.txt
4571 if (draw_tile_map == 0)
4572 {
4573 mapset_need_draw = 0;
4574 }
4575 else
4576 {
4577 if (displaylist->order_hashed < 3)
4578 {
4579 mapset_need_draw = 1;
4580 }
4581 else
4582 {
4583 mapset_need_draw = 0;
4584 }
4585 }
4586 }
4587 else
4588 {
4589 // if its an sdcard street map
4590 if (draw_vector_map == 1)
4591 {
4592 mapset_need_draw = 1;
4593 if (draw_tile_map == 1)
4594 {
4595 only_labels = 1;
4596 }
4597 }
4598 else
4599 {
4600 mapset_need_draw = 0;
4601 }
4602 }
4603 }
4604 }
4605
4606 ////DBG // dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
4607
4608 displaylist->dc.pro = map_projection(displaylist->m);
4609 displaylist->conv = map_requires_conversion(displaylist->m);
4610 if (route_selection)
4611 {
4612 displaylist->sel = route_selection;
4613 }
4614 else
4615 {
4616 displaylist->sel = transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
4617 }
4618 displaylist->mr = map_rect_new(displaylist->m, displaylist->sel);
4619 }
4620
4621
4622 if (displaylist->mr)
4623 {
4624 // dbg(0,"MAP:001:map=%s\n", ttt22);
4625 // draw vector map, or not?
4626 // dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
4627 // ****** if ((draw_vector_map) || (mapset_need_draw == 1))
4628 if (mapset_need_draw == 1)
4629 {
4630 //dbg(0,"MAP:002:map=%s\n", ttt22);
4631 //if (ttt22)
4632 //{
4633 // system_log(0, "MAP:map=%s\n", ttt22);
4634 //}
4635 //else
4636 //{
4637 // system_log(0, "MAP:map=NULL\n");
4638 //}
4639
4640 //// dbg(0, "XXXXXYYYYYYY Draw: A.01\n");
4641
4642
4643 // ------ READ all items in this map rectangle ---------
4644 // ------ READ all items in this map rectangle ---------
4645 // ------ READ all items in this map rectangle ---------
4646 // ------ READ all items in this map rectangle ---------
4647 // ------ READ all items in this map rectangle ---------
4648 // dbg(0,"#+* start reading map file #+*\n");
4649 int _item_counter_ = 0;
4650 while ((item = map_rect_get_item(displaylist->mr)))
4651 {
4652 //dbg(0,"MAP:003:map=%s\n", ttt22);
4653
4654 _item_counter_++;
4655
4656 int label_count = 0;
4657 char *labels[3];
4658 struct hash_entry *entry;
4659
4660 if (cancel_drawing_global == 1)
4661 {
4662 // stop drawing map is requested
4663 //DBG // dbg(0, "** STOP MD 001 **\n");
4664 break;
4665 }
4666
4667 if (item == &busy_item)
4668 {
4669 if (displaylist->workload)
4670 {
4671 // restore order :-)
4672 displaylist->order = saved;
4673
4674 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4675 displaylist->busy = 0;
4676
4677 // dbg(0, "DO__DRAW:%d UN-lock mutex 002\n", rnd);
4678 pthread_mutex_unlock(&uiConditionMutex);
4679 // dbg(0, "DO__DRAW:%d OK UN-lock mutex 002\n", rnd);
4680
4681 //// dbg(0,"return 002\n");
4682 // dbg(0, "DO__DRAW:%d return 002\n", rnd);
4683 return2;
4684 }
4685 else
4686 {
4687 continue;
4688 }
4689 }
4690
4691 if (only_labels == 1)
4692 {
4693 if ((!item_is_town(*item)) && (!item_is_district(*item)))
4694 {
4695 // if its not a label, dont draw it
4696 continue;
4697 }
4698 }
4699
4700 entry = get_hash_entry(displaylist, item->type);
4701
4702 //// dbg(0, "XXXXXYYYYYYY Draw: A.item1 %p %i\n", entry, item->type);
4703
4704 // DEBUG -------- zoffzoff
4705 // DEBUG -------- zoffzoff
4706 // DEBUG -------- zoffzoff
4707 //item_dump_attr_stdout(item, displaylist->m);
4708 // DEBUG -------- zoffzoff
4709 // DEBUG -------- zoffzoff
4710 // DEBUG -------- zoffzoff
4711
4712 //if (item->type == type_rg_segment)
4713 //{
4714 // system_log(0, "type_rg_segment:001");
4715 //}
4716
4717 if (!entry)
4718 {
4719 continue;
4720 }
4721
4722 count = item_coord_get_within_selection(item, ca, item->type < type_line ? 1 : max, displaylist->sel);
4723
4724 if (!count)
4725 {
4726 continue;
4727 }
4728
4729 //dbg(0,"MAP:004:map=%s\n", ttt22);
4730
4731 //// dbg(0, "XXXXXYYYYYYY Draw: A.item2\n");
4732
4733 if (displaylist->dc.pro != pro)
4734 {
4735 //dbg(0,"from to\n");
4736 transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
4737 }
4738
4739 if (count == max)
4740 {
4741 //DBG // dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
4742 displaylist->dc.maxlen = max * 2;
4743 }
4744
4745 //if (item_is_custom_poi(*item))
4746 //{
4747 // if (item_attr_get(item, attr_icon_src, &attr2))
4748 // {
4749 // labels[1] = map_convert_string(displaylist->m, attr2.u.str);
4750 // }
4751 // else
4752 // {
4753 // labels[1] = NULL;
4754 // }
4755 // label_count = 2;
4756 //}
4757 //else
4758 //{
4759 labels[0] = NULL;
4760 labels[1] = NULL;
4761 labels[2] = NULL;
4762 label_count = 0;
4763 //}
4764
4765 // DEBUG -------- zoffzoff
4766 // DEBUG -------- zoffzoff
4767 // DEBUG -------- zoffzoff
4768 // item_dump_attr_stdout(item, displaylist->m);
4769 // DEBUG -------- zoffzoff
4770 // DEBUG -------- zoffzoff
4771 // DEBUG -------- zoffzoff
4772
4773
4774
4775
4776
4777
4778 // --------======== LABELS ========--------
4779 // --------======== LABELS ========--------
4780 if (item_attr_get(item, attr_label, &attr))
4781 {
4782 if (global_show_english_labels < 2)
4783 {
4784 // NORMAL
4785 //dbg(0, "c:%d name=%s\n", label_count, attr.u.str);
4786 labels[label_count] = attr.u.str;
4787 label_count++;
4788 }
4789 }
4790
4791 if (item_attr_get(item, attr_street_name_match, &attr))
4792 {
4793 if ((global_show_english_labels == 1)||(global_show_english_labels == 2))
4794 {
4795 // ENGLISH or alternate
4796 //dbg(0, "c:%d street_en_name=%s\n", label_count, attr.u.str);
4797 labels[label_count] = attr.u.str;
4798 label_count++;
4799 }
4800 }
4801 else if (item_attr_get(item, attr_town_name_match, &attr))
4802 {
4803 if ((global_show_english_labels == 1)||(global_show_english_labels == 2))
4804 {
4805 // ENGLISH or alternate
4806 //dbg(0, "c:%d town_en_name=%s\n", label_count, attr.u.str);
4807 labels[label_count] = attr.u.str;
4808 label_count++;
4809 }
4810 }
4811 else
4812 {
4813 if (global_show_english_labels == 2)
4814 {
4815 // we want ENGLISH labels, but the item does not have it
4816 // --> so show normal label instead (item should not be nameless on map)
4817 if (item_attr_get(item, attr_label, &attr))
4818 {
4819 // NORMAL
4820 //dbg(0, "c:%d name=%s\n", label_count, attr.u.str);
4821 labels[label_count] = attr.u.str;
4822 label_count++;
4823 }
4824 }
4825 }
4826 // --------======== LABELS ========--------
4827 // --------======== LABELS ========--------
4828
4829
4830
4831
4832
4833
4834 // DEBUG -------- zoffzoff
4835 // DEBUG -------- zoffzoff
4836 // DEBUG -------- zoffzoff
4837 // item_dump_attr_stdout(item, displaylist->m);
4838 // DEBUG -------- zoffzoff
4839 // DEBUG -------- zoffzoff
4840 // DEBUG -------- zoffzoff
4841
4842 struct attr attr_77;
4843 if (item_attr_get(item, attr_flags, &attr_77))
4844 {
4845 // // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
4846 item->flags = attr_77.u.num;
4847 }
4848 else
4849 {
4850 item->flags = 0;
4851 }
4852
4853 //struct attr *attr88;
4854 //if (item_attr_get(item, attr_flags, &attr88))
4855 //{
4856 ////DBG // dbg(0,"item flags=%d\n",attr88->u.num);
4857 //}
4858 //attr88=NULL;
4859
4860
4861 /*
4862 if (item->flags & NAVIT_AF_UNDERGROUND)
4863 {
4864 // dbg(0,"is UNDERGROUND\n");
4865 }
4866 else if (item->flags & NAVIT_AF_BRIDGE)
4867 {
4868 // dbg(0,"is BRIDGE\n");
4869 }
4870 */
4871
4872 // a_=0;
4873 if (item_attr_get(item, attr_colour2, &attr_cc))
4874 {
4875
4876 col_int_value = (unsigned int)attr_cc.u.num;
4877 //dbg(0, "ccooll:1 c=%d\n", col_int_value);
4878
4879 //r_= (col_int_value >> 16) & 0xff;
4880 //g_= (col_int_value >> 8) & 0xff;
4881 //b_= col_int_value & 0xff;
4882
4883 //dbg(0, "ccooll:2 r=%d g=%d b=%d\n", r_,g_,b_);
4884
4885 //r_ = r_ << 8;
4886 //g_ = g_ << 8;
4887 //b_ = b_ << 8;
4888
4889 //dbg(0, "ccooll:3 r=%d g=%d b=%d\n", r_,g_,b_);
4890
4891 //a_ = 0xffff;
4892 }
4893 else
4894 {
4895 col_int_value = 0;
4896 }
4897
4898
4899 struct attr attr_88;
4900 if ((item->type == type_street_route) || (item->type == type_street_route_waypoint))
4901 {
4902 if (item_attr_get(item, attr_direction, &attr_88))
4903 {
4904 //dbg(0, "direction(1a1)=%d %x\n", attr_88.u.num, col_int_value);
4905 col_int_value = col_int_value & 0xffffff;
4906 //dbg(0, "direction(1a2)=%x %x\n", attr_88.u.num, col_int_value);
4907 //dbg(0, "direction(1a2.1)=%x %x\n", (attr_88.u.num & 3), ((attr_88.u.num & 3) << 24));
4908 col_int_value = col_int_value | ((attr_88.u.num & 3) << 24);
4909 //dbg(0, "direction(1a3)=%x %x\n", attr_88.u.num, col_int_value);
4910 }
4911 else
4912 {
4913 //dbg(0, "direction(1b1)=%x\n", col_int_value);
4914 col_int_value = col_int_value & 0xffffff;
4915 //dbg(0, "direction(1b2)=%x\n", col_int_value);
4916 }
4917
4918 if (item_attr_get(item, attr_details, &attr_88))
4919 {
4920 // dbg(0, "direction(0)=%x\n", attr_88.u.num);
4921
4922 // #define NAVIT_AF_ONEWAY (1<<0)
4923 // #define NAVIT_AF_ONEWAYREV (1<<1)
4924 // #define NAVIT_AF_ONEWAY_BICYCLE_NO (1<<16)
4925
4926 if (attr_88.u.num & NAVIT_AF_ONEWAY_BICYCLE_NO)
4927 {
4928 // dbg(0, "direction(0)=%x\n", (attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)));
4929 // dbg(0, "direction(0.1)=%x %x\n", col_int_value, (attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)) << 26 );
4930 col_int_value = col_int_value | ((attr_88.u.num & (NAVIT_AF_ONEWAY|NAVIT_AF_ONEWAYREV)) << 26);
4931 }
4932 }
4933 }
4934
4935
4936 // --------======== LABELS ========--------
4937 // --------======== LABELS ========--------
4938 if (label_count > 0)
4939 {
4940 labels[0] = map_convert_string(displaylist->m, labels[0]);
4941 }
4942 if (label_count > 1)
4943 {
4944 labels[1] = map_convert_string(displaylist->m, labels[1]);
4945 }
4946
4947 display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4948
4949 if (label_count > 0)
4950 {
4951 map_convert_free(labels[0]);
4952 }
4953 if (label_count > 1)
4954 {
4955 map_convert_free(labels[1]);
4956 }
4957
4958 //if (displaylist->conv && label_count)
4959 //{
4960 // labels[0] = map_convert_string(displaylist->m, labels[0]);
4961 // display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4962 // map_convert_free(labels[0]);
4963 //}
4964 //else
4965 //{
4966 // display_add(entry, item, count, ca, labels, label_count, 1, col_int_value);
4967 //}
4968 //if (labels[1])
4969 //{
4970 // map_convert_free(labels[1]);
4971 //}
4972 // --------======== LABELS ========--------
4973 // --------======== LABELS ========--------
4974
4975
4976 //workload++;
4977 /*
4978 if (workload == displaylist->workload)
4979 {
4980 // restore order :-)
4981 displaylist->order = saved;
4982 // reset value;
4983 cancel_drawing_global = 0;
4984
4985 // dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
4986 displaylist->busy = 0;
4987
4988 // dbg(0,"return 003\n");
4989 return2;
4990 }
4991 */
4992
4993 } // while item=map_rect_get_item
4994 // ------ READ all items in this map rectangle ---------
4995 // ------ READ all items in this map rectangle ---------
4996 // ------ READ all items in this map rectangle ---------
4997 // ------ READ all items in this map rectangle ---------
4998 // ------ READ all items in this map rectangle ---------
4999
5000 //dbg(0,"MAP:013:map=%s\n", ttt22);
5001
5002 ////DBG // dbg(0, "XXXXXYYYYYYY Draw: A.02\n");
5003
5004 // ************** map_rect_destroy(displaylist->mr);
5005 }
5006
5007 map_rect_destroy(displaylist->mr);
5008 }
5009
5010
5011 if (!route_selection)
5012 {
5013 map_selection_destroy(displaylist->sel);
5014 }
5015
5016 displaylist->mr = NULL;
5017 displaylist->sel = NULL;
5018 displaylist->m = NULL;
5019 } // while ----
5020
5021
5022 // dbg(0, "DO__DRAW:%d load ready\n", rnd);
5023
5024 #ifdef NAVIT_MEASURE_TIME_DEBUG
5025 debug_mrp("do_draw:load", debug_measure_end(s_));
5026 #endif
5027 s_ = debug_measure_start();
5028
5029
5030
5031 // dbg(0, "DO__DRAW:%d dummy \"draw-start\" signal\n", rnd);
5032 #ifdef HAVE_API_ANDROID
5033 android_return_generic_int(2, 77);
5034 #endif
5035
5036 // remove the "wait" screen
5037 //#ifdef HAVE_API_ANDROID
5038 // android_return_generic_int(2, 0);
5039 //#endif
5040
5041 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 004\n");
5042
5043 // reset value;
5044 // cancel_drawing_global = 0;
5045
5046 // restore order :-)
5047 displaylist->order = saved;
5048
5049 // profile(1,"process_selection\n");
5050
5051
5052 if (displaylist->idle_ev)
5053 {
5054 event_remove_idle(displaylist->idle_ev);
5055 displaylist->idle_ev = NULL;
5056 }
5057
5058 if (displaylist->idle_cb)
5059 {
5060 callback_destroy(displaylist->idle_cb);
5061 displaylist->idle_cb = NULL;
5062 }
5063
5064 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
5065 //displaylist->busy = 0;
5066
5067 // graphics_process_selection(displaylist->dc.gra, displaylist);
5068
5069 //profile(1, "draw\n");
5070
5071 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 005\n");
5072
5073 if (!cancel)
5074 {
5075 int flags2 = flags;
5076 if (!(flags2 & 2))
5077 {
5078 // -- now always clean bg of screen!! 2013-07-08 Zoff
5079 //if (!draw_vector_map)
5080 //{
5081 // // dont clean bg of screen when drawing prerendered tiles
5082 // flags2 = flags2 + 2;
5083 //}
5084 }
5085 //DBG // dbg(0,"call graphics_displaylist_draw 3")
5086 //// dbg(0,"# MT:002 #\n");
5087
5088 // stop drawing is requested
5089 if (cancel_drawing_global != 1)
5090 {
5091 graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
5092 }
5093 //// dbg(0,"# MT:003 #\n");
5094 }
5095
5096 #ifdef NAVIT_MEASURE_TIME_DEBUG
5097 debug_mrp("do_draw:draw", debug_measure_end(s_));
5098 #endif
5099
5100 // dbg(0, "DO__DRAW:%d draw ready\n", rnd);
5101
5102 #ifdef HAVE_API_ANDROID
5103 if (cur_mapdraw_time_index < 11)
5104 {
5105 mapdraw_time[cur_mapdraw_time_index] = debug_measure_end_tsecs(s_);
5106 // // dbg(0,"maptime: %d\n", mapdraw_time[cur_mapdraw_time_index]);
5107 cur_mapdraw_time_index++;
5108 }
5109
5110 if (cur_mapdraw_time_index > 10)
5111 {
5112 cur_mapdraw_time_index = 0;
5113 int jk;
5114 int mean_time = 0;
5115 for (jk=0;jk<11;jk++)
5116 {
5117 mean_time = mean_time + mapdraw_time[jk];
5118 }
5119 android_return_generic_int(6, (int)((float)mean_time / (float)10));
5120 }
5121 #endif
5122
5123 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
5124 displaylist->busy = 0;
5125
5126 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 006\n");
5127
5128 map_rect_destroy(displaylist->mr);
5129 if (!route_selection)
5130 {
5131 map_selection_destroy(displaylist->sel);
5132 }
5133 mapset_close(displaylist->msh);
5134 displaylist->mr = NULL;
5135 displaylist->sel = NULL;
5136 displaylist->m = NULL;
5137 displaylist->msh = NULL;
5138
5139 //dbg(0, "callback\n");
5140
5141 // only some old crap need this!! ----------
5142 // only some old crap need this!! ----------
5143 /// **** callback_call_1(displaylist->cb, cancel);
5144 // only some old crap need this!! ----------
5145 // only some old crap need this!! ----------
5146
5147
5148 // dbg(0, "DO__DRAW:%d UN-lock mutex leave\n", rnd);
5149 pthread_mutex_unlock(&uiConditionMutex);
5150 // dbg(0, "DO__DRAW:%d OK UN-lock mutex leave\n", rnd);
5151
5152 // dbg(0, "DO__DRAW:%d cancel_drawing_global 99=%d\n", rnd, cancel_drawing_global);
5153
5154 if (cancel_drawing_global != 1)
5155 {
5156 // dummy "ready" signal ------------------------------------------
5157 // dbg(0, "DO__DRAW:%d dummy \"ready\" signal\n", rnd);
5158 // gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 99);
5159 #ifdef HAVE_API_ANDROID
5160 android_return_generic_int(2, 2);
5161 #endif
5162 // dummy "ready" signal ------------------------------------------
5163 }
5164 else
5165 {
5166 // dummy "cancel" signal ------------------------------------------
5167 // dbg(0, "DO__DRAW:%d dummy \"cancel\" signal\n", rnd);
5168 //gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 95);
5169 #ifdef HAVE_API_ANDROID
5170 android_return_generic_int(2, 3);
5171 #endif
5172 // dummy "ready" signal ------------------------------------------
5173 }
5174
5175 // dbg(0, "DO__DRAW:%d leave\n", rnd);
5176 // dbg(0, "DO__DRAW:%d __\n", rnd);
5177
5178 __F_END__
5179 }
5180
5181 /**
5182 * FIXME
5183 * @param <>
5184 * @returns <>
5185 * @author Martin Schaller (04/2008)
5186 */
5187 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
5188 {
5189 __F_START__
5190
5191 // // dbg(0,"ooo enter ooo flags=%d\n", flags);
5192
5193
5194 int order = transform_get_order(trans);
5195 displaylist->dc.trans = trans;
5196 displaylist->dc.gra = gra;
5197
5198 // *********DISABLED*******
5199 // *********DISABLED*******
5200 // *********DISABLED*******
5201 // set min. distancte of 2 points on line at which a point will be left out when zoomed out too much!!
5202 // *********DISABLED******* displaylist->dc.mindist = transform_get_scale(trans) / 2;
5203 //// dbg(0,"mindist would be:%d\n", (int)(transform_get_scale(trans) / 2));
5204 displaylist->dc.mindist = 0;
5205 if (order < 6)
5206 {
5207 displaylist->dc.mindist = transform_get_scale(trans) * 4;
5208 }
5209 else if (order < 9)
5210 {
5211 displaylist->dc.mindist = transform_get_scale(trans) * 3;
5212 }
5213 else if (order < 13)
5214 {
5215 displaylist->dc.mindist = transform_get_scale(trans) * 2;
5216 }
5217 // *********DISABLED*******
5218 // *********DISABLED*******
5219 // *********DISABLED*******
5220
5221
5222 // FIXME find a better place to set the background color
5223 if (l)
5224 {
5225
5226 if (global_night_mode == 1)
5227 {
5228 graphics_gc_set_background(gra->gc[0], &background_night_mode);
5229 graphics_gc_set_foreground(gra->gc[0], &background_night_mode);
5230 }
5231 else
5232 {
5233 graphics_gc_set_background(gra->gc[0], &l->color);
5234 graphics_gc_set_foreground(gra->gc[0], &l->color);
5235 }
5236 gra->default_font = g_strdup(l->font);
5237 }
5238
5239 graphics_background_gc(gra, gra->gc[0]);
5240
5241 if (flags & 1)
5242 {
5243 // calls -> navit.c navit_predraw --> draw all vehicles
5244 // *********++-- DISABLED --++******* // callback_list_call_attr_0(gra->cbl, attr_predraw);
5245 navit_predraw(global_navit);
5246 }
5247
5248 gra->meth.draw_mode(gra->priv, (flags & 8) ? draw_mode_begin_clear : draw_mode_begin);
5249
5250 if (!(flags & 2))
5251 {
5252 // clear the gfx object pipeline ------------------------------
5253 // // dbg(0, "clear the gfx object pipeline\n");
5254 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 98);
5255
5256 // clear the display/screen/whatever here
5257 // 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);
5258 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);
5259 }
5260
5261 if (l)
5262 {
5263 // draw the mapitems
5264 // // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
5265 xdisplay_draw(displaylist, gra, l, order + l->order_delta);
5266 }
5267
5268 if (flags & 1)
5269 {
5270 // calls: "graphics_displaylist_draw"
5271 // ***********++-- DISABLED --++*********** // callback_list_call_attr_0(gra->cbl, attr_postdraw);
5272 }
5273
5274 if (!(flags & 4))
5275 {
5276 gra->meth.draw_mode(gra->priv, draw_mode_end);
5277 }
5278
5279 __F_END__
5280 }
5281
5282 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)
5283 {
5284 __F_START__
5285
5286 int order = transform_get_order(trans);
5287
5288 if (displaylist->busy)
5289 {
5290 if (async == 1)
5291 {
5292 return2;
5293 }
5294 return2;
5295 }
5296 xdisplay_free(displaylist);
5297
5298 displaylist->dc.gra = gra;
5299 displaylist->ms = mapset;
5300 displaylist->dc.trans = trans;
5301 displaylist->workload = async ? 100 : 0;
5302 displaylist->cb = cb;
5303 displaylist->seq++;
5304
5305 if (l)
5306 {
5307 order += l->order_delta;
5308 }
5309 displaylist->order = order;
5310 displaylist->busy = 1;
5311 displaylist->layout = l;
5312
5313 // ---------- DISABLED ------ no more async!!
5314 /*
5315 if (async)
5316 {
5317 //DBG // dbg(0,"§§async");
5318 if (!displaylist->idle_cb)
5319 {
5320 //DBG // dbg(0,"§§async --> callback");
5321 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
5322 }
5323 //DBG // dbg(0,"§§async --> add idle");
5324 displaylist->idle_ev = event_add_idle(50, displaylist->idle_cb);
5325 }
5326 else
5327 {
5328 //DBG // dbg(0,"@@sync");
5329 do_draw(displaylist, 0, flags);
5330 }
5331 */
5332
5333 if (async)
5334 {
5335 //if (!displaylist->idle_cb)
5336 //{
5337 // this calls "do_draw"
5338 // *++*-- DISABLED --*++* // displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
5339 // *++*-- DISABLED --*++* // callback_add_names(displaylist->idle_cb, "graphics_load_mapset", "do_draw");
5340 do_draw(displaylist, 0, flags);
5341 //}
5342 //dbg(0, "DO__DRAW:call 003 (async callback)\n");
5343 // *++*-- DISABLED --*++* // displaylist->idle_ev = event_add_idle(1000, displaylist->idle_cb);
5344 }
5345 else
5346 {
5347 //// dbg(0,"**draw 2.b5\n");
5348 // dbg(0, "DO__DRAW:call 001\n");
5349 do_draw(displaylist, 0, flags);
5350 }
5351
5352 __F_END__
5353 }
5354
5355 /**
5356 * FIXME
5357 * @param <>
5358 * @returns <>
5359 * @author Martin Schaller (04/2008)
5360 */
5361 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)
5362 {
5363 __F_START__
5364 //// dbg(0,"ooo enter ooo\n");
5365
5366 // dbg(0, "DO__DRAW:gras_draw enter\n");
5367 graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
5368 // dbg(0, "DO__DRAW:gras_draw leave\n");
5369 __F_END__
5370 }
5371
5372 int graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
5373 {
5374 __F_START__
5375
5376 if (!displaylist->busy)
5377 {
5378 return2 0;
5379 }
5380 // dbg(0, "DO__DRAW:call 002\n");
5381 do_draw(displaylist, 1, 0);
5382 return2 1;
5383
5384 __F_END__
5385 }
5386
5387 /**
5388 * FIXME
5389 * @param <>
5390 * @returns <>
5391 * @author Martin Schaller (04/2008)
5392 */
5393 struct displaylist_handle
5394 {
5395 struct displaylist *dl;
5396 struct displayitem *di;
5397 int hashidx;
5398 };
5399
5400 /**
5401 * FIXME
5402 * @param <>
5403 * @returns <>
5404 * @author Martin Schaller (04/2008)
5405 */
5406 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
5407 {
5408 struct displaylist_handle *ret;
5409
5410 ret=g_new0(struct displaylist_handle, 1);
5411 ret->dl = displaylist;
5412
5413 return ret;
5414 }
5415
5416 /**
5417 * FIXME
5418 * @param <>
5419 * @returns <>
5420 * @author Martin Schaller (04/2008)
5421 */
5422 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
5423 {
5424 struct displayitem *ret;
5425 if (!dlh)
5426 return NULL;
5427 for (;;)
5428 {
5429 if (dlh->di)
5430 {
5431 ret = dlh->di;
5432 dlh->di = ret->next;
5433 break;
5434 }
5435 if (dlh->hashidx == HASH_SIZE_GRAPHICS_)
5436 {
5437 ret = NULL;
5438 break;
5439 }
5440 if (dlh->dl->hash_entries[dlh->hashidx].type)
5441 dlh->di = dlh->dl->hash_entries[dlh->hashidx].di;
5442 dlh->hashidx++;
5443 }
5444 return ret;
5445 }
5446
5447 /**
5448 * FIXME
5449 * @param <>
5450 * @returns <>
5451 * @author Martin Schaller (04/2008)
5452 */
5453 void graphics_displaylist_close(struct displaylist_handle *dlh)
5454 {
5455 g_free(dlh);
5456 }
5457
5458 /**
5459 * FIXME
5460 * @param <>
5461 * @returns <>
5462 * @author Martin Schaller (04/2008)
5463 */
5464 struct displaylist * graphics_displaylist_new(void)
5465 {
5466 struct displaylist *ret=g_new0(struct displaylist, 1);
5467
5468 ret->dc.maxlen = 16384;
5469 ret->busy = 0;
5470
5471 return ret;
5472 }
5473
5474 /**
5475 * FIXME
5476 * @param <>
5477 * @returns <>
5478 * @author Martin Schaller (04/2008)
5479 */
5480 struct item * graphics_displayitem_get_item(struct displayitem *di)
5481 {
5482 return &di->item;
5483 }
5484
5485 int graphics_displayitem_get_coord_count(struct displayitem *di)
5486 {
5487 return di->count;
5488 }
5489
5490 /**
5491 * FIXME
5492 * @param <>
5493 * @returns <>
5494 * @author Martin Schaller (04/2008)
5495 */
5496 char * graphics_displayitem_get_label(struct displayitem *di)
5497 {
5498 return di->label;
5499 }
5500
5501 int graphics_displayitem_get_displayed(struct displayitem *di)
5502 {
5503 return 1;
5504 }
5505
5506 /**
5507 * FIXME
5508 * @param <>
5509 * @returns <>
5510 * @author Martin Schaller (04/2008)
5511 */
5512 static int within_dist_point(struct point *p0, struct point *p1, int dist)
5513 {
5514 if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
5515 return 0;
5516 if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
5517 return 0;
5518 if ((p0->x - p1->x) * (p0->x - p1->x) + (p0->y - p1->y) * (p0->y - p1->y) <= dist * dist)
5519 {
5520 return 1;
5521 }
5522 return 0;
5523 }
5524
5525 /**
5526 * FIXME
5527 * @param <>
5528 * @returns <>
5529 * @author Martin Schaller (04/2008)
5530 */
5531 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
5532 {
5533 int vx, vy, wx, wy;
5534 int c1, c2;
5535 struct point line_p;
5536
5537 if (line_p0->x < line_p1->x)
5538 {
5539 if (p->x < line_p0->x - dist)
5540 return 0;
5541 if (p->x > line_p1->x + dist)
5542 return 0;
5543 }
5544 else
5545 {
5546 if (p->x < line_p1->x - dist)
5547 return 0;
5548 if (p->x > line_p0->x + dist)
5549 return 0;
5550 }
5551 if (line_p0->y < line_p1->y)
5552 {
5553 if (p->y < line_p0->y - dist)
5554 return 0;
5555 if (p->y > line_p1->y + dist)
5556 return 0;
5557 }
5558 else
5559 {
5560 if (p->y < line_p1->y - dist)
5561 return 0;
5562 if (p->y > line_p0->y + dist)
5563 return 0;
5564 }
5565
5566 vx = line_p1->x - line_p0->x;
5567 vy = line_p1->y - line_p0->y;
5568 wx = p->x - line_p0->x;
5569 wy = p->y - line_p0->y;
5570
5571 c1 = vx * wx + vy * wy;
5572 if (c1 <= 0)
5573 return within_dist_point(p, line_p0, dist);
5574 c2 = vx * vx + vy * vy;
5575 if (c2 <= c1)
5576 return within_dist_point(p, line_p1, dist);
5577
5578 line_p.x = line_p0->x + vx * c1 / c2;
5579 line_p.y = line_p0->y + vy * c1 / c2;
5580 return within_dist_point(p, &line_p, dist);
5581 }
5582
5583 /**
5584 * FIXME
5585 * @param <>
5586 * @returns <>
5587 * @author Martin Schaller (04/2008)
5588 */
5589 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
5590 {
5591 int i;
5592 for (i = 0; i < count - 1; i++)
5593 {
5594 if (within_dist_line(p, line_pnt + i, line_pnt + i + 1, dist))
5595 {
5596 return 1;
5597 }
5598 }
5599 if (close)
5600 return (within_dist_line(p, line_pnt, line_pnt + count - 1, dist));
5601 return 0;
5602 }
5603
5604 /**
5605 * FIXME
5606 * @param <>
5607 * @returns <>
5608 * @author Martin Schaller (04/2008)
5609 */
5610 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
5611 {
5612 int i, j, c = 0;
5613 for (i = 0, j = count - 1; i < count; j = i++)
5614 {
5615 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))
5616 c = !c;
5617 }
5618 if (!c)
5619 return within_dist_polyline(p, poly_pnt, count, dist, 1);
5620 return c;
5621 }
5622
5623 /**
5624 * FIXME
5625 * @param <>
5626 * @returns <>
5627 * @author Martin Schaller (04/2008)
5628 */
5629 int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
5630 {
5631 struct point *pa = g_alloca(sizeof(struct point) * displaylist->dc.maxlen);
5632 int count;
5633
5634 count = transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
5635
5636 if (di->item.type < type_line)
5637 {
5638 return within_dist_point(p, &pa[0], dist);
5639 }
5640 if (di->item.type < type_area)
5641 {
5642 return within_dist_polyline(p, pa, count, dist, 0);
5643 }
5644 return within_dist_polygon(p, pa, count, dist);
5645 }
5646
5647 static void graphics_process_selection_item(struct displaylist *dl, struct item *item)
5648 {
5649 #if 0 /* FIXME */
5650 struct displayitem di,*di_res;
5651 GHashTable *h;
5652 int count,max=dl->dc.maxlen;
5653 struct coord ca[max];
5654 struct attr attr;
5655 struct map_rect *mr;
5656
5657 di.item=*item;
5658 di.label=NULL;
5659 di.count=0;
5660 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
5661 if (h)
5662 {
5663 di_res=g_hash_table_lookup(h, &di);
5664 if (di_res)
5665 {
5666 di.item.type=(enum item_type)item->priv_data;
5667 display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
5668 return;
5669 }
5670 }
5671
5672 mr=map_rect_new(item->map, NULL);
5673 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
5674 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
5675
5676 if (!item_attr_get(item, attr_label, &attr))
5677 {
5678 attr.u.str=NULL;
5679 }
5680
5681 if (dl->conv && attr.u.str && attr.u.str[0])
5682 {
5683 char *str=map_convert_string(item->map, attr.u.str);
5684 display_add(dl, item, count, ca, &str, 1);
5685 map_convert_free(str);
5686 }
5687 else
5688 display_add(dl, item, count, ca, &attr.u.str, 1);
5689 map_rect_destroy(mr);
5690 #endif
5691 }
5692
5693 void graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
5694 {
5695 struct item *item_dup=g_new(struct item, 1);
5696 *item_dup = *item;
5697 item_dup->priv_data = (void *) type;
5698 gra->selection = g_list_append(gra->selection, item_dup);
5699 if (dl)
5700 graphics_process_selection_item(dl, item_dup);
5701 }
5702
5703 void graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
5704 {
5705 GList *curr;
5706 int found;
5707
5708 for (;;)
5709 {
5710 curr = gra->selection;
5711 found = 0;
5712 while (curr)
5713 {
5714 struct item *sitem = curr->data;
5715 if (item_is_equal(*item, *sitem))
5716 {
5717 if (dl)
5718 {
5719 struct displayitem di;
5720 /* Unused Variable
5721 GHashTable *h; */
5722 di.item = *sitem;
5723 di.label = NULL;
5724 di.count = 0;
5725 di.item.type = type;
5726 #if 0 /* FIXME */
5727 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
5728 if (h)
5729 g_hash_table_remove(h, &di);
5730 #endif
5731 }
5732 g_free(sitem);
5733 gra->selection = g_list_remove(gra->selection, curr->data);
5734 found = 1;
5735 break;
5736 }
5737 }
5738 if (!found)
5739 return;
5740 }
5741 }
5742
5743 void graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
5744 {
5745 while (gra->selection)
5746 {
5747 struct item *item = (struct item *) gra->selection->data;
5748 graphics_remove_selection(gra, item, (enum item_type) item->priv_data, dl);
5749 }
5750 }
5751
5752 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl)
5753 {
5754 GList *curr;
5755
5756 curr = gra->selection;
5757 while (curr)
5758 {
5759 struct item *item = curr->data;
5760 graphics_process_selection_item(dl, item);
5761 curr = g_list_next(curr);
5762 }
5763 }

   
Visit the ZANavi Wiki