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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki