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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki