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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki