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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 98457 byte(s)
new map version, lots of fixes and experimental new features
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 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 "navit.h"
75 #include "route.h"
76
77 #ifdef HAVE_API_ANDROID
78 // nothing todo for android
79 #else
80 // linux seems to need this explicitly
81 #include "pthread.h"
82 #endif
83
84 static pthread_cond_t uiConditionVariable = PTHREAD_COND_INITIALIZER;
85 static pthread_mutex_t uiConditionMutex = PTHREAD_MUTEX_INITIALIZER;
86
87 //##############################################################################################################
88 //# Description:
89 //# Comment:
90 //# Authors: Martin Schaller (04/2008)
91 //##############################################################################################################
92
93 // above what "order" level to show only prerendered map
94 #define ORDER_USE_PRERENDERED_MAP 0
95 // minimum (line legth * 32) squared (in pixel) to show text label
96 #define MIN_LINE_LENGTH_FOR_TEXT_2 409600
97 // minimum (line legth * 32) squared (in pixel) to show text label -> for middle segments of streets
98 #define MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2 1638400
99
100 #define ORDER_LEVEL_FOR_STREET_SIMPLIFY 9
101 #define STREET_SIMPLIFY 24
102
103 struct graphics
104 {
105 struct graphics_priv *priv;
106 struct graphics_methods meth;
107 char *default_font;
108 int font_len;
109 struct graphics_font **font;
110 struct graphics_gc *gc[3];
111 struct attr **attrs;
112 struct callback_list *cbl;
113 struct point_rect r;
114 int gamma, brightness, contrast;
115 int colormgmt;
116 int font_size;
117 GList *selection;
118 };
119
120 /*
121 struct display_context
122 {
123 struct graphics *gra;
124 struct element *e;
125 struct graphics_gc *gc;
126 struct graphics_gc *gc_background;
127 struct graphics_image *img;
128 enum projection pro;
129 int mindist;
130 struct transformation *trans;
131 enum item_type type;
132 int maxlen;
133 };
134
135 #define HASH_SIZE 1024
136 */
137
138 /*
139 struct hash_entry
140 {
141 enum item_type type;
142 struct displayitem *di;
143 };
144 */
145
146 /*
147 struct displaylist {
148 int busy;
149 int workload;
150 struct callback *cb;
151 struct layout *layout, *layout_hashed;
152 struct display_context dc;
153 int order, order_hashed, max_offset;
154 struct mapset *ms;
155 struct mapset_handle *msh;
156 struct map *m;
157 int conv;
158 struct map_selection *sel;
159 struct map_rect *mr;
160 struct callback *idle_cb;
161 struct event_idle *idle_ev;
162 unsigned int seq;
163 struct hash_entry hash_entries[HASH_SIZE];
164 };
165 */
166
167 struct displaylist_icon_cache
168 {
169 unsigned int seq;
170
171 };
172
173 /**
174 * FIXME
175 * @param <>
176 * @returns <>
177 * @author Martin Schaller (04/2008)
178 */
179 struct displayitem
180 {
181 struct displayitem *next;
182 struct item item;
183 char *label;
184 int count;
185 struct coord c[0];
186 };
187
188 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir);
189 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl);
190 static void graphics_gc_init(struct graphics *this_);
191
192 static void clear_hash(struct displaylist *dl)
193 {
194 int i;
195 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
196 {
197 dl->hash_entries[i].type = type_none;
198 }
199 }
200
201 static struct hash_entry *
202 get_hash_entry(struct displaylist *dl, enum item_type type)
203 {
204 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
205 int offset = dl->max_offset;
206 do
207 {
208 if (!dl->hash_entries[hashidx].type)
209 {
210 return NULL;
211 }
212 if (dl->hash_entries[hashidx].type == type)
213 {
214 return &dl->hash_entries[hashidx];
215 }
216 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
217 }
218 while (offset-- > 0);
219
220 return NULL;
221 }
222
223 static struct hash_entry *
224 set_hash_entry(struct displaylist *dl, enum item_type type)
225 {
226 int hashidx = (type * 2654435761UL) & (HASH_SIZE_GRAPHICS_ - 1);
227 int offset = 0;
228 for (;;)
229 {
230 if (!dl->hash_entries[hashidx].type)
231 {
232 dl->hash_entries[hashidx].type = type;
233 if (dl->max_offset < offset)
234 dl->max_offset = offset;
235 return &dl->hash_entries[hashidx];
236 }
237 if (dl->hash_entries[hashidx].type == type)
238 return &dl->hash_entries[hashidx];
239 hashidx = (hashidx + 1) & (HASH_SIZE_GRAPHICS_ - 1);
240 offset++;
241 }
242 return NULL;
243 }
244
245 static int graphics_set_attr_do(struct graphics *gra, struct attr *attr)
246 {
247 switch (attr->type)
248 {
249 case attr_gamma:
250 gra->gamma = attr->u.num;
251 break;
252 case attr_brightness:
253 gra->brightness = attr->u.num;
254 break;
255 case attr_contrast:
256 gra->contrast = attr->u.num;
257 break;
258 case attr_font_size:
259 gra->font_size = attr->u.num;
260 return 1;
261 default:
262 return 0;
263 }
264 gra->colormgmt = (gra->gamma != 65536 || gra->brightness != 0 || gra->contrast != 65536);
265 graphics_gc_init(gra);
266 return 1;
267 }
268
269 int graphics_set_attr(struct graphics *gra, struct attr *attr)
270 {
271 int ret = 1;
272 // //DBG // dbg(0,"enter\n");
273 if (gra->meth.set_attr)
274 ret = gra->meth.set_attr(gra->priv, attr);
275 if (!ret)
276 ret = graphics_set_attr_do(gra, attr);
277 return ret != 0;
278 }
279
280 void graphics_set_rect(struct graphics *gra, struct point_rect *pr)
281 {
282 gra->r = *pr;
283 }
284
285 /**
286 * Creates a new graphics object
287 * attr type required
288 * @param <>
289 * @returns <>
290 * @author Martin Schaller (04/2008)
291 */
292 struct graphics * graphics_new(struct attr *parent, struct attr **attrs)
293 {
294 // dbg(0, "EEnter\n");
295
296 int count = 0;
297 struct graphics *this_;
298 struct attr *type_attr;
299 struct graphics_priv * (*graphicstype_new)(struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl);
300
301 if (!(type_attr = attr_search(attrs, NULL, attr_type)))
302 {
303 return NULL;
304 }
305
306 // dbg(0, "plugins\n");
307
308 graphicstype_new = plugin_get_graphics_type(type_attr->u.str);
309 if (!graphicstype_new)
310 {
311 return NULL;
312 }
313
314 // dbg(0, "g 003\n");
315
316 this_=g_new0(struct graphics, 1);
317 this_->cbl = callback_list_new();
318 // dbg(0, "g 003.1\n");
319 this_->priv = (*graphicstype_new)(parent->u.navit, &this_->meth, attrs, this_->cbl);
320 // dbg(0, "g 003.2\n");
321 this_->attrs = attr_list_dup(attrs);
322 this_->brightness = 0;
323 this_->contrast = 65536;
324 this_->gamma = 65536;
325 this_->font_size = 20;
326
327 // dbg(0, "g 004\n");
328
329 while (*attrs)
330 {
331 count++;
332 // dbg(0, "g 005 attr %d\n", count);
333 graphics_set_attr_do(this_, *attrs);
334 attrs++;
335 // dbg(0, "g 006 attr\n");
336 }
337
338 // dbg(0, "return\n");
339 return this_;
340 }
341
342 /**
343 * FIXME
344 * @param <>
345 * @returns <>
346 * @author Martin Schaller (04/2008)
347 */
348 int graphics_get_attr(struct graphics *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
349 {
350 return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
351 }
352
353 /**
354 * FIXME
355 * @param <>
356 * @returns <>
357 * @author Martin Schaller (04/2008)
358 */
359 struct graphics * graphics_overlay_new(const char* name, struct graphics *parent, struct point *p, int w, int h, int alpha, int wraparound)
360 {
361 struct graphics *this_;
362 struct point_rect pr;
363 if (!parent->meth.overlay_new)
364 return NULL;this_=g_new0(struct graphics, 1);
365 this_->priv = parent->meth.overlay_new(name, parent->priv, &this_->meth, p, w, h, alpha, wraparound);
366 pr.lu.x = 0;
367 pr.lu.y = 0;
368 pr.rl.x = w;
369 pr.rl.y = h;
370 this_->font_size = 20;
371 graphics_set_rect(this_, &pr);
372 if (!this_->priv)
373 {
374 g_free(this_);
375 this_ = NULL;
376 }
377 return this_;
378 }
379
380 /**
381 * @brief Alters the size, position, alpha and wraparound for an overlay
382 *
383 * @param this_ The overlay's graphics struct
384 * @param p The new position of the overlay
385 * @param w The new width of the overlay
386 * @param h The new height of the overlay
387 * @param alpha The new alpha of the overlay
388 * @param wraparound The new wraparound of the overlay
389 */
390 void graphics_overlay_resize(struct graphics *this_, struct point *p, int w, int h, int alpha, int wraparound)
391 {
392 if (!this_->meth.overlay_resize)
393 {
394 return;
395 }
396
397 this_->meth.overlay_resize(this_->priv, p, w, h, alpha, wraparound);
398 }
399
400 static void graphics_gc_init(struct graphics *this_)
401 {
402 // dbg(0, "EEnter\n");
403
404 struct color background = { COLOR_BACKGROUND_ };
405 struct color black = { COLOR_BLACK_ };
406 struct color white = { COLOR_WHITE_ };
407 if (!this_->gc[0] || !this_->gc[1] || !this_->gc[2])
408 return;
409 graphics_gc_set_background(this_->gc[0], &background);
410 graphics_gc_set_foreground(this_->gc[0], &background);
411 graphics_gc_set_background(this_->gc[1], &black);
412 graphics_gc_set_foreground(this_->gc[1], &white);
413 graphics_gc_set_background(this_->gc[2], &white);
414 graphics_gc_set_foreground(this_->gc[2], &black);
415
416 // dbg(0, "return\n");
417 }
418
419 /**
420 * FIXME
421 * @param <>
422 * @returns <>
423 * @author Martin Schaller (04/2008)
424 */
425 void graphics_init(struct graphics *this_)
426 {
427 if (this_->gc[0])
428 return;
429 this_->gc[0] = graphics_gc_new(this_);
430 this_->gc[1] = graphics_gc_new(this_);
431 this_->gc[2] = graphics_gc_new(this_);
432 graphics_gc_init(this_);
433 graphics_background_gc(this_, this_->gc[0]);
434 }
435
436 /**
437 * FIXME
438 * @param <>
439 * @returns <>
440 * @author Martin Schaller (04/2008)
441 */
442 void * graphics_get_data(struct graphics *this_, const char *type)
443 {
444 return (this_->meth.get_data(this_->priv, type));
445 }
446
447 void graphics_add_callback(struct graphics *this_, struct callback *cb)
448 {
449 callback_list_add(this_->cbl, cb);
450 }
451
452 void graphics_remove_callback(struct graphics *this_, struct callback *cb)
453 {
454 callback_list_remove(this_->cbl, cb);
455 }
456
457 /**
458 * FIXME
459 * @param <>
460 * @returns <>
461 * @author Martin Schaller (04/2008)
462 */
463 struct graphics_font * graphics_font_new(struct graphics *gra, int size, int flags)
464 {
465 struct graphics_font *this_;
466
467 this_=g_new0(struct graphics_font,1);
468 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, gra->default_font, size, flags);
469 return this_;
470 }
471
472 struct graphics_font * graphics_named_font_new(struct graphics *gra, char *font, int size, int flags)
473 {
474 struct graphics_font *this_;
475
476 this_=g_new0(struct graphics_font,1);
477 this_->priv = gra->meth.font_new(gra->priv, &this_->meth, font, size, flags);
478 return this_;
479 }
480
481 /**
482 * Destroy graphics
483 * Called when navit exits
484 * @param gra The graphics instance
485 * @returns nothing
486 * @author David Tegze (02/2011)
487 */
488 void graphics_free(struct graphics *gra)
489 {
490 if (!gra)
491 return;
492 gra->meth.graphics_destroy(gra->priv);
493 g_free(gra->default_font);
494 graphics_font_destroy_all(gra);
495 g_free(gra);
496 }
497
498 /**
499 * Free all loaded fonts.
500 * Used when switching layouts.
501 * @param gra The graphics instance
502 * @returns nothing
503 * @author Sarah Nordstrom (05/2008)
504 */
505 void graphics_font_destroy_all(struct graphics *gra)
506 {
507 int i;
508 for (i = 0; i < gra->font_len; i++)
509 {
510 if (!gra->font[i])
511 continue;
512 gra->font[i]->meth.font_destroy(gra->font[i]->priv);
513 gra->font[i] = NULL;
514 }
515 }
516
517 /**
518 * FIXME
519 * @param <>
520 * @returns <>
521 * @author Martin Schaller (04/2008)
522 */
523 struct graphics_gc * graphics_gc_new(struct graphics *gra)
524 {
525 struct graphics_gc *this_;
526
527 this_=g_new0(struct graphics_gc,1);
528 this_->priv = gra->meth.gc_new(gra->priv, &this_->meth);
529 this_->gra = gra;
530 return this_;
531 }
532
533 /**
534 * FIXME
535 * @param <>
536 * @returns <>
537 * @author Martin Schaller (04/2008)
538 */
539 void graphics_gc_destroy(struct graphics_gc *gc)
540 {
541 gc->meth.gc_destroy(gc->priv);
542 g_free(gc);
543 }
544
545 static void graphics_convert_color(struct graphics *gra, struct color *in, struct color *out)
546 {
547 *out = *in;
548 if (gra->brightness)
549 {
550 out->r += gra->brightness;
551 out->g += gra->brightness;
552 out->b += gra->brightness;
553 }
554 if (gra->contrast != 65536)
555 {
556 out->r = out->r * gra->contrast / 65536;
557 out->g = out->g * gra->contrast / 65536;
558 out->b = out->b * gra->contrast / 65536;
559 }
560 if (out->r < 0)
561 out->r = 0;
562 if (out->r > 65535)
563 out->r = 65535;
564 if (out->g < 0)
565 out->g = 0;
566 if (out->g > 65535)
567 out->g = 65535;
568 if (out->b < 0)
569 out->b = 0;
570 if (out->b > 65535)
571 out->b = 65535;
572 if (gra->gamma != 65536)
573 {
574 out->r = pow(out->r / 65535.0, gra->gamma / 65536.0) * 65535.0;
575 out->g = pow(out->g / 65535.0, gra->gamma / 65536.0) * 65535.0;
576 out->b = pow(out->b / 65535.0, gra->gamma / 65536.0) * 65535.0;
577 }
578 }
579
580 /**
581 * FIXME
582 * @param <>
583 * @returns <>
584 * @author Martin Schaller (04/2008)
585 */
586 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
587 {
588 struct color cn;
589 if (gc->gra->colormgmt)
590 {
591 graphics_convert_color(gc->gra, c, &cn);
592 c = &cn;
593 }
594 gc->meth.gc_set_foreground(gc->priv, c);
595 }
596
597 /**
598 * FIXME
599 * @param <>
600 * @returns <>
601 * @author Martin Schaller (04/2008)
602 */
603 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
604 {
605 struct color cn;
606 if (gc->gra->colormgmt)
607 {
608 graphics_convert_color(gc->gra, c, &cn);
609 c = &cn;
610 }
611 gc->meth.gc_set_background(gc->priv, c);
612 }
613
614 /**
615 * FIXME
616 * @param <>
617 * @returns <>
618 * @author Martin Schaller (04/2008)
619 */
620 void graphics_gc_set_stipple(struct graphics_gc *gc, struct graphics_image *img)
621 {
622 gc->meth.gc_set_stipple(gc->priv, img ? img->priv : NULL);
623 }
624
625 /**
626 * FIXME
627 * @param <>
628 * @returns <>
629 * @author Martin Schaller (04/2008)
630 */
631 void graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
632 {
633 gc->meth.gc_set_linewidth(gc->priv, width);
634 }
635
636 /**
637 * FIXME
638 * @param <>
639 * @returns <>
640 * @author Martin Schaller (04/2008)
641 */
642 void graphics_gc_set_dashes(struct graphics *gra, struct graphics_gc *gc, int width, int offset, int dash_list[], int n, int order)
643 {
644 if (gc->meth.gc_set_dashes)
645 {
646 gc->meth.gc_set_dashes(gra->priv, gc->priv, width, offset, dash_list, order);
647 }
648 }
649
650 /**
651 * Create a new image from file path scaled to w and h pixels
652 * @param gra the graphics instance
653 * @param path path of the image to load
654 * @param w width to rescale to
655 * @param h height to rescale to
656 * @returns <>
657 * @author Martin Schaller (04/2008)
658 */
659 struct graphics_image * graphics_image_new_scaled(struct graphics *gra, char *path, int w, int h)
660 {
661 struct graphics_image *this_;
662
663 this_=g_new0(struct graphics_image,1);
664 this_->height = h;
665 this_->width = w;
666 this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, 0);
667 if (!this_->priv)
668 {
669 g_free(this_);
670 this_ = NULL;
671 }
672 return this_;
673 }
674
675 /**
676 * Create a new image from file path scaled to w and h pixels and possibly rotated
677 * @param gra the graphics instance
678 * @param path path of the image to load
679 * @param w width to rescale to
680 * @param h height to rescale to
681 * @param rotate angle to rotate the image. Warning, graphics might only support 90 degree steps here
682 * @returns <>
683 * @author Martin Schaller (04/2008)
684 */
685 struct graphics_image * graphics_image_new_scaled_rotated(struct graphics *gra, char *path, int w, int h, int rotate)
686 {
687 struct graphics_image *this_;
688
689 this_=g_new0(struct graphics_image,1);
690 this_->height = h;
691 this_->width = w;
692 this_->priv = gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot, rotate);
693 if (!this_->priv)
694 {
695 g_free(this_);
696 this_ = NULL;
697 }
698 return this_;
699 }
700
701 /**
702 * Create a new image from file path
703 * @param gra the graphics instance
704 * @param path path of the image to load
705 * @returns <>
706 * @author Martin Schaller (04/2008)
707 */
708 struct graphics_image * graphics_image_new(struct graphics *gra, char *path)
709 {
710 return graphics_image_new_scaled(gra, path, -1, -1);
711 }
712
713 /**
714 * FIXME
715 * @param <>
716 * @returns <>
717 * @author Martin Schaller (04/2008)
718 */
719 void graphics_image_free(struct graphics *gra, struct graphics_image *img)
720 {
721 if (gra->meth.image_free)
722 gra->meth.image_free(gra->priv, img->priv);
723 g_free(img);
724 }
725
726 /**
727 * FIXME
728 * @param <>
729 * @returns <>
730 * @author Martin Schaller (04/2008)
731 */
732 void graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
733 {
734 ////DBG // dbg(0,"ooo enter ooo\n");
735
736 this_->meth.draw_restore(this_->priv, p, w, h);
737 }
738
739 /**
740 * FIXME
741 * @param <>
742 * @returns <>
743 * @author Martin Schaller (04/2008)
744 */
745 void graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
746 {
747 ////DBG // dbg(0,"ooo enter ooo\n");
748
749 this_->meth.draw_mode(this_->priv, mode);
750 }
751
752 /**
753 * FIXME
754 * @param <>
755 * @returns <>
756 * @author Martin Schaller (04/2008)
757 */
758 void graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
759 {
760 this_->meth.draw_lines(this_->priv, gc->priv, p, count);
761 }
762
763 void graphics_draw_lines_dashed(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count, int order, int oneway)
764 {
765 this_->meth.draw_lines_dashed(this_->priv, gc->priv, p, count, order, oneway);
766 }
767
768 /**
769 * FIXME
770 * @param <>
771 * @returns <>
772 * @author Martin Schaller (04/2008)
773 */
774 void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
775 {
776 int i = 0;
777
778 if (this_->meth.draw_circle)
779 {
780 this_->meth.draw_circle(this_->priv, gc->priv, p, r);
781 }
782 else
783 {
784 struct point *pnt = g_alloca(sizeof(struct point) * (r * 4 + 64));
785 draw_circle(p, r, 0, -1, 1026, pnt, &i, 1);
786 pnt[i] = pnt[0];
787 i++;
788 this_->meth.draw_lines(this_->priv, gc->priv, pnt, i);
789 }
790 }
791
792 /**
793 * FIXME
794 * @param <>
795 * @returns <>
796 * @author Martin Schaller (04/2008)
797 */
798 void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
799 {
800 this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
801 }
802
803 void graphics_draw_rectangle_rounded(struct graphics *this_, struct graphics_gc *gc, struct point *plu, int w, int h, int r, int fill)
804 {
805 struct point *p = g_alloca(sizeof(struct point) * (r * 4 + 32));
806 struct point pi0 = { plu->x + r, plu->y + r };
807 struct point pi1 = { plu->x + w - r, plu->y + r };
808 struct point pi2 = { plu->x + w - r, plu->y + h - r };
809 struct point pi3 = { plu->x + r, plu->y + h - r };
810 int i = 0;
811
812 draw_circle(&pi2, r * 2, 0, -1, 258, p, &i, 1);
813 draw_circle(&pi1, r * 2, 0, 255, 258, p, &i, 1);
814 draw_circle(&pi0, r * 2, 0, 511, 258, p, &i, 1);
815 draw_circle(&pi3, r * 2, 0, 767, 258, p, &i, 1);
816 p[i] = p[0];
817 i++;
818 if (fill)
819 this_->meth.draw_polygon(this_->priv, gc->priv, p, i);
820 else
821 this_->meth.draw_lines(this_->priv, gc->priv, p, i);
822 }
823
824 /**
825 * FIXME
826 * @param <>
827 * @returns <>
828 * @author Martin Schaller (04/2008)
829 */
830 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)
831 {
832 this_->meth.draw_text(this_->priv, gc1->priv, gc2 ? gc2->priv : NULL, font->priv, text, p, dx, dy);
833 }
834
835 /**
836 * FIXME
837 * @param <>
838 * @returns <>
839 * @author Martin Schaller (04/2008)
840 */
841 void graphics_get_text_bbox(struct graphics *this_, struct graphics_font *font, char *text, int dx, int dy, struct point *ret, int estimate)
842 {
843 this_->meth.get_text_bbox(this_->priv, font->priv, text, dx, dy, ret, estimate);
844 }
845
846 /**
847 * FIXME
848 * @param <>
849 * @returns <>
850 * @author Martin Schaller (04/2008)
851 */
852 void graphics_overlay_disable(struct graphics *this_, int disable)
853 {
854 if (this_->meth.overlay_disable)
855 this_->meth.overlay_disable(this_->priv, disable);
856 }
857
858 /**
859 * FIXME
860 * @param <>
861 * @returns <>
862 * @author Martin Schaller (04/2008)
863 */
864 void graphics_draw_image(struct graphics *this_, struct graphics_gc *gc, struct point *p, struct graphics_image *img)
865 {
866 this_->meth.draw_image(this_->priv, gc->priv, p, img->priv);
867 }
868
869 /**
870 *
871 *
872 * @author Zoff (2011)
873 */
874 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)
875 {
876 this_->meth.draw_bigmap(this_->priv, gc->priv, yaw, order, clat, clng, x, y, scx, scy, px, py, valid);
877 }
878
879 //##############################################################################################################
880 //# Description:
881 //# Comment:
882 //# Authors: Martin Schaller (04/2008)
883 //##############################################################################################################
884 int graphics_draw_drag(struct graphics *this_, struct point *p)
885 {
886 ////DBG // dbg(0,"ooo enter ooo\n");
887
888 if (!this_->meth.draw_drag)
889 {
890 return 0;
891 }
892 ////DBG // dbg(0,"draw DRAG start ...\n");
893 this_->meth.draw_drag(this_->priv, p);
894 ////DBG // dbg(0,"draw DRAG end ...\n");
895 return 1;
896 }
897
898 void graphics_background_gc(struct graphics *this_, struct graphics_gc *gc)
899 {
900 ////DBG // dbg(0,"ooo enter ooo\n");
901
902 this_->meth.background_gc(this_->priv, gc ? gc->priv : NULL);
903 }
904
905 #include "attr.h"
906 #include "popup.h"
907 #include <stdio.h>
908
909 #if 0
910 //##############################################################################################################
911 //# Description:
912 //# Comment:
913 //# Authors: Martin Schaller (04/2008)
914 //##############################################################################################################
915 static void popup_view_html(struct popup_item *item, char *file)
916 {
917 char command[1024];
918 sprintf(command,"firefox %s", file);
919 system(command);
920 }
921
922 struct transformatin *tg;
923 enum projection pg;
924
925 //##############################################################################################################
926 //# Description:
927 //# Comment:
928 //# Authors: Martin Schaller (04/2008)
929 //##############################################################################################################
930 static void graphics_popup(struct display_list *list, struct popup_item **popup)
931 {
932 struct item *item;
933 struct attr attr;
934 struct map_rect *mr;
935 struct coord c;
936 struct popup_item *curr_item,*last=NULL;
937 item=list->data;
938 mr=map_rect_new(item->map, NULL, NULL, 0);
939 printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
940 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
941 if (item)
942 {
943 if (item_attr_get(item, attr_name, &attr))
944 {
945 curr_item=popup_item_new_text(popup,attr.u.str,1);
946 if (item_attr_get(item, attr_info_html, &attr))
947 {
948 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
949 }
950 if (item_attr_get(item, attr_price_html, &attr))
951 {
952 popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
953 }
954 curr_item->submenu=last;
955 }
956 }
957 map_rect_destroy(mr);
958 }
959 #endif
960
961 /**
962 * FIXME
963 * @param <>
964 * @returns <>
965 * @author Martin Schaller (04/2008)
966 */
967 static void xdisplay_free(struct displaylist *dl)
968 {
969 int i;
970 for (i = 0; i < HASH_SIZE_GRAPHICS_; i++)
971 {
972 struct displayitem *di = dl->hash_entries[i].di;
973 while (di)
974 {
975 struct displayitem *next = di->next;
976 g_free(di);
977 di = next;
978 }
979 dl->hash_entries[i].di = NULL;
980 }
981 }
982
983 /**
984 * FIXME
985 * @param <>
986 * @returns <>
987 * @author Martin Schaller (04/2008)
988 */
989 static void display_add(struct hash_entry *entry, struct item *item, int count, struct coord *c, char **label, int label_count)
990 {
991 struct displayitem *di;
992 int len, i;
993 char *p;
994
995 len = sizeof(*di) + count * sizeof(*c);
996 if (label && label_count)
997 {
998 for (i = 0; i < label_count; i++)
999 {
1000 if (label[i])
1001 {
1002 len += strlen(label[i]) + 1;
1003 }
1004 else
1005 {
1006 len++;
1007 }
1008 }
1009 }
1010 p = g_malloc(len);
1011 // // dbg(0,"malloc len:%d\n", len);
1012
1013 di = (struct displayitem *) p;
1014 p += sizeof(*di) + count * sizeof(*c);
1015 di->item = *item;
1016 if (label && label_count)
1017 {
1018 di->label = p;
1019 for (i = 0; i < label_count; i++)
1020 {
1021 if (label[i])
1022 {
1023 strcpy(p, label[i]);
1024 p += strlen(label[i]) + 1;
1025 }
1026 else
1027 {
1028 *p++ = '\0';
1029 }
1030 }
1031 }
1032 else
1033 {
1034 di->label = NULL;
1035 }
1036 di->count = count;
1037 memcpy(di->c, c, count * sizeof(*c));
1038 di->next = entry->di;
1039 entry->di = di;
1040 }
1041
1042 /**
1043 * FIXME
1044 * @param <>
1045 * @returns <>
1046 * @author Martin Schaller (04/2008)
1047 */
1048 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)
1049 {
1050 int i, x, y, tl, tlm, th, thm, tlsq, l;
1051 float lsq;
1052 // double dx, dy;
1053 float dx, dy;
1054 struct point p_t;
1055 struct point pb[5];
1056
1057 if (gra->meth.get_text_bbox)
1058 {
1059 gra->meth.get_text_bbox(gra->priv, font->priv, label, 0x10000, 0x0, pb, 1);
1060 // tl -> text length
1061 tl = (pb[2].x - pb[0].x);
1062 // th -> text height
1063 th = (pb[0].y - pb[1].y);
1064 }
1065 else
1066 {
1067 // tl -> text length
1068 tl = strlen(label) * 4;
1069 // th -> text height
1070 th = 8;
1071 }
1072 tlm = tl * 32;
1073 thm = th * 36;
1074 // tlsq -> (text length * 32) squared
1075 tlsq = tlm * tlm;
1076 for (i = 0; i < count - 1; i++)
1077 {
1078 dx = p[i + 1].x - p[i].x;
1079 dx *= 32;
1080 dy = p[i + 1].y - p[i].y;
1081 dy *= 32;
1082 // lsq -> (line length * 32) squared
1083 lsq = dx * dx + dy * dy;
1084 if (lsq > tlsq)
1085 {
1086 if (((int) lsq > MIN_LINE_LENGTH_FOR_TEXT_MIDDLE_2) || (((i == 0) || (i == (count - 2)) && ((int) lsq > (int) MIN_LINE_LENGTH_FOR_TEXT_2))))
1087 {
1088 // segments in the middle of the "way" need to be longer for streetname to be drawn
1089 // l -> line length
1090 l = (int) sqrtf_fast2(lsq);
1091 x = p[i].x;
1092 y = p[i].y;
1093 if (dx < 0)
1094 {
1095 dx = -dx;
1096 dy = -dy;
1097 x = p[i + 1].x;
1098 y = p[i + 1].y;
1099 }
1100 x += (l - tlm) * dx / l / 64;
1101 y += (l - tlm) * dy / l / 64;
1102 x -= dy * thm / l / 64;
1103 y += dx * thm / l / 64;
1104 p_t.x = x;
1105 p_t.y = y;
1106 #if 0
1107 //DBG // dbg(0,"display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
1108 #endif
1109 if (x < gra->r.rl.x && x + tl > gra->r.lu.x && y + tl > gra->r.lu.y && y - tl < gra->r.rl.y)
1110 {
1111 gra->meth.draw_text(gra->priv, fg->priv, bg ? bg->priv : NULL, font->priv, label, &p_t, dx * 0x10000 / l, dy * 0x10000 / l);
1112 }
1113 }
1114 }
1115 }
1116 }
1117
1118 static void display_draw_arrow(struct point *p, int dx, int dy, int l, struct graphics_gc *gc, struct graphics *gra)
1119 {
1120 struct point pnt[3];
1121 pnt[0] = pnt[1] = pnt[2] = *p;
1122 pnt[0].x += -dx * l / 65536 + dy * l / 65536;
1123 pnt[0].y += -dy * l / 65536 - dx * l / 65536;
1124 pnt[2].x += -dx * l / 65536 - dy * l / 65536;
1125 pnt[2].y += -dy * l / 65536 + dx * l / 65536;
1126 gra->meth.draw_lines(gra->priv, gc->priv, pnt, 3);
1127 }
1128
1129 static void display_draw_arrows(struct graphics *gra, struct graphics_gc *gc, struct point *pnt, int count)
1130 {
1131 int i, dx, dy, l;
1132 struct point p;
1133 for (i = 0; i < count - 1; i++)
1134 {
1135 dx = pnt[i + 1].x - pnt[i].x;
1136 dy = pnt[i + 1].y - pnt[i].y;
1137 l = sqrt(dx * dx + dy * dy);
1138 if (l)
1139 {
1140 dx = dx * 65536 / l;
1141 dy = dy * 65536 / l;
1142 p = pnt[i];
1143 p.x += dx * 15 / 65536;
1144 p.y += dy * 15 / 65536;
1145 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1146 p = pnt[i + 1];
1147 p.x -= dx * 15 / 65536;
1148 p.y -= dy * 15 / 65536;
1149 display_draw_arrow(&p, dx, dy, 10, gc, gra);
1150 }
1151 }
1152 }
1153
1154 static int intersection(struct point * a1, int adx, int ady, struct point * b1, int bdx, int bdy, struct point * res)
1155 {
1156 int n, a, b;
1157 n = bdy * adx - bdx * ady;
1158 a = bdx * (a1->y - b1->y) - bdy * (a1->x - b1->x);
1159 b = adx * (a1->y - b1->y) - ady * (a1->x - b1->x);
1160 if (n < 0)
1161 {
1162 n = -n;
1163 a = -a;
1164 b = -b;
1165 }
1166 #if 0
1167 if (a < 0 || b < 0)
1168 return 0;
1169 if (a > n || b > n)
1170 return 0;
1171 #endif
1172 if (n == 0)
1173 return 0;
1174 res->x = a1->x + a * adx / n;
1175 res->y = a1->y + a * ady / n;
1176 return 1;
1177 }
1178
1179 struct circle
1180 {
1181 short x, y, fowler;
1182 }
1183 circle64[] =
1184 { { 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 }, };
1185
1186 static void draw_circle(struct point *pnt, int diameter, int scale, int start, int len, struct point *res, int *pos, int dir)
1187 {
1188 struct circle *c;
1189
1190 #if 0
1191 //DBG // dbg(0,"diameter=%d start=%d len=%d pos=%d dir=%d\n", diameter, start, len, *pos, dir);
1192 #endif
1193 int count = 64;
1194 int end = start + len;
1195 int i, step;
1196 c = circle64;
1197 if (diameter > 128)
1198 step = 1;
1199 else if (diameter > 64)
1200 step = 2;
1201 else if (diameter > 24)
1202 step = 4;
1203 else if (diameter > 8)
1204 step = 8;
1205 else
1206 step = 16;
1207 if (len > 0)
1208 {
1209 while (start < 0)
1210 {
1211 start += 1024;
1212 end += 1024;
1213 }
1214 while (end > 0)
1215 {
1216 i = 0;
1217 while (i < count && c[i].fowler <= start)
1218 {
1219 i += step;
1220 }
1221 while (i < count && c[i].fowler < end)
1222 {
1223 if (1 < *pos || 0 < dir)
1224 {
1225 res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1226 res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1227 (*pos) += dir;
1228 }
1229 i += step;
1230 }
1231 end -= 1024;
1232 start -= 1024;
1233 }
1234 }
1235 else
1236 {
1237 while (start > 1024)
1238 {
1239 start -= 1024;
1240 end -= 1024;
1241 }
1242 while (end < 1024)
1243 {
1244 i = count - 1;
1245 while (i >= 0 && c[i].fowler >= start)
1246 i -= step;
1247 while (i >= 0 && c[i].fowler > end)
1248 {
1249 if (1 < *pos || 0 < dir)
1250 {
1251 res[*pos].x = pnt->x + ((c[i].x * diameter + 128) >> 8);
1252 res[*pos].y = pnt->y + ((c[i].y * diameter + 128) >> 8);
1253 (*pos) += dir;
1254 }
1255 i -= step;
1256 }
1257 start += 1024;
1258 end += 1024;
1259 }
1260 }
1261 }
1262
1263 static int fowler(int dy, int dx)
1264 {
1265 int adx, ady; /* Absolute Values of Dx and Dy */
1266 int code; /* Angular Region Classification Code */
1267
1268 adx = (dx < 0) ? -dx : dx; /* Compute the absolute values. */
1269 ady = (dy < 0) ? -dy : dy;
1270
1271 code = (adx < ady) ? 1 : 0;
1272 if (dx < 0)
1273 code += 2;
1274 if (dy < 0)
1275 code += 4;
1276
1277 switch (code)
1278 {
1279 case 0:
1280 return (dx == 0) ? 0 : 128 * ady / adx; /* [ 0, 45] */
1281 case 1:
1282 return (256 - (128 * adx / ady)); /* ( 45, 90] */
1283 case 3:
1284 return (256 + (128 * adx / ady)); /* ( 90,135) */
1285 case 2:
1286 return (512 - (128 * ady / adx)); /* [135,180] */
1287 case 6:
1288 return (512 + (128 * ady / adx)); /* (180,225] */
1289 case 7:
1290 return (768 - (128 * adx / ady)); /* (225,270) */
1291 case 5:
1292 return (768 + (128 * adx / ady)); /* [270,315) */
1293 case 4:
1294 return (1024 - (128 * ady / adx));/* [315,360) */
1295 }
1296 return 0;
1297 }
1298
1299 static int int_sqrt(unsigned int n)
1300 {
1301 unsigned int h, p = 0, q = 1, r = n;
1302
1303 /* avoid q rollover */
1304 if (n >= (1 << (sizeof(n) * 8 - 2)))
1305 {
1306 q = 1 << (sizeof(n) * 8 - 2);
1307 }
1308 else
1309 {
1310 while (q <= n)
1311 {
1312 q <<= 2;
1313 }
1314 q >>= 2;
1315 }
1316
1317 while (q != 0)
1318 {
1319 h = p + q;
1320 p >>= 1;
1321 if (r >= h)
1322 {
1323 p += q;
1324 r -= h;
1325 }
1326 q >>= 2;
1327 }
1328 return p;
1329 }
1330
1331 struct offset
1332 {
1333 int px, py, nx, ny;
1334 };
1335
1336 static void calc_offsets(int wi, int l, int dx, int dy, struct offset *res)
1337 {
1338 int x, y;
1339
1340 x = (dx * wi) / l;
1341 y = (dy * wi) / l;
1342 if (x < 0)
1343 {
1344 res->nx = -x / 2;
1345 res->px = (x - 1) / 2;
1346 }
1347 else
1348 {
1349 res->nx = -(x + 1) / 2;
1350 res->px = x / 2;
1351 }
1352 if (y < 0)
1353 {
1354 res->ny = -y / 2;
1355 res->py = (y - 1) / 2;
1356 }
1357 else
1358 {
1359 res->ny = -(y + 1) / 2;
1360 res->py = y / 2;
1361 }
1362 }
1363
1364 // this func. is now obsolete!! and unused!!!!
1365 // this func. is now obsolete!! and unused!!!!
1366 // this func. is now obsolete!! and unused!!!!
1367 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)
1368 {
1369 int maxpoints = 200;
1370 struct point *res = g_alloca(sizeof(struct point) * maxpoints);
1371 struct point pos, poso, neg, nego;
1372 int i, dx = 0, dy = 0, l = 0, dxo = 0, dyo = 0;
1373 struct offset o, oo = { 0, 0, 0, 0 };
1374 int fow = 0, fowo = 0, delta;
1375 int wi, ppos = maxpoints / 2, npos = maxpoints / 2;
1376 int state, prec = 5;
1377 int max_circle_points = 20;
1378 int lscale = 16;
1379 i = 0;
1380 for (;;)
1381 {
1382 wi = *width;
1383 width += step;
1384 if (i < count - 1)
1385 {
1386 int dxs, dys, lscales;
1387
1388 dx = (pnt[i + 1].x - pnt[i].x);
1389 dy = (pnt[i + 1].y - pnt[i].y);
1390 #if 0
1391 l = int_sqrt(dx * dx * lscale * lscale + dy * dy * lscale * lscale);
1392 #else
1393 dxs = dx * dx;
1394 dys = dy * dy;
1395 lscales = lscale * lscale;
1396 if (dxs + dys > lscales)
1397 l = int_sqrt(dxs + dys) * lscale;
1398 else
1399 l = int_sqrt((dxs + dys) * lscales);
1400 #endif
1401 fow = fowler(-dy, dx);
1402 }
1403 if (!l)
1404 l = 1;
1405 if (wi * lscale > 10000)
1406 lscale = 10000 / wi;
1407 dbg_assert(wi * lscale <= 10000);
1408 calc_offsets(wi * lscale, l, dx, dy, &o);
1409 pos.x = pnt[i].x + o.ny;
1410 pos.y = pnt[i].y + o.px;
1411 neg.x = pnt[i].x + o.py;
1412 neg.y = pnt[i].y + o.nx;
1413 if (!i)
1414 state = 0;
1415 else if (i == count - 1)
1416 state = 2;
1417 else if (npos < max_circle_points || ppos >= maxpoints - max_circle_points)
1418 state = 3;
1419 else
1420 state = 1;
1421 switch (state)
1422 {
1423 case 1:
1424 if (fowo != fow)
1425 {
1426 poso.x = pnt[i].x + oo.ny;
1427 poso.y = pnt[i].y + oo.px;
1428 nego.x = pnt[i].x + oo.py;
1429 nego.y = pnt[i].y + oo.nx;
1430 delta = fowo - fow;
1431 if (delta < 0)
1432 delta += 1024;
1433 if (delta < 512)
1434 {
1435 if (intersection(&pos, dx, dy, &poso, dxo, dyo, &res[ppos]))
1436 {
1437 ppos++;
1438 }
1439 res[--npos] = nego;
1440 --npos;
1441 if (fill == 1)
1442 {
1443 if (draw_polylines_fast == 0)
1444 {
1445 draw_circle(&pnt[i], wi, prec, fowo - 512, -delta, res, &npos, -1);
1446 }
1447 }
1448 res[npos] = neg;
1449 }
1450 else
1451 {
1452 res[ppos++] = poso;
1453 if (fill == 1)
1454 {
1455 if (draw_polylines_fast == 0)
1456 {
1457 draw_circle(&pnt[i], wi, prec, fowo, 1024 - delta, res, &ppos, 1);
1458 }
1459 }
1460 res[ppos++] = pos;
1461 if (intersection(&neg, dx, dy, &nego, dxo, dyo, &res[npos - 1]))
1462 {
1463 npos--;
1464 }
1465 }
1466 }
1467 break;
1468 case 2:
1469 case 3:
1470 res[--npos] = neg;
1471 --npos;
1472 if (fill == 1)
1473 {
1474 if (draw_polylines_fast == 0)
1475 {
1476 draw_circle(&pnt[i], wi, prec, fow - 512, -512, res, &npos, -1);
1477 }
1478 }
1479 res[npos] = pos;
1480 res[ppos++] = pos;
1481 dbg_assert(npos > 0);
1482 dbg_assert(ppos < maxpoints);
1483 if (fill == 1)
1484 {
1485 gra->meth.draw_polygon2(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1486 }
1487 else
1488 {
1489 gra->meth.draw_lines_dashed(gra->priv, gc->priv, res + npos, ppos - npos, order, oneway);
1490 }
1491 if (state == 2)
1492 break;
1493 npos = maxpoints / 2;
1494 ppos = maxpoints / 2;
1495 case 0:
1496 res[ppos++] = neg;
1497 if (fill == 1)
1498 {
1499 if (draw_polylines_fast == 0)
1500 {
1501 draw_circle(&pnt[i], wi, prec, fow + 512, 512, res, &ppos, 1);
1502 }
1503 }
1504 res[ppos++] = pos;
1505 break;
1506 }
1507
1508 i++;
1509
1510 if (i >= count)
1511 {
1512 break;
1513 }
1514
1515 if (step)
1516 {
1517 wi = *width;
1518 calc_offsets(wi * lscale, l, dx, dy, &oo);
1519 }
1520 else
1521 {
1522 oo = o;
1523 }
1524
1525 dxo = -dx;
1526 dyo = -dy;
1527 fowo = fow;
1528 }
1529 }
1530 // this func. is now obsolete!! and unused!!!!
1531 // this func. is now obsolete!! and unused!!!!
1532 // this func. is now obsolete!! and unused!!!!
1533
1534
1535 struct wpoint
1536 {
1537 int x, y, w;
1538 };
1539
1540 static int clipcode(struct wpoint *p, struct point_rect *r)
1541 {
1542 int code = 0;
1543 if (p->x < r->lu.x)
1544 code = 1;
1545 if (p->x > r->rl.x)
1546 code = 2;
1547 if (p->y < r->lu.y)
1548 code |= 4;
1549 if (p->y > r->rl.y)
1550 code |= 8;
1551 return code;
1552 }
1553
1554 #define DONT_INTERSECT 0
1555 #define DO_INTERSECT 1
1556 #define COLLINEAR 2
1557 #define SAME_SIGNS( a, b ) \
1558 (((long) ((unsigned long) a ^ (unsigned long) b)) >= 0 )
1559
1560 static int lines_intersect(int x1, int y1, /* First line segment */
1561 int x2, int y2,
1562
1563 int x3, int y3, /* Second line segment */
1564 int x4, int y4,
1565
1566 int *x, int *y /* Output value:
1567 * point of intersection */
1568 )
1569 {
1570 int a1, a2, b1, b2, c1, c2; /* Coefficients of line eqns. */
1571 int r1, r2, r3, r4; /* 'Sign' values */
1572 int denom, offset, num; /* Intermediate values */
1573
1574 /* Compute a1, b1, c1, where line joining points 1 and 2
1575 * is "a1 x + b1 y + c1 = 0".
1576 */
1577
1578 a1 = y2 - y1;
1579 b1 = x1 - x2;
1580 c1 = x2 * y1 - x1 * y2;
1581
1582 /* Compute r3 and r4.
1583 */
1584 r3 = a1 * x3 + b1 * y3 + c1;
1585 r4 = a1 * x4 + b1 * y4 + c1;
1586
1587 /* Check signs of r3 and r4. If both point 3 and point 4 lie on
1588 * same side of line 1, the line segments do not intersect.
1589 */
1590 if (r3 != 0 && r4 != 0 && SAME_SIGNS( r3, r4 ))
1591 {
1592 return (DONT_INTERSECT);
1593 }
1594
1595 /* Compute a2, b2, c2 */
1596 a2 = y4 - y3;
1597 b2 = x3 - x4;
1598 c2 = x4 * y3 - x3 * y4;
1599
1600 /* Compute r1 and r2 */
1601 r1 = a2 * x1 + b2 * y1 + c2;
1602 r2 = a2 * x2 + b2 * y2 + c2;
1603
1604 /* Check signs of r1 and r2. If both point 1 and point 2 lie
1605 * on same side of second line segment, the line segments do
1606 * not intersect.
1607 */
1608 if (r1 != 0 && r2 != 0 && SAME_SIGNS( r1, r2 ))
1609 {
1610 return (DONT_INTERSECT);
1611 }
1612
1613 /* Line segments intersect: compute intersection point.
1614 */
1615
1616 denom = a1 * b2 - a2 * b1;
1617 if (denom == 0)
1618 {
1619 return (COLLINEAR);
1620 }
1621 offset = denom < 0 ? -denom / 2 : denom / 2;
1622
1623 /* The denom/2 is to get rounding instead of truncating. It
1624 * is added or subtracted to the numerator, depending upon the
1625 * sign of the numerator.
1626 */
1627 /*
1628 num = b1 * c2 - b2 * c1;
1629 *x = ( num < 0 ? num - offset : num + offset ) / denom;
1630 num = a2 * c1 - a1 * c2;
1631 *y = ( num < 0 ? num - offset : num + offset ) / denom;
1632 */
1633
1634 return (DO_INTERSECT);
1635 } /* lines_intersect */
1636
1637 static int clip_line_aprox(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1638 {
1639 int code1, code2;
1640 code1 = clipcode(p1, r);
1641 code2 = clipcode(p2, r);
1642 if (code1 & code2)
1643 {
1644 // line completely invisible!
1645 return 0;
1646 }
1647 else if ((code1 == 0) && (code2 == 0))
1648 {
1649 // line completely visible!
1650 return 1;
1651 }
1652 else if ((code1 == 0) || (code2 == 0))
1653 {
1654 // at least 1 point of line is visible
1655 return 2;
1656 }
1657 else
1658 {
1659 int xx;
1660 int yy;
1661 // top
1662 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);
1663 if (ret_ == DO_INTERSECT)
1664 {
1665 return 3;
1666 }
1667 // bottom
1668 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);
1669 if (ret_ == DO_INTERSECT)
1670 {
1671 return 3;
1672 }
1673 // left
1674 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);
1675 if (ret_ == DO_INTERSECT)
1676 {
1677 return 3;
1678 }
1679 // right
1680 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);
1681 if (ret_ == DO_INTERSECT)
1682 {
1683 return 3;
1684 }
1685 }
1686 // not visible
1687 return 0;
1688 }
1689
1690 static int clip_line(struct wpoint *p1, struct wpoint *p2, struct point_rect *r)
1691 {
1692 int code1, code2, ret = 1;
1693 int dx, dy, dw;
1694 code1 = clipcode(p1, r);
1695 if (code1)
1696 ret |= 2;
1697 code2 = clipcode(p2, r);
1698 if (code2)
1699 ret |= 4;
1700 dx = p2->x - p1->x;
1701 dy = p2->y - p1->y;
1702 dw = p2->w - p1->w;
1703 while (code1 || code2)
1704 {
1705 if (code1 & code2)
1706 {
1707 return 0;
1708 }
1709 if (code1 & 1)
1710 {
1711 p1->y += (r->lu.x - p1->x) * dy / dx;
1712 p1->w += (r->lu.x - p1->x) * dw / dx;
1713 p1->x = r->lu.x;
1714 }
1715 else if (code1 & 2)
1716 {
1717 p1->y += (r->rl.x - p1->x) * dy / dx;
1718 p1->w += (r->rl.x - p1->x) * dw / dx;
1719 p1->x = r->rl.x;
1720 }
1721 else if (code1 & 4)
1722 {
1723 p1->x += (r->lu.y - p1->y) * dx / dy;
1724 p1->w += (r->lu.y - p1->y) * dw / dy;
1725 p1->y = r->lu.y;
1726 }
1727 else if (code1 & 8)
1728 {
1729 p1->x += (r->rl.y - p1->y) * dx / dy;
1730 p1->w += (r->rl.y - p1->y) * dw / dy;
1731 p1->y = r->rl.y;
1732 }
1733 code1 = clipcode(p1, r);
1734 if (code1 & code2)
1735 return 0;
1736 if (code2 & 1)
1737 {
1738 p2->y += (r->lu.x - p2->x) * dy / dx;
1739 p2->w += (r->lu.x - p2->x) * dw / dx;
1740 p2->x = r->lu.x;
1741 }
1742 else if (code2 & 2)
1743 {
1744 p2->y += (r->rl.x - p2->x) * dy / dx;
1745 p2->w += (r->rl.x - p2->x) * dw / dx;
1746 p2->x = r->rl.x;
1747 }
1748 else if (code2 & 4)
1749 {
1750 p2->x += (r->lu.y - p2->y) * dx / dy;
1751 p2->w += (r->lu.y - p2->y) * dw / dy;
1752 p2->y = r->lu.y;
1753 }
1754 else if (code2 & 8)
1755 {
1756 p2->x += (r->rl.y - p2->y) * dx / dy;
1757 p2->w += (r->rl.y - p2->y) * dw / dy;
1758 p2->y = r->rl.y;
1759 }
1760 code2 = clipcode(p2, r);
1761 }
1762 return ret;
1763 }
1764
1765 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)
1766 {
1767 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
1768 dbg(0,"+#+:enter\n");
1769 #endif
1770
1771 struct point *p = g_alloca(sizeof(struct point) * (count + 1));
1772 struct wpoint p1, p2;
1773 int i;
1774 int code;
1775 int wmax;
1776 int out = 0;
1777 // const int max_segs = 2000;
1778 const int max_segs = 60; // send max this many segments to java with one single call
1779 struct point_rect r = gra->r;
1780
1781 //if (count > 30)
1782 //{
1783 // dbg(0,"segment count=%d\n", count);
1784 //}
1785
1786 #if 0
1787 // check if whole line is within a 2x2 pixel square
1788 if (order < 11)
1789 {
1790 const int max_dist = 2*2;
1791 int need_draw = 0;
1792 int diff;
1793 for (i = 0; i < count; i++)
1794 {
1795 if (i > 0)
1796 {
1797 p2.x = pa[i].x;
1798 p2.y = pa[i].y;
1799 diff = (p2.x - p1.x) * (p2.y - p1.y);
1800 if (diff < 0)
1801 {
1802 diff = -diff;
1803 }
1804
1805 if (diff > max_dist)
1806 {
1807 // line is bigger, so we need to draw it
1808 need_draw = 1;
1809 break;
1810 }
1811 }
1812 else
1813 {
1814 p1.x = pa[i - 1].x;
1815 p1.y = pa[i - 1].y;
1816 }
1817 }
1818
1819 if (need_draw == 0)
1820 {
1821 // dont draw this line
1822 return;
1823 }
1824 }
1825 #endif
1826
1827 // calc visible area on screen
1828 wmax = width[0];
1829 r.lu.x -= wmax;
1830 r.lu.y -= wmax;
1831 r.rl.x += wmax;
1832 r.rl.y += wmax;
1833
1834 for (i = 0; i < count; i++)
1835 {
1836 if (i > 0)
1837 {
1838 p1.x = pa[i - 1].x;
1839 p1.y = pa[i - 1].y;
1840 p2.x = pa[i].x;
1841 p2.y = pa[i].y;
1842 /* 0 = invisible, 1 = completely visible, 2,3 = at least part of line visible */
1843 code = clip_line_aprox(&p1, &p2, &r);
1844 // code = 1;
1845
1846 if (code > 0)
1847 {
1848 if (out == 0)
1849 {
1850 p[out].x = p1.x;
1851 p[out].y = p1.y;
1852 out++;
1853 }
1854 p[out].x = p2.x;
1855 p[out].y = p2.y;
1856 out++;
1857
1858 if ((out <= max_segs) && (i < (count - 1)))
1859 {
1860 // ok gather more line segs
1861 continue;
1862 }
1863 }
1864 else // (code == 0)
1865 {
1866 if (out == 0)
1867 {
1868 // first visible line seg not yet found, search on ...
1869 continue;
1870 }
1871 }
1872
1873 // PAINT --- LINE SEGMENTS ------------
1874 // PAINT --- LINE SEGMENTS ------------
1875
1876 if ((poly == 1) || (poly == 0))
1877 {
1878 // normal street
1879 //if (1 == 0)
1880 //{
1881 // // draw as polygon --> OLD method
1882 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 1, order, 0);
1883 //}
1884 //else
1885 //{
1886 // draw as line
1887 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c);
1888 //draw_lines_count_3++;
1889 //}
1890
1891 // one way arrow
1892 if ((oneway > 0) && (order > 13))
1893 {
1894 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1895 //draw_lines_count_2++;
1896 }
1897 }
1898 else if (poly == 2)
1899 {
1900 // ******* street is underground ********
1901 // ******* street is underground ********
1902 // ******* street is underground ********
1903
1904 //if (1 == 0)
1905 //{
1906 // // draw as polygon --> OLD method
1907 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 0, order, 0);
1908 //}
1909 //else
1910 //{
1911
1912 // draw as line
1913 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 1, dashes, c);
1914 //draw_lines_count_4++;
1915 //}
1916
1917 // one way arrow
1918 if ((oneway > 0) && (order > 13))
1919 {
1920 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1921 //draw_lines_count_2++;
1922 }
1923 }
1924 else if (poly == 3)
1925 {
1926 // ******* street has bridge ********
1927 // ******* street has bridge ********
1928 // ******* street has bridge ********
1929 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 2, dashes, c);
1930 //draw_lines_count_4++;
1931
1932 // one way arrow
1933 if ((oneway > 0) && (order > 13))
1934 {
1935 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1936 //draw_lines_count_2++;
1937 }
1938 }
1939 // --> now NOT used anymore!!
1940 else // poly==0 -> street that is only a line (width=1)
1941 {
1942 // OLD // gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, 0);
1943
1944 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i], dashes, c);
1945 //draw_lines_count_3++;
1946
1947 // one way arrow
1948 if ((oneway > 0) && (order > 13))
1949 {
1950 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1951 //draw_lines_count_2++;
1952 }
1953 }
1954
1955 out = 0; // reset point counter after painting
1956 // PAINT --- LINE SEGMENTS ------------
1957 // PAINT --- LINE SEGMENTS ------------
1958 // PAINT --- LINE SEGMENTS ------------
1959 }
1960 }
1961 }
1962
1963 static int is_inside(struct point *p, struct point_rect *r, int edge)
1964 {
1965 switch (edge)
1966 {
1967 case 0:
1968 return p->x >= r->lu.x;
1969 case 1:
1970 return p->x <= r->rl.x;
1971 case 2:
1972 return p->y >= r->lu.y;
1973 case 3:
1974 return p->y <= r->rl.y;
1975 default:
1976 return 0;
1977 }
1978 }
1979
1980 static void poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
1981 {
1982 int dx = p2->x - p1->x;
1983 int dy = p2->y - p1->y;
1984 switch (edge)
1985 {
1986 case 0:
1987 ret->y = p1->y + (r->lu.x - p1->x) * dy / dx;
1988 ret->x = r->lu.x;
1989 break;
1990 case 1:
1991 ret->y = p1->y + (r->rl.x - p1->x) * dy / dx;
1992 ret->x = r->rl.x;
1993 break;
1994 case 2:
1995 ret->x = p1->x + (r->lu.y - p1->y) * dx / dy;
1996 ret->y = r->lu.y;
1997 break;
1998 case 3:
1999 ret->x = p1->x + (r->rl.y - p1->y) * dx / dy;
2000 ret->y = r->rl.y;
2001 break;
2002 }
2003 }
2004
2005 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
2006 {
2007 struct point_rect r = gra->r;
2008 struct point *pout, *p, *s, pi, *p1, *p2;
2009 int limit = 10000;
2010 struct point *pa1 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2011 struct point *pa2 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2012 int count_out, edge = 3;
2013 int i;
2014 #if 0
2015 r.lu.x+=20;
2016 r.lu.y+=20;
2017 r.rl.x-=20;
2018 r.rl.y-=20;
2019 #endif
2020 if (count_in < limit)
2021 {
2022 p1 = pa1;
2023 p2 = pa2;
2024 }
2025 else
2026 {
2027 p1 =g_new(struct point, count_in*8+1);
2028 p2=g_new(struct point, count_in*8+1);
2029 }
2030
2031 pout=p1;
2032 for (edge = 0; edge < 4; edge++)
2033 {
2034 p=pin;
2035 s=pin+count_in-1;
2036 count_out=0;
2037 for (i = 0; i < count_in; i++)
2038 {
2039 if (is_inside(p, &r, edge))
2040 {
2041 if (! is_inside(s, &r, edge))
2042 {
2043 poly_intersection(s,p,&r,edge,&pi);
2044 pout[count_out++]=pi;
2045 }
2046 pout[count_out++]=*p;
2047 }
2048 else
2049 {
2050 if (is_inside(s, &r, edge))
2051 {
2052 poly_intersection(p,s,&r,edge,&pi);
2053 pout[count_out++]=pi;
2054 }
2055 }
2056 s=p;
2057 p++;
2058 }
2059 count_in=count_out;
2060 if (pin == p1)
2061 {
2062 pin=p2;
2063 pout=p1;
2064 }
2065 else
2066 {
2067 pin=p1;
2068 pout=p2;
2069 }
2070 }
2071
2072 gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
2073 if (count_in >= limit)
2074 {
2075 g_free(p1);
2076 g_free(p2);
2077 }
2078 }
2079
2080 static void display_context_free(struct display_context *dc)
2081 {
2082 if (dc->gc)
2083 graphics_gc_destroy(dc->gc);
2084 if (dc->gc_background)
2085 graphics_gc_destroy(dc->gc_background);
2086 if (dc->img)
2087 graphics_image_free(dc->gra, dc->img);
2088 dc->gc = NULL;
2089 dc->gc_background = NULL;
2090 dc->img = NULL;
2091 }
2092
2093 static struct graphics_font *
2094 get_font(struct graphics *gra, int size)
2095 {
2096 if (size > 64)
2097 {
2098 size = 64;
2099 }
2100 if (size >= gra->font_len)
2101 {
2102 gra->font=g_renew(struct graphics_font *, gra->font, size+1);
2103 while (gra->font_len <= size)
2104 {
2105 gra->font[gra->font_len++] = NULL;
2106 }
2107 }
2108 if (!gra->font[size])
2109 {
2110 gra->font[size] = graphics_font_new(gra, size * gra->font_size, 0);
2111 }
2112 return gra->font[size];
2113 }
2114
2115 void graphics_draw_text_std(struct graphics *this_, int text_size, char *text, struct point *p)
2116 {
2117 struct graphics_font *font = get_font(this_, text_size);
2118 struct point bbox[4];
2119 int i;
2120
2121 graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
2122 for (i = 0; i < 4; i++)
2123 {
2124 bbox[i].x += p->x;
2125 bbox[i].y += p->y;
2126 }
2127 graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x - bbox[0].x, bbox[0].y - bbox[1].y + 5);
2128 graphics_draw_text(this_, this_->gc[1], this_->gc[2], font, text, p, 0x10000, 0);
2129 }
2130
2131 char *
2132 graphics_icon_path(char *icon)
2133 {
2134 static char *navit_sharedir;
2135 char *ret = NULL;
2136 struct file_wordexp *wordexp = NULL;
2137 // dbg(1, "enter %s\n", icon);
2138 if (strchr(icon, '$'))
2139 {
2140 wordexp = file_wordexp_new(icon);
2141 if (file_wordexp_get_count(wordexp))
2142 {
2143 icon = file_wordexp_get_array(wordexp)[0];
2144 }
2145 }
2146
2147 if (strchr(icon, '/'))
2148 {
2149 ret = g_strdup(icon);
2150 }
2151 else
2152 {
2153 #ifdef HAVE_API_ANDROID
2154 // get resources for the correct screen density
2155 //
2156 // this part not needed, android unpacks only the correct version into res/drawable dir!
2157 // // dbg(1,"android icon_path %s\n",icon);
2158 // static char *android_density;
2159 // android_density = getenv("ANDROID_DENSITY");
2160 // ret=g_strdup_printf("res/drawable-%s/%s",android_density ,icon);
2161 ret=g_strdup_printf("res/drawable/%s" ,icon);
2162 #else
2163 if (!navit_sharedir)
2164 {
2165 navit_sharedir = getenv("NAVIT_SHAREDIR");
2166 }
2167 ret = g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
2168 #endif
2169 }
2170
2171 if (wordexp)
2172 {
2173 file_wordexp_destroy(wordexp);
2174 }
2175
2176 return ret;
2177 }
2178
2179 static int limit_count(struct coord *c, int count)
2180 {
2181 int i;
2182 for (i = 1; i < count; i++)
2183 {
2184 if (c[i].x == c[0].x && c[i].y == c[0].y)
2185 return i + 1;
2186 }
2187 return count;
2188 }
2189
2190 static void displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc, int order, int allow_dashed, int run_type)
2191 {
2192 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
2193 dbg(0,"+#+:enter\n");
2194 #endif
2195
2196 //// dbg(0, "EEnter\n");
2197
2198 int *width = g_alloca(sizeof(int) * dc->maxlen);
2199 struct point *pa = g_alloca(sizeof(struct point) * dc->maxlen);
2200 struct graphics *gra = dc->gra;
2201 struct graphics_gc *gc = dc->gc;
2202 struct element *e = dc->e;
2203 struct graphics_image *img = dc->img;
2204 struct point p;
2205 char *path;
2206
2207 //if (run_type > 100) // dbg(0,"enter\n");
2208
2209 while (di)
2210 {
2211
2212 // stop drawing is requested
2213 if (cancel_drawing_global == 1)
2214 {
2215 break;
2216 }
2217
2218 if (run_type != 99)
2219 {
2220 if (run_type == 1)
2221 {
2222 if (di->item.flags & AF_UNDERGROUND)
2223 {
2224 // next item
2225 di = di->next;
2226 continue;
2227 }
2228 else if (di->item.flags & AF_BRIDGE)
2229 {
2230 // next item
2231 di = di->next;
2232 continue;
2233 }
2234 }
2235 else if (run_type == 2)
2236 {
2237 // tunnel
2238 if (di->item.flags & AF_UNDERGROUND)
2239 {
2240 }
2241 else
2242 {
2243 // next item
2244 di = di->next;
2245 continue;
2246 }
2247 }
2248 else if (run_type == 3)
2249 {
2250 // bridge
2251 if (di->item.flags & AF_BRIDGE)
2252 {
2253 }
2254 else
2255 {
2256 // next item
2257 di = di->next;
2258 continue;
2259 }
2260 }
2261 }
2262
2263 int i, count = di->count, mindist = dc->mindist;
2264
2265 if (!gc)
2266 {
2267 gc = graphics_gc_new(gra);
2268 graphics_gc_set_foreground(gc, &e->color);
2269 dc->gc = gc;
2270 }
2271
2272 if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
2273 {
2274 count = limit_count(di->c, count);
2275 }
2276
2277 if (dc->type == type_poly_water_tiled)
2278 {
2279 mindist = 0;
2280 if (order < 10)
2281 {
2282 mindist = 3;
2283 }
2284 }
2285 else if (dc->type == type_border_country)
2286 {
2287 if (order < 10)
2288 {
2289 mindist = 3;
2290 }
2291 }
2292 else if (dc->type == type_poly_wood_from_triang)
2293 {
2294 if (order > 4)
2295 {
2296 // always show triangulates triangles normally
2297 mindist = 0;
2298 }
2299 }
2300 else if (dc->type == type_poly_water_from_triang)
2301 {
2302 if (order > 4)
2303 {
2304 // always show triangulates triangles normally
2305 mindist = 0;
2306 }
2307 }
2308
2309 if (dc->e->type == element_polyline)
2310 {
2311 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
2312 }
2313 else
2314 {
2315 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
2316 }
2317
2318 switch (e->type)
2319 {
2320 case element_polygon:
2321 graphics_draw_polygon_clipped(gra, gc, pa, count);
2322 break;
2323 case element_polyline:
2324 {
2325 gc->meth.gc_set_linewidth(gc->priv, 1);
2326
2327 int poly = e->u.polyline.width > 1;
2328
2329 // detect underground streets/lines/etc ...
2330 //if ((allow_dashed) && (di->item.flags & AF_UNDERGROUND))
2331 if (di->item.flags & AF_UNDERGROUND)
2332 {
2333 poly = 2;
2334 }
2335 else if (di->item.flags & AF_BRIDGE)
2336 {
2337 poly = 3;
2338 }
2339
2340 int oneway = 0;
2341
2342 if (di->item.flags & AF_ONEWAYREV)
2343 {
2344 oneway = 2;
2345 }
2346 else if (di->item.flags & AF_ONEWAY)
2347 {
2348 oneway = 1;
2349 }
2350
2351 // -------- apply dashes -------
2352 //if (e->u.polyline.dash_num > 0)
2353 //{
2354 // 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);
2355 //}
2356 // -------- apply dashes -------
2357
2358 //for (i = 0; i < count; i++)
2359 //{
2360 // if (width[i] < 1)
2361 // {
2362 // width[i] = 1;
2363 // }
2364 //}
2365
2366 if (dc->type == type_border_country)
2367 {
2368 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway, e->u.polyline.dash_num, &e->color);
2369 }
2370 else
2371 {
2372 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway, e->u.polyline.dash_num, &e->color);
2373 // graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway);
2374 }
2375
2376 // -------- cancel dashes -------
2377 //if (e->u.polyline.dash_num > 0)
2378 //{
2379 // int dummy_1[1];
2380 // dummy_1[0] = 0;
2381 // graphics_gc_set_dashes(gra, gc, e->u.polyline.width, e->u.polyline.offset, dummy_1, e->u.polyline.dash_num, order);
2382 //}
2383 //if (run_type > 100) // dbg(0,"gg005\n");
2384 // -------- cancel dashes -------
2385 }
2386 break;
2387 case element_circle:
2388 if (count)
2389 {
2390 if (e->u.circle.width > 1)
2391 {
2392 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
2393 }
2394
2395 //// dbg(0, "graphics_draw_circle\n");
2396 graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
2397
2398 if (di->label && e->text_size)
2399 {
2400 struct graphics_font *font = get_font(gra, e->text_size);
2401 struct graphics_gc *gc_background = dc->gc_background;
2402 if (!gc_background && e->u.circle.background_color.a)
2403 {
2404 gc_background = graphics_gc_new(gra);
2405 graphics_gc_set_foreground(gc_background, &e->u.circle.background_color);
2406 dc->gc_background = gc_background;
2407 }
2408 p.x = pa[0].x + 3;
2409 p.y = pa[0].y + 10;
2410
2411 if (font)
2412 {
2413 gra->meth.draw_text(gra->priv, gc->priv, gc_background ? gc_background->priv : NULL, font->priv, di->label, &p, 0x10000, 0);
2414 }
2415 else
2416 {
2417 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2418 }
2419 }
2420 }
2421 break;
2422 case element_text:
2423 if (count && di->label)
2424 {
2425 //if (run_type > 100) // dbg(0,"gg006\n");
2426
2427 struct graphics_font *font = get_font(gra, e->text_size);
2428 struct graphics_gc *gc_background = dc->gc_background;
2429
2430 if (!gc_background && e->u.text.background_color.a)
2431 {
2432 gc_background = graphics_gc_new(gra);
2433 graphics_gc_set_foreground(gc_background, &e->u.text.background_color);
2434 dc->gc_background = gc_background;
2435 }
2436
2437 if (font)
2438 {
2439 label_line(gra, gc, gc_background, font, pa, count, di->label);
2440 }
2441 else
2442 {
2443 //DBG // dbg(0, "Failed to get font with size %d\n", e->text_size);
2444 }
2445 }
2446 break;
2447 case element_icon:
2448 if (count)
2449 {
2450 if (!img || item_is_custom_poi(di->item))
2451 {
2452 if (item_is_custom_poi(di->item))
2453 {
2454 char *icon;
2455 char *src;
2456 if (img)
2457 {
2458 graphics_image_free(dc->gra, img);
2459 }
2460 src = e->u.icon.src;
2461 if (!src || !src[0])
2462 {
2463 src = "%s";
2464 }
2465 icon = g_strdup_printf(src, di->label + strlen(di->label) + 1);
2466 path = graphics_icon_path(icon);
2467 g_free(icon);
2468 }
2469 else
2470 {
2471 path = graphics_icon_path(e->u.icon.src);
2472 }
2473 img = graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
2474 if (img)
2475 {
2476 dc->img = img;
2477 }
2478 else
2479 {
2480 // missing icon // // dbg(0, "-- ICON MISSING -- failed to load icon '%s'\n", path);
2481 }
2482 g_free(path);
2483 }
2484
2485 if (img)
2486 {
2487 p.x = pa[0].x - img->hot.x;
2488 p.y = pa[0].y - img->hot.y;
2489 //// dbg(0, "icon: '%s'\n", path);
2490 //// dbg(0,"hot: %d %d\n", img->hot.x, img->hot.y);
2491 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
2492 }
2493 }
2494 break;
2495 case element_image:
2496 //// dbg(0, "image: '%s'\n", di->label);
2497 if (gra->meth.draw_image_warp)
2498 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2499 else
2500 {
2501 // // dbg(0,"draw_image_warp not supported by graphics driver drawing '%s'\n",di->label);
2502 }
2503 break;
2504 case element_arrows:
2505 display_draw_arrows(gra, gc, pa, count);
2506 break;
2507 //default:
2508 // printf("Unhandled element type %d\n", e->type);
2509 }
2510 di = di->next;
2511 }
2512
2513 //if (run_type > 100) // dbg(0,"gg099\n");
2514
2515 }
2516 /**
2517 * FIXME
2518 * @param <>
2519 * @returns <>
2520 * @author Martin Schaller (04/2008)
2521 */
2522 static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, int run_type)
2523 {
2524 // // dbg(0,"Enter\n");
2525
2526 struct element *e;
2527 GList *es, *types;
2528 struct display_context *dc = &display_list->dc;
2529 struct hash_entry *entry;
2530 int draw_it = 1;
2531
2532 #ifdef NAVIT_MEASURE_TIME_DEBUG
2533 clock_t s_ = debug_measure_start();
2534 #endif
2535
2536 es = itm->elements;
2537 while (es)
2538 {
2539 //// dbg(0,"*es\n");
2540 e = es->data;
2541 dc->e = e;
2542 types = itm->type;
2543 while (types)
2544 {
2545 draw_it = 1;
2546
2547 // stop drawing is requested
2548 if (cancel_drawing_global == 1)
2549 {
2550 break;
2551 }
2552
2553 dc->type = GPOINTER_TO_INT(types->data);
2554 //// dbg(0,"**type=%d\n", dc->type);
2555
2556 if (global_draw_multipolygons == 0)
2557 {
2558 if (dc->type == type_poly_water_from_relations)
2559 {
2560 // ok "poly_water_from_relations" is found, now what?
2561 draw_it = 0;
2562 }
2563 else if (dc->type == type_poly_water_from_triang)
2564 {
2565 draw_it = 0;
2566 }
2567 else if (dc->type == type_wood_from_relations)
2568 {
2569 draw_it = 0;
2570 }
2571 else if (dc->type == type_poly_wood_from_triang)
2572 {
2573 draw_it = 0;
2574 }
2575 else if (dc->type == type_poly_building_from_triang)
2576 {
2577 draw_it = 0;
2578 }
2579 }
2580
2581 if (draw_it == 1)
2582 {
2583 entry = get_hash_entry(display_list, dc->type);
2584 if (entry && entry->di)
2585 {
2586 // // dbg(0,"++type=%s\n", item_to_name(dc->type));
2587 //if (!strcmp(item_to_name(dc->type), "border_country"))
2588 //{
2589 // displayitem_draw(entry->di, NULL, dc, display_list->order, 1, 101);
2590 //}
2591 //else
2592 //{
2593 displayitem_draw(entry->di, NULL, dc, display_list->order, 1, run_type);
2594 //}
2595 // // dbg(0,"**+gc free\n");
2596 display_context_free(dc);
2597 }
2598 }
2599 types = g_list_next(types);
2600 draw_it = 1;
2601 }
2602 es = g_list_next(es);
2603 }
2604
2605 #ifdef NAVIT_MEASURE_TIME_DEBUG
2606 debug_mrp("xdisplay_draw_elements:", debug_measure_end(s_));
2607 #endif
2608 }
2609
2610 void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
2611 {
2612 // dbg(0, "EEnter\n");
2613
2614 // HINT: seems to only be called from vehicle.c (draw the vehicle on screen)
2615
2616 GList *es;
2617 struct display_context dc;
2618 int max_coord = 32;
2619 char *buffer = g_alloca(sizeof(struct displayitem) + max_coord * sizeof(struct coord));
2620 struct displayitem *di = (struct displayitem *) buffer;
2621 es = itm->elements;
2622 di->item.type = type_none;
2623 di->item.id_hi = 0;
2624 di->item.id_lo = 0;
2625 di->item.map = NULL;
2626 di->label = label;
2627 dc.gra = gra;
2628 dc.gc = NULL;
2629 dc.gc_background = NULL;
2630 dc.img = NULL;
2631 dc.pro = projection_screen;
2632 dc.mindist = 0;
2633 dc.trans = t;
2634 dc.type = type_none;
2635 dc.maxlen = max_coord;
2636 while (es)
2637 {
2638 // dbg(0, "while loop\n");
2639 struct element *e = es->data;
2640 if (e->coord_count)
2641 {
2642 if (e->coord_count > max_coord)
2643 {
2644 //DBG // dbg(0, "maximum number of coords reached: %d > %d\n", e->coord_count, max_coord);
2645 di->count = max_coord;
2646 }
2647 else
2648 {
2649 di->count = e->coord_count;
2650 }
2651 memcpy(di->c, e->coord, di->count * sizeof(struct coord));
2652 }
2653 else
2654 {
2655 di->c[0].x = 0;
2656 di->c[0].y = 0;
2657 di->count = 1;
2658 }
2659 dc.e = e;
2660 di->next = NULL;
2661 displayitem_draw(di, NULL, &dc, transform_get_scale(t), 0, 99);
2662 display_context_free(&dc);
2663 es = g_list_next(es);
2664 }
2665 }
2666
2667 /**
2668 * FIXME
2669 * @param <>
2670 * @returns <>
2671 * @author Martin Schaller (04/2008)
2672 */
2673 static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order)
2674 {
2675 //DBG // dbg(0,"ooo enter ooo\n");
2676
2677 GList *itms;
2678 struct itemgra *itm;
2679
2680 int run_type = 0; // 99 -> normal
2681 // 1 -> normal streets (except tunnels and bridges)
2682 // 2 -> tunnel
2683 // 3 -> bridge
2684
2685 int send_refresh = 0;
2686
2687 int order_corrected = order + shift_order;
2688 if (order_corrected < limit_order_corrected)
2689 {
2690 order_corrected = limit_order_corrected;
2691 }
2692
2693 int order_corrected_2 = order + shift_order;
2694 if (order < 0)
2695 {
2696 order_corrected_2 = 0;
2697 }
2698
2699 //// dbg(0,"layer name=%s\n", lay->name);
2700
2701 if ((strncmp("streets_1", lay->name, 9) == 0))
2702 {
2703 //// dbg(0,"MT:7.3.1 - tunnel start\n");
2704 //draw_lines_count_2 = 0;
2705 //draw_lines_count_3 = 0;
2706 //draw_lines_count_4 = 0;
2707
2708 send_refresh = 1;
2709
2710 run_type = 2;
2711 itms = lay->itemgras;
2712 while (itms)
2713 {
2714 // stop drawing is requested
2715 if (cancel_drawing_global == 1)
2716 {
2717 //DBG // dbg(0, "** STOP MD 002 **\n");
2718 break;
2719 }
2720
2721 itm = itms->data;
2722 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2723 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2724 {
2725 xdisplay_draw_elements(gra, display_list, itm, run_type);
2726 }
2727 itms = g_list_next(itms);
2728 }
2729
2730 //// dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2731 //// dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2732 //// dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2733 //draw_lines_count_2 = 0;
2734 //draw_lines_count_3 = 0;
2735 //draw_lines_count_4 = 0;
2736 //// dbg(0,"MT:7.3.2 - streets start\n");
2737
2738 run_type = 1;
2739 itms = lay->itemgras;
2740 while (itms)
2741 {
2742 // stop drawing is requested
2743 if (cancel_drawing_global == 1)
2744 {
2745 //DBG // dbg(0, "** STOP MD 002 **\n");
2746 break;
2747 }
2748
2749 itm = itms->data;
2750 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2751 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2752 {
2753 xdisplay_draw_elements(gra, display_list, itm, run_type);
2754 }
2755 itms = g_list_next(itms);
2756 }
2757
2758 /*
2759 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2760 // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2761 // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2762 draw_lines_count_2 = 0;
2763 draw_lines_count_3 = 0;
2764 draw_lines_count_4 = 0;
2765 // dbg(0,"MT:7.3.3 - bridges start\n");
2766 */
2767
2768 run_type = 3;
2769 itms = lay->itemgras;
2770 while (itms)
2771 {
2772 // stop drawing is requested
2773 if (cancel_drawing_global == 1)
2774 {
2775 //DBG // dbg(0, "** STOP MD 002 **\n");
2776 break;
2777 }
2778
2779 itm = itms->data;
2780 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2781 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2782 {
2783 xdisplay_draw_elements(gra, display_list, itm, run_type);
2784 }
2785 itms = g_list_next(itms);
2786 }
2787
2788 /*
2789 // dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2790 // dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2791 // dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2792 draw_lines_count_2 = 0;
2793 draw_lines_count_3 = 0;
2794 draw_lines_count_4 = 0;
2795 // dbg(0,"MT:7.3.4 - ready\n");
2796 */
2797
2798 }
2799 else
2800 {
2801 run_type = 99;
2802 itms = lay->itemgras;
2803 while (itms)
2804 {
2805 // stop drawing is requested
2806 if (cancel_drawing_global == 1)
2807 {
2808 //DBG // dbg(0, "** STOP MD 002 **\n");
2809 break;
2810 }
2811
2812 itm = itms->data;
2813 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2814 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2815 {
2816 xdisplay_draw_elements(gra, display_list, itm, run_type);
2817 }
2818 itms = g_list_next(itms);
2819 }
2820 }
2821
2822 //if (strncmp("streets__tunnel", lay->name, 15) == 0)
2823 //{
2824 //}
2825 //else if (strncmp("streets__bridge", lay->name, 15) == 0)
2826 //{
2827 //}
2828
2829 // dirty hack to draw "waypoint(s)" ---------------------------
2830 if (strncmp("Internal", lay->name, 8) == 0)
2831 {
2832 if (global_navit->route)
2833 {
2834 if (global_navit->destination_valid == 1)
2835 {
2836 int count_ = 0;
2837 int curr_ = 0;
2838 count_ = g_list_length(global_navit->route->destinations);
2839 if (count_ > 1)
2840 {
2841 if (!global_img_waypoint)
2842 {
2843 char *path2;
2844 path2 = graphics_icon_path("nav_waypoint_bk_center.png");
2845 global_img_waypoint = graphics_image_new_scaled_rotated(gra, path2, 59, 59, 0);
2846 g_free(path2);
2847 }
2848
2849 struct point p2;
2850 struct coord pc77;
2851 GList *ldest = global_navit->route->destinations;
2852 while (ldest)
2853 {
2854 curr_++;
2855 if (curr_ < count_)
2856 {
2857 struct route_info *dst = ldest->data;
2858 pc77.x = dst->c.x;
2859 pc77.y = dst->c.y;
2860 //// dbg(0, "draw1 curr=%d x y: %d %d\n", curr_, dst->c.x, dst->c.y);
2861 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2862 transform(global_navit->trans, pro, &pc77, &p2, 1, 0, 0, NULL);
2863 // transform(global_navit->trans, projection_mg, &pc77, &p2, 1, 0, 0, NULL);
2864 p2.x = p2.x - global_img_waypoint->hot.x; // hot = 29
2865 p2.y = p2.y - global_img_waypoint->hot.y; // hot = 29
2866 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p2, global_img_waypoint->priv);
2867 }
2868 // next dest. / waypoint
2869 ldest = g_list_next(ldest);
2870 }
2871 }
2872 }
2873 }
2874 }
2875 // dirty hack to draw "waypoint(s)" ---------------------------
2876
2877
2878 if (send_refresh == 1)
2879 {
2880 // dummy "ready" signal ------------------------------------------
2881 // dbg(0, "dummy \"ready\" signal (layers)\n");
2882 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 96, 0, NULL);
2883 // dummy "ready" signal ------------------------------------------
2884 }
2885
2886 }
2887
2888 /**
2889 * FIXME
2890 * @param <>
2891 * @returns <>
2892 * @author Martin Schaller (04/2008)
2893 */
2894 static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
2895 {
2896 ////DBG // dbg(0,"ooo enter ooo\n");
2897
2898 GList *lays;
2899 struct layer *lay;
2900
2901 int draw_vector_map = 1;
2902
2903 // if zoomed out too much then use prerendered map tiles
2904 if (display_list->order < ORDER_USE_PRERENDERED_MAP)
2905 {
2906 draw_vector_map = 0;
2907 }
2908
2909 if (!draw_vector_map)
2910 {
2911 // draw prerendered big mapimage --- HERE ---
2912 struct transformation *t;
2913 t = display_list->dc.trans;
2914 struct coord *cp;
2915 cp = transform_get_center(t);
2916 struct attr attr;
2917 struct config
2918 {
2919 struct attr **attrs;
2920 struct callback_list *cbl;
2921 }*config;
2922 struct point p;
2923 int valid = 0;
2924 if (global_navit)
2925 {
2926 if ((global_navit->vehicle) && (global_navit->vehicle->vehicle))
2927 {
2928 //int a, s;
2929 //struct point pnt2;
2930 //vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
2931
2932 //struct attr pos_attr;
2933 //if (vehicle_get_attr(global_navit->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL))
2934 //{
2935 // ////DBG // dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
2936 //}
2937
2938 valid = 1;
2939 }
2940 }
2941
2942 struct coord *c;
2943 c = &(t->map_center);
2944
2945 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2946 struct coord_geo g22;
2947 struct coord *c22;
2948 struct point mcenter_pnt;
2949 c22 = &(t->map_center);
2950 transform_to_geo(projection_mg, c22, &g22);
2951 transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
2952
2953 struct coord c99;
2954 struct coord_geo g99;
2955 struct point cursor_pnt;
2956 struct point p99;
2957 long my_scale;
2958
2959 my_scale = transform_get_scale(global_navit->trans);
2960
2961 g99.lat = 0.0;
2962 g99.lng = 0.0;
2963 // g99.lat = 80.0;
2964 // g99.lng = -174.0;
2965 transform_from_geo(pro, &g99, &c99);
2966 transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2967
2968 // now really draw it
2969 struct graphics *gra22 = display_list->dc.gra;
2970 struct graphics_gc *gc22 = display_list->dc.gc;
2971 if (!gc22)
2972 {
2973 gc22 = graphics_gc_new(gra22);
2974 }
2975 // 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);
2976 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);
2977 }
2978
2979 // reset value; --> not sure here, maybe it should NOT be reset here!!!???
2980 // cancel_drawing_global = 0;
2981
2982 lays = l->layers;
2983 while (lays)
2984 {
2985 // stop drawing is requested
2986 if (cancel_drawing_global == 1)
2987 {
2988 break;
2989 }
2990
2991 lay = lays->data;
2992 if (lay->active)
2993 {
2994 xdisplay_draw_layer(display_list, gra, lay, order);
2995 }
2996 lays = g_list_next(lays);
2997 }
2998
2999 // reset value;
3000 // cancel_drawing_global = 0;
3001
3002 // dummy "start" signal ------------------------------------------
3003 // // dbg(0, "dummy \"start\" signal\n");
3004 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 97);
3005 // dummy "start" signal ------------------------------------------
3006
3007 }
3008
3009 /**
3010 * FIXME
3011 * @param <>
3012 * @returns <>
3013 * @author Martin Schaller (04/2008)
3014 */
3015 extern void *route_selection;
3016
3017 static void displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
3018 {
3019 ////DBG // dbg(0,"ooo enter ooo\n");
3020
3021 int order_corrected = order + shift_order;
3022 //int saved=displaylist->order;
3023 if (order < limit_order_corrected)
3024 {
3025 order_corrected = limit_order_corrected;
3026 // displaylist->order=0;
3027 }
3028
3029 while (layers)
3030 {
3031 struct layer *layer = layers->data;
3032 GList *itemgras = layer->itemgras;
3033 while (itemgras)
3034 {
3035 struct itemgra *itemgra = itemgras->data;
3036 GList *types = itemgra->type;
3037 if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
3038 {
3039 while (types)
3040 {
3041 enum item_type type = (enum item_type) types->data;
3042 set_hash_entry(displaylist, type);
3043 types = g_list_next(types);
3044 }
3045 }
3046 itemgras = g_list_next(itemgras);
3047 }
3048 layers = g_list_next(layers);
3049 }
3050 // displaylist->order=saved;
3051 }
3052
3053 static void displaylist_update_hash(struct displaylist *displaylist)
3054 {
3055 ////DBG // dbg(0,"ooo enter ooo\n");
3056
3057 displaylist->max_offset = 0;
3058 clear_hash(displaylist);
3059 displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
3060 // dbg(1, "max offset %d\n", displaylist->max_offset);
3061 }
3062
3063 static void do_draw(struct displaylist *displaylist, int cancel, int flags)
3064 {
3065
3066 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3067 dbg(0,"+#+:enter\n");
3068 #endif
3069
3070 // int rnd = rand();
3071 // dbg(0, "DO__DRAW:%d enter\n", rnd);
3072
3073 // try to cancel any previous drawing that might be going on ...
3074 // try to cancel any previous drawing that might be going on ...
3075 // try to cancel any previous drawing that might be going on ...
3076 // dbg(0, "DO__DRAW:%d cancel_drawing_global 1=%d\n", rnd, cancel_drawing_global);
3077 cancel_drawing_global = 1;
3078 // dbg(0, "DO__DRAW:%d cancel_drawing_global 2=%d\n", rnd, cancel_drawing_global);
3079 // try to cancel any previous drawing that might be going on ...
3080 // try to cancel any previous drawing that might be going on ...
3081 // try to cancel any previous drawing that might be going on ...
3082
3083
3084 // dbg(0, "DO__DRAW:%d lock mutex\n", rnd);
3085 pthread_mutex_lock(&uiConditionMutex);
3086 // dbg(0, "DO__DRAW:%d OK lock mutex\n", rnd);
3087
3088 // drawing is now starting ...
3089 // drawing is now starting ...
3090 // drawing is now starting ...
3091 // dbg(0, "DO__DRAW:%d cancel_drawing_global 3=%d\n", rnd, cancel_drawing_global);
3092 cancel_drawing_global = 0;
3093 // dbg(0, "DO__DRAW:%d cancel_drawing_global 4=%d\n", rnd, cancel_drawing_global);
3094 // drawing is now starting ...
3095 // drawing is now starting ...
3096 // drawing is now starting ...
3097
3098
3099 #ifdef HAVE_API_ANDROID
3100 // ---- disable map view -----
3101 // ---- disable map view -----
3102 // ---- disable map view -----
3103 if (disable_map_drawing == 1)
3104 {
3105 //android_return_generic_int(2, 0);
3106
3107 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3108 displaylist->busy = 0;
3109
3110 // dbg(0,"DO__DRAW:%d UN-lock mutex 001\n", rnd);
3111 pthread_mutex_unlock(&uiConditionMutex);
3112 // dbg(0,"DO__DRAW:%d OK UN-lock mutex 001\n", rnd);
3113
3114 // dbg(0,"DO__DRAW:%d return 001\n", rnd);
3115 return;
3116 }
3117 // ---- disable map view -----
3118 // ---- disable map view -----
3119 // ---- disable map view -----
3120 #endif
3121
3122 clock_t s_;
3123 #ifdef NAVIT_MEASURE_TIME_DEBUG
3124 s_ = debug_measure_start();
3125 #endif
3126
3127 struct item *item;
3128 int count, max = displaylist->dc.maxlen, workload = 0;
3129 struct coord *ca = g_alloca(sizeof(struct coord) * max);
3130 struct attr attr, attr2;
3131 enum projection pro;
3132 int draw_vector_map = 1; // do we draw the vecotor map, or not? 0=false, 1=true
3133 int mapset_counter = 0;
3134 int mapset_need_draw = 0;
3135
3136 // // dbg(0,"ooo enter ooo %d\n",displaylist->order);
3137
3138 int order_corrected = displaylist->order + shift_order;
3139 int saved = displaylist->order;
3140 if (order_corrected < limit_order_corrected)
3141 {
3142 order_corrected = limit_order_corrected;
3143 }
3144
3145 if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
3146 {
3147 displaylist_update_hash(displaylist);
3148 displaylist->order_hashed = displaylist->order;
3149 displaylist->layout_hashed = displaylist->layout;
3150 }
3151
3152 pro = transform_get_projection(displaylist->dc.trans);
3153
3154 // if zoomed out too much then use prerendered map tiles
3155 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP)
3156 {
3157 draw_vector_map = 0;
3158 }
3159
3160 displaylist->order = order_corrected;
3161
3162 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 003\n");
3163
3164 // reset value;
3165 // cancel_drawing_global = 0;
3166
3167 while (!cancel)
3168 {
3169 if (!displaylist->msh)
3170 {
3171 displaylist->msh = mapset_open(displaylist->ms);
3172 }
3173
3174 if (!displaylist->m)
3175 {
3176 displaylist->m = mapset_next(displaylist->msh, 1);
3177 if (!displaylist->m)
3178 {
3179 mapset_close(displaylist->msh);
3180 displaylist->msh = NULL;
3181 break;
3182 }
3183
3184 mapset_counter++;
3185 mapset_need_draw = 1;
3186 struct attr map_name_attr;
3187
3188 if (map_get_attr(displaylist->m, attr_name, &map_name_attr, NULL))
3189 {
3190 //// dbg(0,"#+* start reading map file #+*=%s\n",map_name_attr.u.str);
3191 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
3192 {
3193 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
3194 {
3195 // if its the countryborder map, always draw it
3196 mapset_need_draw = 0; // now dont even draw border map!!
3197 }
3198 else
3199 {
3200 // if its an sdcard street map, don't draw it
3201 mapset_need_draw = 0;
3202 }
3203 }
3204 }
3205
3206 ////DBG // dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
3207
3208 displaylist->dc.pro = map_projection(displaylist->m);
3209 displaylist->conv = map_requires_conversion(displaylist->m);
3210 if (route_selection)
3211 {
3212 displaylist->sel = route_selection;
3213 }
3214 else
3215 {
3216 displaylist->sel = transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
3217 }
3218 displaylist->mr = map_rect_new(displaylist->m, displaylist->sel);
3219 }
3220
3221 if (displaylist->mr)
3222 {
3223 // draw vector map, or not?
3224 //// dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
3225 if ((draw_vector_map) || (mapset_need_draw == 1))
3226 {
3227
3228 //// dbg(0, "XXXXXYYYYYYY Draw: A.01\n");
3229
3230
3231 // ------ READ all items in this map rectangle ---------
3232 // ------ READ all items in this map rectangle ---------
3233 // ------ READ all items in this map rectangle ---------
3234 // ------ READ all items in this map rectangle ---------
3235 // ------ READ all items in this map rectangle ---------
3236 // dbg(0,"#+* start reading map file #+*\n");
3237 int _item_counter_ = 0;
3238 while ((item = map_rect_get_item(displaylist->mr)))
3239 {
3240 _item_counter_++;
3241
3242 int label_count = 0;
3243 char *labels[2];
3244 struct hash_entry *entry;
3245
3246 if (cancel_drawing_global == 1)
3247 {
3248 // stop drawing map is requested
3249 //DBG // dbg(0, "** STOP MD 001 **\n");
3250 break;
3251 }
3252
3253 if (item == &busy_item)
3254 {
3255 if (displaylist->workload)
3256 {
3257 // restore order :-)
3258 displaylist->order = saved;
3259
3260 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3261 displaylist->busy = 0;
3262
3263 // dbg(0, "DO__DRAW:%d UN-lock mutex 002\n", rnd);
3264 pthread_mutex_unlock(&uiConditionMutex);
3265 // dbg(0, "DO__DRAW:%d OK UN-lock mutex 002\n", rnd);
3266
3267 //// dbg(0,"return 002\n");
3268 // dbg(0, "DO__DRAW:%d return 002\n", rnd);
3269 return;
3270 }
3271 else
3272 {
3273 continue;
3274 }
3275 }
3276
3277 entry = get_hash_entry(displaylist, item->type);
3278
3279 //// dbg(0, "XXXXXYYYYYYY Draw: A.item1 %p %i\n", entry, item->type);
3280
3281 // DEBUG -------- zoffzoff
3282 // DEBUG -------- zoffzoff
3283 // DEBUG -------- zoffzoff
3284 //item_dump_attr_stdout(item, displaylist->m);
3285 // DEBUG -------- zoffzoff
3286 // DEBUG -------- zoffzoff
3287 // DEBUG -------- zoffzoff
3288
3289 if (!entry)
3290 {
3291 continue;
3292 }
3293
3294 count = item_coord_get_within_selection(item, ca, item->type < type_line ? 1 : max, displaylist->sel);
3295
3296 if (!count)
3297 {
3298 continue;
3299 }
3300
3301 //// dbg(0, "XXXXXYYYYYYY Draw: A.item2\n");
3302
3303 if (displaylist->dc.pro != pro)
3304 {
3305 dbg(0,"from to\n");
3306 transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
3307 }
3308
3309 if (count == max)
3310 {
3311 //DBG // dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
3312 displaylist->dc.maxlen = max * 2;
3313 }
3314
3315 if (item_is_custom_poi(*item))
3316 {
3317 if (item_attr_get(item, attr_icon_src, &attr2))
3318 {
3319 labels[1] = map_convert_string(displaylist->m, attr2.u.str);
3320 }
3321 else
3322 {
3323 labels[1] = NULL;
3324 }
3325 label_count = 2;
3326 }
3327 else
3328 {
3329 labels[1] = NULL;
3330 label_count = 0;
3331 }
3332
3333 // DEBUG -------- zoffzoff
3334 // DEBUG -------- zoffzoff
3335 // DEBUG -------- zoffzoff
3336 // item_dump_attr_stdout(item, displaylist->m);
3337 // DEBUG -------- zoffzoff
3338 // DEBUG -------- zoffzoff
3339 // DEBUG -------- zoffzoff
3340
3341 if (item_attr_get(item, attr_label, &attr))
3342 {
3343 labels[0] = attr.u.str;
3344 if (!label_count)
3345 {
3346 label_count = 2;
3347 }
3348 }
3349 else
3350 {
3351 labels[0] = NULL;
3352 }
3353
3354 // DEBUG -------- zoffzoff
3355 // DEBUG -------- zoffzoff
3356 // DEBUG -------- zoffzoff
3357 // item_dump_attr_stdout(item, displaylist->m);
3358 // DEBUG -------- zoffzoff
3359 // DEBUG -------- zoffzoff
3360 // DEBUG -------- zoffzoff
3361
3362 struct attr attr_77;
3363 if (item_attr_get(item, attr_flags, &attr_77))
3364 {
3365 // // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
3366 item->flags = attr_77.u.num;
3367 }
3368 else
3369 {
3370 item->flags = 0;
3371 }
3372
3373 //struct attr *attr88;
3374 //if (item_attr_get(item, attr_flags, &attr88))
3375 //{
3376 ////DBG // dbg(0,"item flags=%d\n",attr88->u.num);
3377 //}
3378 //attr88=NULL;
3379
3380
3381 /*
3382 if (item->flags & AF_UNDERGROUND)
3383 {
3384 // dbg(0,"is UNDERGROUND\n");
3385 }
3386 else if (item->flags & AF_BRIDGE)
3387 {
3388 // dbg(0,"is BRIDGE\n");
3389 }
3390 */
3391
3392 if (displaylist->conv && label_count)
3393 {
3394 labels[0] = map_convert_string(displaylist->m, labels[0]);
3395 display_add(entry, item, count, ca, labels, label_count);
3396 map_convert_free(labels[0]);
3397 }
3398 else
3399 {
3400 display_add(entry, item, count, ca, labels, label_count);
3401 }
3402
3403 if (labels[1])
3404 {
3405 map_convert_free(labels[1]);
3406 }
3407
3408 //workload++;
3409 /*
3410 if (workload == displaylist->workload)
3411 {
3412 // restore order :-)
3413 displaylist->order = saved;
3414 // reset value;
3415 cancel_drawing_global = 0;
3416
3417 // dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3418 displaylist->busy = 0;
3419
3420 // dbg(0,"return 003\n");
3421 return;
3422 }
3423 */
3424
3425 } // while item=map_rect_get_item
3426 // ------ READ all items in this map rectangle ---------
3427 // ------ READ all items in this map rectangle ---------
3428 // ------ READ all items in this map rectangle ---------
3429 // ------ READ all items in this map rectangle ---------
3430 // ------ READ all items in this map rectangle ---------
3431
3432
3433 ////DBG // dbg(0, "XXXXXYYYYYYY Draw: A.02\n");
3434
3435 map_rect_destroy(displaylist->mr);
3436 }
3437 }
3438
3439 if (!route_selection)
3440 {
3441 map_selection_destroy(displaylist->sel);
3442 }
3443
3444 displaylist->mr = NULL;
3445 displaylist->sel = NULL;
3446 displaylist->m = NULL;
3447 } // while ----
3448
3449
3450 // dbg(0, "DO__DRAW:%d load ready\n", rnd);
3451
3452 #ifdef NAVIT_MEASURE_TIME_DEBUG
3453 debug_mrp("do_draw:load", debug_measure_end(s_));
3454 #endif
3455 s_ = debug_measure_start();
3456
3457 // remove the "wait" screen
3458 //#ifdef HAVE_API_ANDROID
3459 // android_return_generic_int(2, 0);
3460 //#endif
3461
3462 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 004\n");
3463
3464 // reset value;
3465 // cancel_drawing_global = 0;
3466
3467 // restore order :-)
3468 displaylist->order = saved;
3469
3470 // profile(1,"process_selection\n");
3471
3472
3473 if (displaylist->idle_ev)
3474 {
3475 event_remove_idle(displaylist->idle_ev);
3476 displaylist->idle_ev = NULL;
3477 }
3478
3479 if (displaylist->idle_cb)
3480 {
3481 callback_destroy(displaylist->idle_cb);
3482 displaylist->idle_cb = NULL;
3483 }
3484
3485 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3486 //displaylist->busy = 0;
3487
3488 // graphics_process_selection(displaylist->dc.gra, displaylist);
3489
3490 //profile(1, "draw\n");
3491
3492 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 005\n");
3493
3494 if (!cancel)
3495 {
3496 int flags2 = flags;
3497 if (!(flags2 & 2))
3498 {
3499 if (!draw_vector_map)
3500 {
3501 // dont clean bg of screen when drawing prerendered tiles
3502 flags2 = flags2 + 2;
3503 }
3504 }
3505 //DBG // dbg(0,"call graphics_displaylist_draw 3")
3506 //// dbg(0,"# MT:002 #\n");
3507
3508 // stop drawing is requested
3509 if (cancel_drawing_global != 1)
3510 {
3511 graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
3512 }
3513 //// dbg(0,"# MT:003 #\n");
3514 }
3515
3516 #ifdef NAVIT_MEASURE_TIME_DEBUG
3517 debug_mrp("do_draw:draw", debug_measure_end(s_));
3518 #endif
3519
3520 // dbg(0, "DO__DRAW:%d draw ready\n", rnd);
3521
3522 #ifdef HAVE_API_ANDROID
3523 if (cur_mapdraw_time_index < 11)
3524 {
3525 mapdraw_time[cur_mapdraw_time_index] = debug_measure_end_tsecs(s_);
3526 // // dbg(0,"maptime: %d\n", mapdraw_time[cur_mapdraw_time_index]);
3527 cur_mapdraw_time_index++;
3528 }
3529
3530 if (cur_mapdraw_time_index > 10)
3531 {
3532 cur_mapdraw_time_index = 0;
3533 int jk;
3534 int mean_time = 0;
3535 for (jk=0;jk<11;jk++)
3536 {
3537 mean_time = mean_time + mapdraw_time[jk];
3538 }
3539 android_return_generic_int(6, (int)((float)mean_time / (float)10));
3540 }
3541 #endif
3542
3543 //// dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3544 displaylist->busy = 0;
3545
3546 //DBG // dbg(0, "XXXXXYYYYYYY Draw: 006\n");
3547
3548 map_rect_destroy(displaylist->mr);
3549 if (!route_selection)
3550 {
3551 map_selection_destroy(displaylist->sel);
3552 }
3553 mapset_close(displaylist->msh);
3554 displaylist->mr = NULL;
3555 displaylist->sel = NULL;
3556 displaylist->m = NULL;
3557 displaylist->msh = NULL;
3558
3559 //dbg(0, "callback\n");
3560
3561 // only some old crap need this!! ----------
3562 // only some old crap need this!! ----------
3563 /// **** callback_call_1(displaylist->cb, cancel);
3564 // only some old crap need this!! ----------
3565 // only some old crap need this!! ----------
3566
3567
3568 // dbg(0, "DO__DRAW:%d UN-lock mutex leave\n", rnd);
3569 pthread_mutex_unlock(&uiConditionMutex);
3570 // dbg(0, "DO__DRAW:%d OK UN-lock mutex leave\n", rnd);
3571
3572 // dbg(0, "DO__DRAW:%d cancel_drawing_global 99=%d\n", rnd, cancel_drawing_global);
3573
3574 if (cancel_drawing_global != 1)
3575 {
3576 // dummy "ready" signal ------------------------------------------
3577 // dbg(0, "DO__DRAW:%d dummy \"ready\" signal\n", rnd);
3578 // gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 99);
3579 #ifdef HAVE_API_ANDROID
3580 android_return_generic_int(2, 2);
3581 #endif
3582 // dummy "ready" signal ------------------------------------------
3583 }
3584 else
3585 {
3586 // dummy "cancel" signal ------------------------------------------
3587 // dbg(0, "DO__DRAW:%d dummy \"cancel\" signal\n", rnd);
3588 //gra->meth.draw_lines4(displaylist->dc.gra, NULL, NULL, NULL, 1, 1, 95);
3589 #ifdef HAVE_API_ANDROID
3590 android_return_generic_int(2, 3);
3591 #endif
3592 // dummy "ready" signal ------------------------------------------
3593 }
3594
3595 // dbg(0, "DO__DRAW:%d leave\n", rnd);
3596 // dbg(0, "DO__DRAW:%d __\n", rnd);
3597
3598 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3599 dbg(0,"+#+:leave\n");
3600 #endif
3601
3602 }
3603
3604 /**
3605 * FIXME
3606 * @param <>
3607 * @returns <>
3608 * @author Martin Schaller (04/2008)
3609 */
3610 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
3611 {
3612 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3613 dbg(0,"+#+:enter\n");
3614 #endif
3615
3616 // // dbg(0,"ooo enter ooo flags=%d\n", flags);
3617
3618
3619 int order = transform_get_order(trans);
3620 displaylist->dc.trans = trans;
3621 displaylist->dc.gra = gra;
3622
3623 // *********DISABLED*******
3624 // *********DISABLED*******
3625 // *********DISABLED*******
3626 // set min. distancte of 2 points on line at which a point will be left out when zoomed out too much!!
3627 // *********DISABLED******* displaylist->dc.mindist = transform_get_scale(trans) / 2;
3628 //// dbg(0,"mindist would be:%d\n", (int)(transform_get_scale(trans) / 2));
3629 displaylist->dc.mindist = 0;
3630 if (order < 8)
3631 {
3632 displaylist->dc.mindist = transform_get_scale(trans) * 2;
3633 }
3634 else if (order < 13)
3635 {
3636 displaylist->dc.mindist = transform_get_scale(trans);
3637 }
3638 // *********DISABLED*******
3639 // *********DISABLED*******
3640 // *********DISABLED*******
3641
3642
3643 // FIXME find a better place to set the background color
3644 if (l)
3645 {
3646 graphics_gc_set_background(gra->gc[0], &l->color);
3647 graphics_gc_set_foreground(gra->gc[0], &l->color);
3648 gra->default_font = g_strdup(l->font);
3649 }
3650 graphics_background_gc(gra, gra->gc[0]);
3651 if (flags & 1)
3652 {
3653 // calls -> navit.c navit_predraw --> draw all vehicles
3654 callback_list_call_attr_0(gra->cbl, attr_predraw);
3655 }
3656 gra->meth.draw_mode(gra->priv, (flags & 8) ? draw_mode_begin_clear : draw_mode_begin);
3657 if (!(flags & 2))
3658 {
3659 // clear the gfx object pipeline ------------------------------
3660 // // dbg(0, "clear the gfx object pipeline\n");
3661 // gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 98);
3662
3663 // clear the display/screen/whatever here
3664 // 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);
3665 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);
3666 }
3667 if (l)
3668 {
3669 // draw the mapitems
3670 // // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
3671 xdisplay_draw(displaylist, gra, l, order + l->order_delta);
3672 }
3673 if (flags & 1)
3674 {
3675 callback_list_call_attr_0(gra->cbl, attr_postdraw);
3676 }
3677 if (!(flags & 4))
3678 {
3679 gra->meth.draw_mode(gra->priv, draw_mode_end);
3680 }
3681
3682 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3683 dbg(0,"+#+:leave\n");
3684 #endif
3685
3686 }
3687
3688 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)
3689 {
3690 // dbg(0, "DO__DRAW:gl_ms enter\n");
3691
3692 int order = transform_get_order(trans);
3693
3694 //// dbg(0,"enter displaylist->busy=%d\n",displaylist->busy);
3695 //// dbg(0,"async=%d\n",async);
3696 if (displaylist->busy)
3697 {
3698 if (async == 1)
3699 {
3700 //// dbg(0,"**draw 1.a\n");
3701 // dbg(0, "DO__DRAW:gl_ms return 001\n");
3702 return;
3703 }
3704 ///// dbg(0,"**draw 1\n");
3705 // dbg(0, "DO__DRAW:gl_ms return 002\n");
3706 return;
3707 //do_draw(displaylist, 1, flags);
3708 }
3709 xdisplay_free(displaylist);
3710
3711 displaylist->dc.gra = gra;
3712 displaylist->ms = mapset;
3713 displaylist->dc.trans = trans;
3714 displaylist->workload = async ? 100 : 0;
3715 displaylist->cb = cb;
3716 displaylist->seq++;
3717
3718 if (l)
3719 {
3720 order += l->order_delta;
3721 }
3722 displaylist->order = order;
3723 //// dbg(0,"set:1:displaylist->busy=%d\n",displaylist->busy);
3724 displaylist->busy = 1;
3725 displaylist->layout = l;
3726
3727 // ---------- DISABLED ------ no more async!!
3728 /*
3729 if (async)
3730 {
3731 //DBG // dbg(0,"§§async");
3732 if (!displaylist->idle_cb)
3733 {
3734 //DBG // dbg(0,"§§async --> callback");
3735 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3736 }
3737 //DBG // dbg(0,"§§async --> add idle");
3738 displaylist->idle_ev = event_add_idle(50, displaylist->idle_cb);
3739 }
3740 else
3741 {
3742 //DBG // dbg(0,"@@sync");
3743 do_draw(displaylist, 0, flags);
3744 }
3745 */
3746
3747 if (async)
3748 {
3749 if (!displaylist->idle_cb)
3750 {
3751 //dbg(0,"**draw 2.b1\n");
3752 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3753 callback_add_names(displaylist->idle_cb, "graphics_load_mapset", "do_draw");
3754 //// dbg(0,"**draw 2.b2\n");
3755 }
3756 //dbg(0,"**draw 2.b3\n");
3757 //dbg(0, "DO__DRAW:call 003 (async callback)\n");
3758 displaylist->idle_ev = event_add_idle(1000, displaylist->idle_cb);
3759 // dbg(0, "**draw 2.b4 %p\n", displaylist->idle_ev);
3760 }
3761 else
3762 {
3763 //// dbg(0,"**draw 2.b5\n");
3764 // dbg(0, "DO__DRAW:call 001\n");
3765 do_draw(displaylist, 0, flags);
3766 }
3767
3768 // dbg(0, "DO__DRAW:gl_ms leave\n");
3769 }
3770
3771 /**
3772 * FIXME
3773 * @param <>
3774 * @returns <>
3775 * @author Martin Schaller (04/2008)
3776 */
3777 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)
3778 {
3779 //// dbg(0,"ooo enter ooo\n");
3780
3781 // dbg(0, "DO__DRAW:gras_draw enter\n");
3782 graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
3783 // dbg(0, "DO__DRAW:gras_draw leave\n");
3784 }
3785
3786 int graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
3787 {
3788 //DBG // dbg(0,"ooo enter ooo\n");
3789
3790 if (!displaylist->busy)
3791 {
3792 return 0;
3793 }
3794 // dbg(0, "DO__DRAW:call 002\n");
3795 do_draw(displaylist, 1, 0);
3796 return 1;
3797 }
3798
3799 /**
3800 * FIXME
3801 * @param <>
3802 * @returns <>
3803 * @author Martin Schaller (04/2008)
3804 */
3805 struct displaylist_handle
3806 {
3807 struct displaylist *dl;
3808 struct displayitem *di;
3809 int hashidx;
3810 };
3811
3812 /**
3813 * FIXME
3814 * @param <>
3815 * @returns <>
3816 * @author Martin Schaller (04/2008)
3817 */
3818 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
3819 {
3820 struct displaylist_handle *ret;
3821
3822 ret=g_new0(struct displaylist_handle, 1);
3823 ret->dl = displaylist;
3824
3825 return ret;
3826 }
3827
3828 /**
3829 * FIXME
3830 * @param <>
3831 * @returns <>
3832 * @author Martin Schaller (04/2008)
3833 */
3834 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
3835 {
3836 struct displayitem *ret;
3837 if (!dlh)
3838 return NULL;
3839 for (;;)
3840 {
3841 if (dlh->di)
3842 {
3843 ret = dlh->di;
3844 dlh->di = ret->next;
3845 break;
3846 }
3847 if (dlh->hashidx == HASH_SIZE_GRAPHICS_)
3848 {
3849 ret = NULL;
3850 break;
3851 }
3852 if (dlh->dl->hash_entries[dlh->hashidx].type)
3853 dlh->di = dlh->dl->hash_entries[dlh->hashidx].di;
3854 dlh->hashidx++;
3855 }
3856 return ret;
3857 }
3858
3859 /**
3860 * FIXME
3861 * @param <>
3862 * @returns <>
3863 * @author Martin Schaller (04/2008)
3864 */
3865 void graphics_displaylist_close(struct displaylist_handle *dlh)
3866 {
3867 g_free(dlh);
3868 }
3869
3870 /**
3871 * FIXME
3872 * @param <>
3873 * @returns <>
3874 * @author Martin Schaller (04/2008)
3875 */
3876 struct displaylist * graphics_displaylist_new(void)
3877 {
3878 struct displaylist *ret=g_new0(struct displaylist, 1);
3879
3880 ret->dc.maxlen = 16384;
3881 ret->busy = 0;
3882
3883 return ret;
3884 }
3885
3886 /**
3887 * FIXME
3888 * @param <>
3889 * @returns <>
3890 * @author Martin Schaller (04/2008)
3891 */
3892 struct item * graphics_displayitem_get_item(struct displayitem *di)
3893 {
3894 return &di->item;
3895 }
3896
3897 int graphics_displayitem_get_coord_count(struct displayitem *di)
3898 {
3899 return di->count;
3900 }
3901
3902 /**
3903 * FIXME
3904 * @param <>
3905 * @returns <>
3906 * @author Martin Schaller (04/2008)
3907 */
3908 char * graphics_displayitem_get_label(struct displayitem *di)
3909 {
3910 return di->label;
3911 }
3912
3913 int graphics_displayitem_get_displayed(struct displayitem *di)
3914 {
3915 return 1;
3916 }
3917
3918 /**
3919 * FIXME
3920 * @param <>
3921 * @returns <>
3922 * @author Martin Schaller (04/2008)
3923 */
3924 static int within_dist_point(struct point *p0, struct point *p1, int dist)
3925 {
3926 if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
3927 return 0;
3928 if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
3929 return 0;
3930 if ((p0->x - p1->x) * (p0->x - p1->x) + (p0->y - p1->y) * (p0->y - p1->y) <= dist * dist)
3931 {
3932 return 1;
3933 }
3934 return 0;
3935 }
3936
3937 /**
3938 * FIXME
3939 * @param <>
3940 * @returns <>
3941 * @author Martin Schaller (04/2008)
3942 */
3943 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
3944 {
3945 int vx, vy, wx, wy;
3946 int c1, c2;
3947 struct point line_p;
3948
3949 if (line_p0->x < line_p1->x)
3950 {
3951 if (p->x < line_p0->x - dist)
3952 return 0;
3953 if (p->x > line_p1->x + dist)
3954 return 0;
3955 }
3956 else
3957 {
3958 if (p->x < line_p1->x - dist)
3959 return 0;
3960 if (p->x > line_p0->x + dist)
3961 return 0;
3962 }
3963 if (line_p0->y < line_p1->y)
3964 {
3965 if (p->y < line_p0->y - dist)
3966 return 0;
3967 if (p->y > line_p1->y + dist)
3968 return 0;
3969 }
3970 else
3971 {
3972 if (p->y < line_p1->y - dist)
3973 return 0;
3974 if (p->y > line_p0->y + dist)
3975 return 0;
3976 }
3977
3978 vx = line_p1->x - line_p0->x;
3979 vy = line_p1->y - line_p0->y;
3980 wx = p->x - line_p0->x;
3981 wy = p->y - line_p0->y;
3982
3983 c1 = vx * wx + vy * wy;
3984 if (c1 <= 0)
3985 return within_dist_point(p, line_p0, dist);
3986 c2 = vx * vx + vy * vy;
3987 if (c2 <= c1)
3988 return within_dist_point(p, line_p1, dist);
3989
3990 line_p.x = line_p0->x + vx * c1 / c2;
3991 line_p.y = line_p0->y + vy * c1 / c2;
3992 return within_dist_point(p, &line_p, dist);
3993 }
3994
3995 /**
3996 * FIXME
3997 * @param <>
3998 * @returns <>
3999 * @author Martin Schaller (04/2008)
4000 */
4001 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
4002 {
4003 int i;
4004 for (i = 0; i < count - 1; i++)
4005 {
4006 if (within_dist_line(p, line_pnt + i, line_pnt + i + 1, dist))
4007 {
4008 return 1;
4009 }
4010 }
4011 if (close)
4012 return (within_dist_line(p, line_pnt, line_pnt + count - 1, dist));
4013 return 0;
4014 }
4015
4016 /**
4017 * FIXME
4018 * @param <>
4019 * @returns <>
4020 * @author Martin Schaller (04/2008)
4021 */
4022 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
4023 {
4024 int i, j, c = 0;
4025 for (i = 0, j = count - 1; i < count; j = i++)
4026 {
4027 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))
4028 c = !c;
4029 }
4030 if (!c)
4031 return within_dist_polyline(p, poly_pnt, count, dist, 1);
4032 return c;
4033 }
4034
4035 /**
4036 * FIXME
4037 * @param <>
4038 * @returns <>
4039 * @author Martin Schaller (04/2008)
4040 */
4041 int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
4042 {
4043 struct point *pa = g_alloca(sizeof(struct point) * displaylist->dc.maxlen);
4044 int count;
4045
4046 count = transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
4047
4048 if (di->item.type < type_line)
4049 {
4050 return within_dist_point(p, &pa[0], dist);
4051 }
4052 if (di->item.type < type_area)
4053 {
4054 return within_dist_polyline(p, pa, count, dist, 0);
4055 }
4056 return within_dist_polygon(p, pa, count, dist);
4057 }
4058
4059 static void graphics_process_selection_item(struct displaylist *dl, struct item *item)
4060 {
4061 #if 0 /* FIXME */
4062 struct displayitem di,*di_res;
4063 GHashTable *h;
4064 int count,max=dl->dc.maxlen;
4065 struct coord ca[max];
4066 struct attr attr;
4067 struct map_rect *mr;
4068
4069 di.item=*item;
4070 di.label=NULL;
4071 di.count=0;
4072 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
4073 if (h)
4074 {
4075 di_res=g_hash_table_lookup(h, &di);
4076 if (di_res)
4077 {
4078 di.item.type=(enum item_type)item->priv_data;
4079 display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
4080 return;
4081 }
4082 }
4083 mr=map_rect_new(item->map, NULL);
4084 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
4085 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
4086 if (!item_attr_get(item, attr_label, &attr))
4087 attr.u.str=NULL;
4088 if (dl->conv && attr.u.str && attr.u.str[0])
4089 {
4090 char *str=map_convert_string(item->map, attr.u.str);
4091 display_add(dl, item, count, ca, &str, 1);
4092 map_convert_free(str);
4093 }
4094 else
4095 display_add(dl, item, count, ca, &attr.u.str, 1);
4096 map_rect_destroy(mr);
4097 #endif
4098 }
4099
4100 void graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
4101 {
4102 struct item *item_dup=g_new(struct item, 1);
4103 *item_dup = *item;
4104 item_dup->priv_data = (void *) type;
4105 gra->selection = g_list_append(gra->selection, item_dup);
4106 if (dl)
4107 graphics_process_selection_item(dl, item_dup);
4108 }
4109
4110 void graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
4111 {
4112 GList *curr;
4113 int found;
4114
4115 for (;;)
4116 {
4117 curr = gra->selection;
4118 found = 0;
4119 while (curr)
4120 {
4121 struct item *sitem = curr->data;
4122 if (item_is_equal(*item, *sitem))
4123 {
4124 if (dl)
4125 {
4126 struct displayitem di;
4127 /* Unused Variable
4128 GHashTable *h; */
4129 di.item = *sitem;
4130 di.label = NULL;
4131 di.count = 0;
4132 di.item.type = type;
4133 #if 0 /* FIXME */
4134 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
4135 if (h)
4136 g_hash_table_remove(h, &di);
4137 #endif
4138 }
4139 g_free(sitem);
4140 gra->selection = g_list_remove(gra->selection, curr->data);
4141 found = 1;
4142 break;
4143 }
4144 }
4145 if (!found)
4146 return;
4147 }
4148 }
4149
4150 void graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
4151 {
4152 while (gra->selection)
4153 {
4154 struct item *item = (struct item *) gra->selection->data;
4155 graphics_remove_selection(gra, item, (enum item_type) item->priv_data, dl);
4156 }
4157 }
4158
4159 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl)
4160 {
4161 GList *curr;
4162
4163 curr = gra->selection;
4164 while (curr)
4165 {
4166 struct item *item = curr->data;
4167 graphics_process_selection_item(dl, item);
4168 curr = g_list_next(curr);
4169 }
4170 }

   
Visit the ZANavi Wiki