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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki