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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki