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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 29 - (show annotations) (download)
Tue Aug 21 19:31:50 2012 UTC (11 years, 8 months ago) by zoff99
File MIME type: text/plain
File size: 93193 byte(s)
some 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 // minimum (line legth * 32) squared (in pixel) to show text label
86 #define MIN_LINE_LENGTH_FOR_TEXT_2 409600
87 // minimum (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 now obsolete!! and unused!!!!
1411 // this func. is now obsolete!! and unused!!!!
1412 // this func. is now 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 now obsolete!! and unused!!!!
1578 // this func. is now obsolete!! and unused!!!!
1579 // this func. is now 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 = 2000;
1829 struct point_rect r = gra->r;
1830
1831
1832 #if 0
1833 // check if whole line is within a 2x2 pixel square
1834 if (order < 11)
1835 {
1836 const int max_dist = 2*2;
1837 int need_draw = 0;
1838 int diff;
1839 for (i = 0; i < count; i++)
1840 {
1841 if (i > 0)
1842 {
1843 p2.x = pa[i].x;
1844 p2.y = pa[i].y;
1845 diff = (p2.x - p1.x) * (p2.y - p1.y);
1846 if (diff < 0)
1847 {
1848 diff = -diff;
1849 }
1850
1851 if (diff > max_dist)
1852 {
1853 // line is bigger, so we need to draw it
1854 need_draw = 1;
1855 break;
1856 }
1857 }
1858 else
1859 {
1860 p1.x = pa[i - 1].x;
1861 p1.y = pa[i - 1].y;
1862 }
1863 }
1864
1865 if (need_draw == 0)
1866 {
1867 // dont draw this line
1868 return;
1869 }
1870 }
1871 #endif
1872
1873
1874 // calc visible area on screen
1875 wmax=width[0];
1876 r.lu.x-=wmax;
1877 r.lu.y-=wmax;
1878 r.rl.x+=wmax;
1879 r.rl.y+=wmax;
1880
1881 for (i = 0; i < count; i++)
1882 {
1883 if (i > 0)
1884 {
1885 p1.x = pa[i - 1].x;
1886 p1.y = pa[i - 1].y;
1887 p2.x = pa[i].x;
1888 p2.y = pa[i].y;
1889 /* 0 = invisible, 1 = completely visible, 2,3 = at least part of line visible */
1890 code=clip_line_aprox(&p1, &p2, &r);
1891 // code = 1;
1892
1893 if (code > 0)
1894 {
1895 if (out == 0)
1896 {
1897 p[out].x=p1.x;
1898 p[out].y=p1.y;
1899 out++;
1900 }
1901 p[out].x=p2.x;
1902 p[out].y=p2.y;
1903 out++;
1904
1905 if ((out <= max_segs) && (i < (count - 1)))
1906 {
1907 // ok gather more line segs
1908 continue;
1909 }
1910 }
1911 else // (code == 0)
1912 {
1913 if (out == 0)
1914 {
1915 // first visible line seg not yet found, search on ...
1916 continue;
1917 }
1918 }
1919
1920 // PAINT --- LINE SEGMENTS ------------
1921 // PAINT --- LINE SEGMENTS ------------
1922
1923 if ((poly == 1) || (poly == 0))
1924 {
1925 // normal street
1926 //if (1 == 0)
1927 //{
1928 // // draw as polygon --> OLD method
1929 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 1, order, 0);
1930 //}
1931 //else
1932 //{
1933 // draw as line
1934 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i]);
1935 //draw_lines_count_3++;
1936 //}
1937
1938 // one way arrow
1939 if ((oneway > 0) && (order > 13))
1940 {
1941 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1942 //draw_lines_count_2++;
1943 }
1944 }
1945 else if (poly == 2)
1946 {
1947 // ******* street is underground ********
1948 // ******* street is underground ********
1949 // ******* street is underground ********
1950
1951 //if (1 == 0)
1952 //{
1953 // // draw as polygon --> OLD method
1954 // graphics_draw_polyline_as_polygon(gra, gc, p, out, w, step, 0, order, 0);
1955 //}
1956 //else
1957 //{
1958
1959 // draw as line
1960 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 1);
1961 //draw_lines_count_4++;
1962 //}
1963
1964 // one way arrow
1965 if ((oneway > 0) && (order > 13))
1966 {
1967 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1968 //draw_lines_count_2++;
1969 }
1970 }
1971 else if (poly == 3)
1972 {
1973 // ******* street has bridge ********
1974 // ******* street has bridge ********
1975 // ******* street has bridge ********
1976 gra->meth.draw_lines4(gra->priv, gc->priv, p, out, order, width[i], 2);
1977 //draw_lines_count_4++;
1978
1979 // one way arrow
1980 if ((oneway > 0) && (order > 13))
1981 {
1982 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1983 //draw_lines_count_2++;
1984 }
1985 }
1986 // --> now NOT used anymore!!
1987 else // poly==0 -> street that is only a line (width=1)
1988 {
1989 // OLD // gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, 0);
1990
1991 gra->meth.draw_lines3(gra->priv, gc->priv, p, out, order, width[i]);
1992 //draw_lines_count_3++;
1993
1994 // one way arrow
1995 if ((oneway > 0) && (order > 13))
1996 {
1997 gra->meth.draw_lines2(gra->priv, gc->priv, p, out, order, oneway);
1998 //draw_lines_count_2++;
1999 }
2000 }
2001
2002 out = 0; // reset point counter after painting
2003 // PAINT --- LINE SEGMENTS ------------
2004 // PAINT --- LINE SEGMENTS ------------
2005 // PAINT --- LINE SEGMENTS ------------
2006 }
2007 }
2008 }
2009
2010
2011 static int is_inside(struct point *p, struct point_rect *r, int edge)
2012 {
2013 switch (edge)
2014 {
2015 case 0:
2016 return p->x >= r->lu.x;
2017 case 1:
2018 return p->x <= r->rl.x;
2019 case 2:
2020 return p->y >= r->lu.y;
2021 case 3:
2022 return p->y <= r->rl.y;
2023 default:
2024 return 0;
2025 }
2026 }
2027
2028 static void poly_intersection(struct point *p1, struct point *p2, struct point_rect *r, int edge, struct point *ret)
2029 {
2030 int dx = p2->x - p1->x;
2031 int dy = p2->y - p1->y;
2032 switch (edge)
2033 {
2034 case 0:
2035 ret->y = p1->y + (r->lu.x - p1->x) * dy / dx;
2036 ret->x = r->lu.x;
2037 break;
2038 case 1:
2039 ret->y = p1->y + (r->rl.x - p1->x) * dy / dx;
2040 ret->x = r->rl.x;
2041 break;
2042 case 2:
2043 ret->x = p1->x + (r->lu.y - p1->y) * dx / dy;
2044 ret->y = r->lu.y;
2045 break;
2046 case 3:
2047 ret->x = p1->x + (r->rl.y - p1->y) * dx / dy;
2048 ret->y = r->rl.y;
2049 break;
2050 }
2051 }
2052
2053 static void graphics_draw_polygon_clipped(struct graphics *gra, struct graphics_gc *gc, struct point *pin, int count_in)
2054 {
2055 struct point_rect r = gra->r;
2056 struct point *pout, *p, *s, pi, *p1, *p2;
2057 int limit = 10000;
2058 struct point *pa1 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2059 struct point *pa2 = g_alloca(sizeof(struct point) * (count_in < limit ? count_in * 8 + 1 : 0));
2060 int count_out, edge = 3;
2061 int i;
2062 #if 0
2063 r.lu.x+=20;
2064 r.lu.y+=20;
2065 r.rl.x-=20;
2066 r.rl.y-=20;
2067 #endif
2068 if (count_in < limit)
2069 {
2070 p1 = pa1;
2071 p2 = pa2;
2072 }
2073 else
2074 {
2075 p1=g_new(struct point, count_in*8+1);
2076 p2=g_new(struct point, count_in*8+1);
2077 }
2078
2079 pout=p1;
2080 for (edge = 0; edge < 4; edge++)
2081 {
2082 p=pin;
2083 s=pin+count_in-1;
2084 count_out=0;
2085 for (i = 0; i < count_in; i++)
2086 {
2087 if (is_inside(p, &r, edge))
2088 {
2089 if (! is_inside(s, &r, edge))
2090 {
2091 poly_intersection(s,p,&r,edge,&pi);
2092 pout[count_out++]=pi;
2093 }
2094 pout[count_out++]=*p;
2095 }
2096 else
2097 {
2098 if (is_inside(s, &r, edge))
2099 {
2100 poly_intersection(p,s,&r,edge,&pi);
2101 pout[count_out++]=pi;
2102 }
2103 }
2104 s=p;
2105 p++;
2106 }
2107 count_in=count_out;
2108 if (pin == p1)
2109 {
2110 pin=p2;
2111 pout=p1;
2112 }
2113 else
2114 {
2115 pin=p1;
2116 pout=p2;
2117 }
2118 }
2119
2120 gra->meth.draw_polygon(gra->priv, gc->priv, pin, count_in);
2121 if (count_in >= limit)
2122 {
2123 g_free(p1);
2124 g_free(p2);
2125 }
2126 }
2127
2128 static void display_context_free(struct display_context *dc)
2129 {
2130 if (dc->gc)
2131 graphics_gc_destroy(dc->gc);
2132 if (dc->gc_background)
2133 graphics_gc_destroy(dc->gc_background);
2134 if (dc->img)
2135 graphics_image_free(dc->gra, dc->img);
2136 dc->gc = NULL;
2137 dc->gc_background = NULL;
2138 dc->img = NULL;
2139 }
2140
2141 static struct graphics_font *
2142 get_font(struct graphics *gra, int size)
2143 {
2144 if (size > 64)
2145 {
2146 size = 64;
2147 }
2148 if (size >= gra->font_len)
2149 {
2150 gra->font=g_renew(struct graphics_font *, gra->font, size+1);
2151 while (gra->font_len <= size)
2152 {
2153 gra->font[gra->font_len++] = NULL;
2154 }
2155 }
2156 if (!gra->font[size])
2157 {
2158 gra->font[size] = graphics_font_new(gra, size * gra->font_size, 0);
2159 }
2160 return gra->font[size];
2161 }
2162
2163 void graphics_draw_text_std(struct graphics *this_, int text_size, char *text, struct point *p)
2164 {
2165 struct graphics_font *font = get_font(this_, text_size);
2166 struct point bbox[4];
2167 int i;
2168
2169 graphics_get_text_bbox(this_, font, text, 0x10000, 0, bbox, 0);
2170 for (i = 0; i < 4; i++)
2171 {
2172 bbox[i].x += p->x;
2173 bbox[i].y += p->y;
2174 }
2175 graphics_draw_rectangle(this_, this_->gc[2], &bbox[1], bbox[2].x - bbox[0].x, bbox[0].y - bbox[1].y + 5);
2176 graphics_draw_text(this_, this_->gc[1], this_->gc[2], font, text, p, 0x10000, 0);
2177 }
2178
2179 char *
2180 graphics_icon_path(char *icon)
2181 {
2182 static char *navit_sharedir;
2183 char *ret = NULL;
2184 struct file_wordexp *wordexp = NULL;
2185 // dbg(1, "enter %s\n", icon);
2186 if (strchr(icon, '$'))
2187 {
2188 wordexp = file_wordexp_new(icon);
2189 if (file_wordexp_get_count(wordexp))
2190 {
2191 icon = file_wordexp_get_array(wordexp)[0];
2192 }
2193 }
2194
2195 if (strchr(icon, '/'))
2196 {
2197 ret = g_strdup(icon);
2198 }
2199 else
2200 {
2201 #ifdef HAVE_API_ANDROID
2202 // get resources for the correct screen density
2203 //
2204 // this part not needed, android unpacks only the correct version into res/drawable dir!
2205 // // dbg(1,"android icon_path %s\n",icon);
2206 // static char *android_density;
2207 // android_density = getenv("ANDROID_DENSITY");
2208 // ret=g_strdup_printf("res/drawable-%s/%s",android_density ,icon);
2209 ret=g_strdup_printf("res/drawable/%s" ,icon);
2210 #else
2211 if (!navit_sharedir)
2212 {
2213 navit_sharedir = getenv("NAVIT_SHAREDIR");
2214 }
2215 ret = g_strdup_printf("%s/xpm/%s", navit_sharedir, icon);
2216 #endif
2217 }
2218
2219 if (wordexp)
2220 {
2221 file_wordexp_destroy(wordexp);
2222 }
2223
2224 return ret;
2225 }
2226
2227 static int limit_count(struct coord *c, int count)
2228 {
2229 int i;
2230 for (i = 1; i < count; i++)
2231 {
2232 if (c[i].x == c[0].x && c[i].y == c[0].y)
2233 return i + 1;
2234 }
2235 return count;
2236 }
2237
2238 static void displayitem_draw(struct displayitem *di, void *dummy, struct display_context *dc, int order, int allow_dashed, int run_type)
2239 {
2240 ////DBG dbg(0,"ooo enter ooo\n");
2241
2242 int *width = g_alloca(sizeof(int) * dc->maxlen);
2243 struct point *pa = g_alloca(sizeof(struct point) * dc->maxlen);
2244 struct graphics *gra = dc->gra;
2245 struct graphics_gc *gc = dc->gc;
2246 struct element *e = dc->e;
2247 struct graphics_image *img = dc->img;
2248 struct point p;
2249 char *path;
2250
2251 //if (run_type > 100) dbg(0,"enter\n");
2252
2253 while (di)
2254 {
2255 if (run_type != 99)
2256 {
2257 if (run_type == 1)
2258 {
2259 if (di->item.flags & AF_UNDERGROUND)
2260 {
2261 // next item
2262 di = di->next;
2263 continue;
2264 }
2265 else if (di->item.flags & AF_BRIDGE)
2266 {
2267 // next item
2268 di = di->next;
2269 continue;
2270 }
2271 }
2272 else if (run_type == 2)
2273 {
2274 // tunnel
2275 if (di->item.flags & AF_UNDERGROUND)
2276 {
2277 }
2278 else
2279 {
2280 // next item
2281 di = di->next;
2282 continue;
2283 }
2284 }
2285 else if (run_type == 3)
2286 {
2287 // bridge
2288 if (di->item.flags & AF_BRIDGE)
2289 {
2290 }
2291 else
2292 {
2293 // next item
2294 di = di->next;
2295 continue;
2296 }
2297 }
2298 }
2299
2300 int i, count = di->count, mindist = dc->mindist;
2301
2302 if (!gc)
2303 {
2304 gc = graphics_gc_new(gra);
2305 graphics_gc_set_foreground(gc, &e->color);
2306 dc->gc = gc;
2307 }
2308
2309 if (item_type_is_area(dc->type) && (dc->e->type == element_polyline || dc->e->type == element_text))
2310 {
2311 count = limit_count(di->c, count);
2312 }
2313 if (dc->type == type_poly_water_tiled)
2314 {
2315 mindist = 0;
2316 }
2317 if (dc->type == type_border_country)
2318 {
2319 if (order < 10)
2320 {
2321 mindist = 3;
2322 }
2323 }
2324 if (dc->e->type == element_polyline)
2325 {
2326 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, e->u.polyline.width, width);
2327 }
2328 else
2329 {
2330 count = transform(dc->trans, dc->pro, di->c, pa, count, mindist, 0, NULL);
2331 }
2332
2333 switch (e->type)
2334 {
2335 case element_polygon:
2336 graphics_draw_polygon_clipped(gra, gc, pa, count);
2337 break;
2338 case element_polyline:
2339 {
2340 gc->meth.gc_set_linewidth(gc->priv, 1);
2341
2342 int poly = e->u.polyline.width > 1;
2343
2344 // detect underground streets/lines/etc ...
2345 //if ((allow_dashed) && (di->item.flags & AF_UNDERGROUND))
2346 if (di->item.flags & AF_UNDERGROUND)
2347 {
2348 poly = 2;
2349 }
2350 else if (di->item.flags & AF_BRIDGE)
2351 {
2352 poly = 3;
2353 }
2354
2355 int oneway = 0;
2356
2357 if (di->item.flags & AF_ONEWAYREV)
2358 {
2359 oneway = 2;
2360 }
2361 else if (di->item.flags & AF_ONEWAY)
2362 {
2363 oneway = 1;
2364 }
2365
2366 // -------- apply dashes -------
2367 if (e->u.polyline.dash_num > 0)
2368 {
2369 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);
2370 }
2371 // -------- apply dashes -------
2372
2373 for (i = 0; i < count; i++)
2374 {
2375 if (width[i] < 1)
2376 {
2377 width[i] = 1;
2378 }
2379 }
2380
2381 if (dc->type == type_border_country)
2382 {
2383 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway);
2384 }
2385 else
2386 {
2387 graphics_draw_polyline_clipped(gra, gc, pa, count, width, 1, poly, order, oneway);
2388 // graphics_draw_polyline_clipped(gra, gc, pa, count, width, 99, poly, order, oneway);
2389 }
2390
2391 // -------- cancel dashes -------
2392 if (e->u.polyline.dash_num > 0)
2393 {
2394 int dummy_1[1];
2395 dummy_1[0]=0;
2396 graphics_gc_set_dashes(gra, gc, e->u.polyline.width, e->u.polyline.offset, dummy_1, e->u.polyline.dash_num, order);
2397 }
2398 //if (run_type > 100) dbg(0,"gg005\n");
2399 // -------- cancel dashes -------
2400 }
2401 break;
2402 case element_circle:
2403 if (count)
2404 {
2405 if (e->u.circle.width > 1)
2406 {
2407 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
2408 }
2409
2410 graphics_draw_circle(gra, gc, pa, e->u.circle.radius);
2411
2412 if (di->label && e->text_size)
2413 {
2414 struct graphics_font *font = get_font(gra, e->text_size);
2415 struct graphics_gc *gc_background = dc->gc_background;
2416 if (!gc_background && e->u.circle.background_color.a)
2417 {
2418 gc_background = graphics_gc_new(gra);
2419 graphics_gc_set_foreground(gc_background, &e->u.circle.background_color);
2420 dc->gc_background = gc_background;
2421 }
2422 p.x = pa[0].x + 3;
2423 p.y = pa[0].y + 10;
2424
2425 if (font)
2426 {
2427 gra->meth.draw_text(gra->priv, gc->priv, gc_background ? gc_background->priv : NULL, font->priv, di->label, &p, 0x10000, 0);
2428 }
2429 else
2430 {
2431 //DBG dbg(0, "Failed to get font with size %d\n", e->text_size);
2432 }
2433 }
2434 }
2435 break;
2436 case element_text:
2437 if (count && di->label)
2438 {
2439 //if (run_type > 100) dbg(0,"gg006\n");
2440
2441 struct graphics_font *font = get_font(gra, e->text_size);
2442 struct graphics_gc *gc_background = dc->gc_background;
2443
2444 if (!gc_background && e->u.text.background_color.a)
2445 {
2446 gc_background = graphics_gc_new(gra);
2447 graphics_gc_set_foreground(gc_background, &e->u.text.background_color);
2448 dc->gc_background = gc_background;
2449 }
2450
2451 if (font)
2452 {
2453 label_line(gra, gc, gc_background, font, pa, count, di->label);
2454 }
2455 else
2456 {
2457 //DBG dbg(0, "Failed to get font with size %d\n", e->text_size);
2458 }
2459 }
2460 break;
2461 case element_icon:
2462 if (count)
2463 {
2464 if (!img || item_is_custom_poi(di->item))
2465 {
2466 if (item_is_custom_poi(di->item))
2467 {
2468 char *icon;
2469 char *src;
2470 if (img)
2471 {
2472 graphics_image_free(dc->gra, img);
2473 }
2474 src = e->u.icon.src;
2475 if (!src || !src[0])
2476 {
2477 src = "%s";
2478 }
2479 icon = g_strdup_printf(src, di->label + strlen(di->label) + 1);
2480 path = graphics_icon_path(icon);
2481 g_free(icon);
2482 }
2483 else
2484 {
2485 path = graphics_icon_path(e->u.icon.src);
2486 }
2487 img = graphics_image_new_scaled_rotated(gra, path, e->u.icon.width, e->u.icon.height, e->u.icon.rotation);
2488 if (img)
2489 {
2490 dc->img = img;
2491 }
2492 else
2493 {
2494 // missing icon // dbg(0, "-- ICON MISSING -- failed to load icon '%s'\n", path);
2495 }
2496 g_free(path);
2497 }
2498
2499 if (img)
2500 {
2501 p.x = pa[0].x - img->hot.x;
2502 p.y = pa[0].y - img->hot.y;
2503 //dbg(0, "icon: '%s'\n", path);
2504 //dbg(0,"hot: %d %d\n", img->hot.x, img->hot.y);
2505 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
2506 }
2507 }
2508 break;
2509 case element_image:
2510 //dbg(0, "image: '%s'\n", di->label);
2511 if (gra->meth.draw_image_warp)
2512 gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, pa, count, di->label);
2513 else
2514 {
2515 // dbg(0,"draw_image_warp not supported by graphics driver drawing '%s'\n",di->label);
2516 }
2517 break;
2518 case element_arrows:
2519 display_draw_arrows(gra, gc, pa, count);
2520 break;
2521 default:
2522 printf("Unhandled element type %d\n", e->type);
2523
2524 }
2525 di = di->next;
2526 }
2527
2528 //if (run_type > 100) dbg(0,"gg099\n");
2529
2530 }
2531 /**
2532 * FIXME
2533 * @param <>
2534 * @returns <>
2535 * @author Martin Schaller (04/2008)
2536 */
2537 static void xdisplay_draw_elements(struct graphics *gra, struct displaylist *display_list, struct itemgra *itm, int run_type)
2538 {
2539 // dbg(0,"Enter\n");
2540
2541 struct element *e;
2542 GList *es, *types;
2543 struct display_context *dc = &display_list->dc;
2544 struct hash_entry *entry;
2545 int draw_it = 1;
2546
2547 #ifdef NAVIT_MEASURE_TIME_DEBUG
2548 clock_t s_ = debug_measure_start();
2549 #endif
2550
2551 es = itm->elements;
2552 while (es)
2553 {
2554 //dbg(0,"*es\n");
2555 e = es->data;
2556 dc->e = e;
2557 types = itm->type;
2558 while (types)
2559 {
2560 draw_it = 1;
2561
2562 dc->type = GPOINTER_TO_INT(types->data);
2563 //dbg(0,"**type=%d\n", dc->type);
2564
2565 if (dc->type == type_poly_water_from_relations)
2566 {
2567 // ok "poly_water_from_relations" is found, now what?
2568 if (enable_water_from_relations == 0)
2569 {
2570 draw_it = 0;
2571 }
2572 }
2573
2574 if (draw_it == 1)
2575 {
2576 entry = get_hash_entry(display_list, dc->type);
2577 if (entry && entry->di)
2578 {
2579 // dbg(0,"++type=%s\n", item_to_name(dc->type));
2580 //if (!strcmp(item_to_name(dc->type), "border_country"))
2581 //{
2582 // displayitem_draw(entry->di, NULL, dc, display_list->order, 1, 101);
2583 //}
2584 //else
2585 //{
2586 displayitem_draw(entry->di, NULL, dc, display_list->order, 1, run_type);
2587 //}
2588 // dbg(0,"**+gc free\n");
2589 display_context_free(dc);
2590 }
2591 }
2592 types = g_list_next(types);
2593 draw_it = 1;
2594 }
2595 es = g_list_next(es);
2596 }
2597
2598 #ifdef NAVIT_MEASURE_TIME_DEBUG
2599 debug_mrp("xdisplay_draw_elements:", debug_measure_end(s_));
2600 #endif
2601 }
2602
2603 void graphics_draw_itemgra(struct graphics *gra, struct itemgra *itm, struct transformation *t, char *label)
2604 {
2605 ////DBG dbg(0,"ooo enter ooo\n");
2606
2607 // HINT: seems to only be called from vehicle.c (draw the vehicle on screen)
2608
2609 GList *es;
2610 struct display_context dc;
2611 int max_coord = 32;
2612 char *buffer = g_alloca(sizeof(struct displayitem) + max_coord * sizeof(struct coord));
2613 struct displayitem *di = (struct displayitem *) buffer;
2614 es = itm->elements;
2615 di->item.type = type_none;
2616 di->item.id_hi = 0;
2617 di->item.id_lo = 0;
2618 di->item.map = NULL;
2619 di->label = label;
2620 dc.gra = gra;
2621 dc.gc = NULL;
2622 dc.gc_background = NULL;
2623 dc.img = NULL;
2624 dc.pro = projection_screen;
2625 dc.mindist = 0;
2626 dc.trans = t;
2627 dc.type = type_none;
2628 dc.maxlen = max_coord;
2629 while (es)
2630 {
2631 struct element *e = es->data;
2632 if (e->coord_count)
2633 {
2634 if (e->coord_count > max_coord)
2635 {
2636 //DBG dbg(0, "maximum number of coords reached: %d > %d\n", e->coord_count, max_coord);
2637 di->count = max_coord;
2638 }
2639 else
2640 {
2641 di->count = e->coord_count;
2642 }
2643 memcpy(di->c, e->coord, di->count * sizeof(struct coord));
2644 }
2645 else
2646 {
2647 di->c[0].x = 0;
2648 di->c[0].y = 0;
2649 di->count = 1;
2650 }
2651 dc.e = e;
2652 di->next = NULL;
2653 displayitem_draw(di, NULL, &dc, transform_get_scale(t), 0, 99);
2654 display_context_free(&dc);
2655 es = g_list_next(es);
2656 }
2657 }
2658
2659 /**
2660 * FIXME
2661 * @param <>
2662 * @returns <>
2663 * @author Martin Schaller (04/2008)
2664 */
2665 static void xdisplay_draw_layer(struct displaylist *display_list, struct graphics *gra, struct layer *lay, int order)
2666 {
2667 //DBG dbg(0,"ooo enter ooo\n");
2668
2669 GList *itms;
2670 struct itemgra *itm;
2671
2672 int run_type = 0; // 99 -> normal
2673 // 1 -> normal streets (except tunnels and bridges)
2674 // 2 -> tunnel
2675 // 3 -> bridge
2676
2677 int send_refresh = 0;
2678
2679 int order_corrected = order + shift_order;
2680 if (order_corrected < limit_order_corrected)
2681 {
2682 order_corrected = limit_order_corrected;
2683 }
2684
2685 int order_corrected_2 = order + shift_order;
2686 if (order < 0)
2687 {
2688 order_corrected_2 = 0;
2689 }
2690
2691 //dbg(0,"layer name=%s\n", lay->name);
2692
2693 if ((strncmp("streets_1", lay->name, 9) == 0))
2694 {
2695 //dbg(0,"MT:7.3.1 - tunnel start\n");
2696 //draw_lines_count_2 = 0;
2697 //draw_lines_count_3 = 0;
2698 //draw_lines_count_4 = 0;
2699
2700 send_refresh = 1;
2701
2702 run_type = 2;
2703 itms = lay->itemgras;
2704 while (itms)
2705 {
2706 // stop drawing is requested
2707 if (cancel_drawing_global == 1)
2708 {
2709 //DBG dbg(0, "** STOP MD 002 **\n");
2710 break;
2711 }
2712
2713 itm = itms->data;
2714 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2715 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2716 {
2717 xdisplay_draw_elements(gra, display_list, itm, run_type);
2718 }
2719 itms = g_list_next(itms);
2720 }
2721
2722 //dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2723 //dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2724 //dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2725 //draw_lines_count_2 = 0;
2726 //draw_lines_count_3 = 0;
2727 //draw_lines_count_4 = 0;
2728 //dbg(0,"MT:7.3.2 - streets start\n");
2729
2730 run_type = 1;
2731 itms = lay->itemgras;
2732 while (itms)
2733 {
2734 // stop drawing is requested
2735 if (cancel_drawing_global == 1)
2736 {
2737 //DBG dbg(0, "** STOP MD 002 **\n");
2738 break;
2739 }
2740
2741 itm = itms->data;
2742 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2743 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2744 {
2745 xdisplay_draw_elements(gra, display_list, itm, run_type);
2746 }
2747 itms = g_list_next(itms);
2748 }
2749
2750 /*
2751 dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2752 dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2753 dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2754 draw_lines_count_2 = 0;
2755 draw_lines_count_3 = 0;
2756 draw_lines_count_4 = 0;
2757 dbg(0,"MT:7.3.3 - bridges start\n");
2758 */
2759
2760 run_type = 3;
2761 itms = lay->itemgras;
2762 while (itms)
2763 {
2764 // stop drawing is requested
2765 if (cancel_drawing_global == 1)
2766 {
2767 //DBG dbg(0, "** STOP MD 002 **\n");
2768 break;
2769 }
2770
2771 itm = itms->data;
2772 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2773 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2774 {
2775 xdisplay_draw_elements(gra, display_list, itm, run_type);
2776 }
2777 itms = g_list_next(itms);
2778 }
2779
2780 /*
2781 dbg(0,"lines count2=%lld\n", draw_lines_count_2);
2782 dbg(0,"lines count3=%lld\n", draw_lines_count_3);
2783 dbg(0,"lines count4=%lld\n", draw_lines_count_4);
2784 draw_lines_count_2 = 0;
2785 draw_lines_count_3 = 0;
2786 draw_lines_count_4 = 0;
2787 dbg(0,"MT:7.3.4 - ready\n");
2788 */
2789
2790 }
2791 else
2792 {
2793 run_type = 99;
2794 itms = lay->itemgras;
2795 while (itms)
2796 {
2797 // stop drawing is requested
2798 if (cancel_drawing_global == 1)
2799 {
2800 //DBG dbg(0, "** STOP MD 002 **\n");
2801 break;
2802 }
2803
2804 itm = itms->data;
2805 //if (order_corrected >= itm->order.min && order_corrected <= itm->order.max)
2806 if (order_corrected_2 >= itm->order.min && order_corrected_2 <= itm->order.max)
2807 {
2808 xdisplay_draw_elements(gra, display_list, itm, run_type);
2809 }
2810 itms = g_list_next(itms);
2811 }
2812 }
2813
2814 //if (strncmp("streets__tunnel", lay->name, 15) == 0)
2815 //{
2816 //}
2817 //else if (strncmp("streets__bridge", lay->name, 15) == 0)
2818 //{
2819 //}
2820
2821 // dirty hack to draw "waypoint(s)" ---------------------------
2822 if (strncmp("Internal", lay->name, 8) == 0)
2823 {
2824 if (global_navit->route)
2825 {
2826 if (global_navit->destination_valid == 1)
2827 {
2828 int count_ = 0;
2829 int curr_ = 0;
2830 count_ = g_list_length(global_navit->route->destinations);
2831 if (count_ > 1)
2832 {
2833 if (!global_img_waypoint)
2834 {
2835 char *path2;
2836 path2 = graphics_icon_path("nav_waypoint_bk_center.png");
2837 global_img_waypoint = graphics_image_new_scaled_rotated(gra, path2, 59, 59, 0);
2838 g_free(path2);
2839 }
2840
2841 struct point p2;
2842 struct coord pc77;
2843 GList *ldest = global_navit->route->destinations;
2844 while (ldest)
2845 {
2846 curr_++;
2847 if (curr_ < count_)
2848 {
2849 struct route_info *dst = ldest->data;
2850 pc77.x = dst->c.x;
2851 pc77.y = dst->c.y;
2852 //dbg(0, "draw1 curr=%d x y: %d %d\n", curr_, dst->c.x, dst->c.y);
2853 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2854 transform(global_navit->trans, pro, &pc77, &p2, 1, 0, 0, NULL);
2855 // transform(global_navit->trans, projection_mg, &pc77, &p2, 1, 0, 0, NULL);
2856 p2.x = p2.x - global_img_waypoint->hot.x; // hot = 29
2857 p2.y = p2.y - global_img_waypoint->hot.y; // hot = 29
2858 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p2, global_img_waypoint->priv);
2859 }
2860 // next dest. / waypoint
2861 ldest=g_list_next(ldest);
2862 }
2863 }
2864 }
2865 }
2866 }
2867 // dirty hack to draw "waypoint(s)" ---------------------------
2868
2869
2870 if (send_refresh == 1)
2871 {
2872 // dummy "ready" signal ------------------------------------------
2873 dbg(0,"dummy \"ready\" signal (layers)\n");
2874 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 96);
2875 // dummy "ready" signal ------------------------------------------
2876 }
2877
2878 }
2879
2880 /**
2881 * FIXME
2882 * @param <>
2883 * @returns <>
2884 * @author Martin Schaller (04/2008)
2885 */
2886 static void xdisplay_draw(struct displaylist *display_list, struct graphics *gra, struct layout *l, int order)
2887 {
2888 ////DBG dbg(0,"ooo enter ooo\n");
2889
2890 GList *lays;
2891 struct layer *lay;
2892
2893 int draw_vector_map = 1;
2894
2895 // if zoomed out too much then use prerendered map tiles
2896 if (display_list->order < ORDER_USE_PRERENDERED_MAP)
2897 {
2898 draw_vector_map = 0;
2899 }
2900
2901 if (!draw_vector_map)
2902 {
2903 // draw prerendered big mapimage --- HERE ---
2904 struct transformation *t;
2905 t = display_list->dc.trans;
2906 struct coord *cp;
2907 cp = transform_get_center(t);
2908 struct attr attr;
2909 struct config
2910 {
2911 struct attr **attrs;
2912 struct callback_list *cbl;
2913 }*config;
2914 struct point p;
2915 int valid = 0;
2916 if (global_navit)
2917 {
2918 if ((global_navit->vehicle) && (global_navit->vehicle->vehicle))
2919 {
2920 //int a, s;
2921 //struct point pnt2;
2922 //vehicle_get_cursor_data(global_navit->vehicle->vehicle, &pnt2, &a, &s);
2923
2924 //struct attr pos_attr;
2925 //if (vehicle_get_attr(global_navit->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL))
2926 //{
2927 // ////DBG dbg(0,"1 lat=%f, lng=%f\n",pos_attr.u.coord_geo->lat,pos_attr.u.coord_geo->lng);
2928 //}
2929
2930 valid = 1;
2931 }
2932 }
2933
2934 struct coord *c;
2935 c = &(t->map_center);
2936
2937 enum projection pro = transform_get_projection(global_navit->trans_cursor);
2938 struct coord_geo g22;
2939 struct coord *c22;
2940 struct point mcenter_pnt;
2941 c22 = &(t->map_center);
2942 transform_to_geo(projection_mg, c22, &g22);
2943 transform(global_navit->trans, pro, c22, &mcenter_pnt, 1, 0, 0, NULL);
2944
2945 struct coord c99;
2946 struct coord_geo g99;
2947 struct point cursor_pnt;
2948 struct point p99;
2949 long my_scale;
2950
2951 my_scale = transform_get_scale(global_navit->trans);
2952
2953 g99.lat = 0.0;
2954 g99.lng = 0.0;
2955 // g99.lat = 80.0;
2956 // g99.lng = -174.0;
2957 transform_from_geo(pro, &g99, &c99);
2958 transform(global_navit->trans, pro, &c99, &cursor_pnt, 1, 0, 0, NULL);
2959
2960 // now really draw it
2961 struct graphics *gra22 = display_list->dc.gra;
2962 struct graphics_gc *gc22 = display_list->dc.gc;
2963 if (!gc22)
2964 {
2965 gc22 = graphics_gc_new(gra22);
2966 }
2967 // 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);
2968 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);
2969 }
2970
2971 // reset value; --> not sure here, maybe it should NOT be reset here!!!???
2972 cancel_drawing_global = 0;
2973
2974 lays = l->layers;
2975 while (lays)
2976 {
2977 lay = lays->data;
2978 if (lay->active)
2979 {
2980 xdisplay_draw_layer(display_list, gra, lay, order);
2981 }
2982 lays = g_list_next(lays);
2983
2984 // stop drawing is requested
2985 if (cancel_drawing_global == 1)
2986 {
2987 break;
2988 }
2989 }
2990
2991 // reset value;
2992 cancel_drawing_global = 0;
2993
2994 // dummy "start" signal ------------------------------------------
2995 dbg(0,"dummy \"start\" signal\n");
2996 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 97);
2997 // dummy "start" signal ------------------------------------------
2998
2999
3000 // dummy "ready" signal ------------------------------------------
3001 dbg(0,"dummy \"ready\" signal\n");
3002 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 99);
3003 // dummy "ready" signal ------------------------------------------
3004
3005
3006
3007 #ifdef HAVE_API_ANDROID
3008 android_return_generic_int(2, 1);
3009 #endif
3010
3011 }
3012
3013 /**
3014 * FIXME
3015 * @param <>
3016 * @returns <>
3017 * @author Martin Schaller (04/2008)
3018 */
3019 extern void *route_selection;
3020
3021 static void displaylist_update_layers(struct displaylist *displaylist, GList *layers, int order)
3022 {
3023 ////DBG dbg(0,"ooo enter ooo\n");
3024
3025 int order_corrected = order + shift_order;
3026 //int saved=displaylist->order;
3027 if (order < limit_order_corrected)
3028 {
3029 order_corrected = limit_order_corrected;
3030 // displaylist->order=0;
3031 }
3032
3033 while (layers)
3034 {
3035 struct layer *layer = layers->data;
3036 GList *itemgras = layer->itemgras;
3037 while (itemgras)
3038 {
3039 struct itemgra *itemgra = itemgras->data;
3040 GList *types = itemgra->type;
3041 if (itemgra->order.min <= order_corrected && itemgra->order.max >= order_corrected)
3042 {
3043 while (types)
3044 {
3045 enum item_type type = (enum item_type) types->data;
3046 set_hash_entry(displaylist, type);
3047 types = g_list_next(types);
3048 }
3049 }
3050 itemgras = g_list_next(itemgras);
3051 }
3052 layers = g_list_next(layers);
3053 }
3054 // displaylist->order=saved;
3055 }
3056
3057 static void displaylist_update_hash(struct displaylist *displaylist)
3058 {
3059 ////DBG dbg(0,"ooo enter ooo\n");
3060
3061 displaylist->max_offset = 0;
3062 clear_hash(displaylist);
3063 displaylist_update_layers(displaylist, displaylist->layout->layers, displaylist->order);
3064 // dbg(1, "max offset %d\n", displaylist->max_offset);
3065 }
3066
3067 static void do_draw(struct displaylist *displaylist, int cancel, int flags)
3068 {
3069
3070 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3071 dbg(0,"+#+:enter\n");
3072 #endif
3073
3074 //dbg(0,"enter\n");
3075
3076 #ifdef HAVE_API_ANDROID
3077 // ---- disable map view -----
3078 // ---- disable map view -----
3079 // ---- disable map view -----
3080 if (disable_map_drawing == 1)
3081 {
3082 android_return_generic_int(2, 0);
3083
3084 //dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3085 displaylist->busy = 0;
3086
3087 //dbg(0,"return 001\n");
3088 return;
3089 }
3090 // ---- disable map view -----
3091 // ---- disable map view -----
3092 // ---- disable map view -----
3093 #endif
3094
3095
3096
3097 clock_t s_;
3098 #ifdef NAVIT_MEASURE_TIME_DEBUG
3099 s_ = debug_measure_start();
3100 #endif
3101
3102
3103 struct item *item;
3104 int count, max = displaylist->dc.maxlen, workload = 0;
3105 struct coord *ca = g_alloca(sizeof(struct coord) * max);
3106 struct attr attr, attr2;
3107 enum projection pro;
3108 int draw_vector_map = 1; // do we draw the vecotor map, or not? 0=false, 1=true
3109 int mapset_counter = 0;
3110 int mapset_need_draw = 0;
3111
3112 // dbg(0,"ooo enter ooo %d\n",displaylist->order);
3113
3114 int order_corrected = displaylist->order + shift_order;
3115 int saved = displaylist->order;
3116 if (order_corrected < limit_order_corrected)
3117 {
3118 order_corrected = limit_order_corrected;
3119 }
3120
3121 if (displaylist->order != displaylist->order_hashed || displaylist->layout != displaylist->layout_hashed)
3122 {
3123 displaylist_update_hash(displaylist);
3124 displaylist->order_hashed = displaylist->order;
3125 displaylist->layout_hashed = displaylist->layout;
3126 }
3127
3128 pro = transform_get_projection(displaylist->dc.trans);
3129
3130 // if zoomed out too much then use prerendered map tiles
3131 if (displaylist->order_hashed < ORDER_USE_PRERENDERED_MAP)
3132 {
3133 draw_vector_map = 0;
3134 }
3135
3136 displaylist->order = order_corrected;
3137
3138 //DBG dbg(0, "XXXXXYYYYYYY Draw: 003\n");
3139
3140 // reset value;
3141 cancel_drawing_global = 0;
3142
3143 while (!cancel)
3144 {
3145 if (!displaylist->msh)
3146 {
3147 displaylist->msh = mapset_open(displaylist->ms);
3148 }
3149
3150 if (!displaylist->m)
3151 {
3152 displaylist->m = mapset_next(displaylist->msh, 1);
3153 if (!displaylist->m)
3154 {
3155 mapset_close(displaylist->msh);
3156 displaylist->msh = NULL;
3157 break;
3158 }
3159
3160 mapset_counter++;
3161 mapset_need_draw = 1;
3162 struct attr map_name_attr;
3163
3164 if (map_get_attr(displaylist->m, attr_name, &map_name_attr, NULL))
3165 {
3166 //dbg(0,"#+* start reading map file #+*=%s\n",map_name_attr.u.str);
3167 if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0)
3168 {
3169 if (strncmp("_ms_sdcard_map:/sdcard/zanavi/maps/borders.bin", map_name_attr.u.str, 41) == 0)
3170 {
3171 // if its the countryborder map, always draw it
3172 mapset_need_draw = 0; // now dont even draw border map!!
3173 }
3174 else
3175 {
3176 // if its an sdcard street map, don't draw it
3177 mapset_need_draw = 0;
3178 }
3179 }
3180 }
3181
3182 ////DBG dbg(0,"---------==============>>>>>>>>>> ***** %d ****",mapset_counter);
3183
3184 displaylist->dc.pro = map_projection(displaylist->m);
3185 displaylist->conv = map_requires_conversion(displaylist->m);
3186 if (route_selection)
3187 {
3188 displaylist->sel = route_selection;
3189 }
3190 else
3191 {
3192 displaylist->sel = transform_get_selection(displaylist->dc.trans, displaylist->dc.pro, displaylist->order);
3193 }
3194 displaylist->mr = map_rect_new(displaylist->m, displaylist->sel);
3195 }
3196
3197 if (displaylist->mr)
3198 {
3199 // draw vector map, or not?
3200 //dbg(0,"draw_vector_map=%d mapset_need_draw=%d\n", draw_vector_map, mapset_need_draw);
3201 if ((draw_vector_map) || (mapset_need_draw == 1))
3202 {
3203
3204 //dbg(0, "XXXXXYYYYYYY Draw: A.01\n");
3205
3206
3207 // ------ READ all items in this map rectangle ---------
3208 // ------ READ all items in this map rectangle ---------
3209 // ------ READ all items in this map rectangle ---------
3210 // ------ READ all items in this map rectangle ---------
3211 // ------ READ all items in this map rectangle ---------
3212 //dbg(0,"#+* start reading map file #+*\n");
3213 int _item_counter_ = 0;
3214 while ((item = map_rect_get_item(displaylist->mr)))
3215 {
3216 _item_counter_++;
3217
3218 int label_count = 0;
3219 char *labels[2];
3220 struct hash_entry *entry;
3221
3222 if (cancel_drawing_global == 1)
3223 {
3224 // stop drawing map is requested
3225 //DBG dbg(0, "** STOP MD 001 **\n");
3226 break;
3227 }
3228
3229 if (item == &busy_item)
3230 {
3231 if (displaylist->workload)
3232 {
3233 // restore order :-)
3234 displaylist->order = saved;
3235
3236 //dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3237 displaylist->busy = 0;
3238
3239 //dbg(0,"return 002\n");
3240 return;
3241 }
3242 else
3243 {
3244 continue;
3245 }
3246 }
3247
3248 entry = get_hash_entry(displaylist, item->type);
3249
3250 //dbg(0, "XXXXXYYYYYYY Draw: A.item1 %p %i\n", entry, item->type);
3251
3252 // DEBUG -------- zoffzoff
3253 // DEBUG -------- zoffzoff
3254 // DEBUG -------- zoffzoff
3255 //item_dump_attr_stdout(item, displaylist->m);
3256 // DEBUG -------- zoffzoff
3257 // DEBUG -------- zoffzoff
3258 // DEBUG -------- zoffzoff
3259
3260 if (!entry)
3261 {
3262 continue;
3263 }
3264
3265 count = item_coord_get_within_selection(item, ca, item->type < type_line ? 1 : max, displaylist->sel);
3266
3267 if (!count)
3268 {
3269 continue;
3270 }
3271
3272 //dbg(0, "XXXXXYYYYYYY Draw: A.item2\n");
3273
3274 if (displaylist->dc.pro != pro)
3275 {
3276 transform_from_to_count(ca, displaylist->dc.pro, ca, pro, count);
3277 }
3278
3279 if (count == max)
3280 {
3281 //DBG dbg(0,"point count overflow %d for %s "ITEM_ID_FMT"\n", count,item_to_name(item->type),ITEM_ID_ARGS(*item));
3282 displaylist->dc.maxlen = max * 2;
3283 }
3284
3285 if (item_is_custom_poi(*item))
3286 {
3287 if (item_attr_get(item, attr_icon_src, &attr2))
3288 labels[1] = map_convert_string(displaylist->m, attr2.u.str);
3289 else
3290 labels[1] = NULL;
3291 label_count = 2;
3292 }
3293 else
3294 {
3295 labels[1] = NULL;
3296 label_count = 0;
3297 }
3298
3299 if (item_attr_get(item, attr_label, &attr))
3300 {
3301 labels[0] = attr.u.str;
3302 if (!label_count)
3303 {
3304 label_count = 2;
3305 }
3306 }
3307 else
3308 {
3309 labels[0] = NULL;
3310 }
3311
3312 // DEBUG -------- zoffzoff
3313 // DEBUG -------- zoffzoff
3314 // DEBUG -------- zoffzoff
3315 // item_dump_attr_stdout(item, displaylist->m);
3316 // DEBUG -------- zoffzoff
3317 // DEBUG -------- zoffzoff
3318 // DEBUG -------- zoffzoff
3319
3320 struct attr attr_77;
3321 if (item_attr_get(item, attr_flags, &attr_77))
3322 {
3323 // dbg(0,"uuuuuuuuuuuuu %s uuuuu %d\n",item_to_name(item->type), attr_77.u.num);
3324 item->flags = attr_77.u.num;
3325 }
3326 else
3327 {
3328 item->flags = 0;
3329 }
3330
3331 //struct attr *attr88;
3332 //if (item_attr_get(item, attr_flags, &attr88))
3333 //{
3334 ////DBG dbg(0,"item flags=%d\n",attr88->u.num);
3335 //}
3336 //attr88=NULL;
3337
3338
3339 /*
3340 if (item->flags & AF_UNDERGROUND)
3341 {
3342 dbg(0,"is UNDERGROUND\n");
3343 }
3344 else if (item->flags & AF_BRIDGE)
3345 {
3346 dbg(0,"is BRIDGE\n");
3347 }
3348 */
3349
3350 if (displaylist->conv && label_count)
3351 {
3352 labels[0] = map_convert_string(displaylist->m, labels[0]);
3353 display_add(entry, item, count, ca, labels, label_count);
3354 map_convert_free(labels[0]);
3355 }
3356 else
3357 {
3358 display_add(entry, item, count, ca, labels, label_count);
3359 }
3360
3361 if (labels[1])
3362 {
3363 map_convert_free(labels[1]);
3364 }
3365
3366 //workload++;
3367 /*
3368 if (workload == displaylist->workload)
3369 {
3370 // restore order :-)
3371 displaylist->order = saved;
3372 // reset value;
3373 cancel_drawing_global = 0;
3374
3375 dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3376 displaylist->busy = 0;
3377
3378 dbg(0,"return 003\n");
3379 return;
3380 }
3381 */
3382 } // while item=map_rect_get_item
3383 // ------ READ all items in this map rectangle ---------
3384 // ------ READ all items in this map rectangle ---------
3385 // ------ READ all items in this map rectangle ---------
3386 // ------ READ all items in this map rectangle ---------
3387 // ------ READ all items in this map rectangle ---------
3388
3389
3390 ////DBG dbg(0, "XXXXXYYYYYYY Draw: A.02\n");
3391
3392 map_rect_destroy(displaylist->mr);
3393 }
3394 }
3395
3396 if (!route_selection)
3397 {
3398 map_selection_destroy(displaylist->sel);
3399 }
3400
3401 displaylist->mr = NULL;
3402 displaylist->sel = NULL;
3403 displaylist->m = NULL;
3404 } // while ----
3405
3406
3407
3408 #ifdef NAVIT_MEASURE_TIME_DEBUG
3409 debug_mrp("do_draw:load", debug_measure_end(s_));
3410 #endif
3411 s_ = debug_measure_start();
3412
3413
3414 // remove the "wait" screen
3415 #ifdef HAVE_API_ANDROID
3416 android_return_generic_int(2, 0);
3417 #endif
3418
3419
3420 //DBG dbg(0, "XXXXXYYYYYYY Draw: 004\n");
3421
3422 // reset value;
3423 cancel_drawing_global = 0;
3424
3425 // restore order :-)
3426 displaylist->order = saved;
3427
3428 // profile(1,"process_selection\n");
3429
3430 if (displaylist->idle_ev)
3431 {
3432 event_remove_idle(displaylist->idle_ev);
3433 }
3434
3435 displaylist->idle_ev = NULL;
3436 callback_destroy(displaylist->idle_cb);
3437 displaylist->idle_cb = NULL;
3438 //dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3439 //displaylist->busy = 0;
3440
3441 // graphics_process_selection(displaylist->dc.gra, displaylist);
3442
3443 //profile(1, "draw\n");
3444
3445 //DBG dbg(0, "XXXXXYYYYYYY Draw: 005\n");
3446
3447 if (!cancel)
3448 {
3449 int flags2 = flags;
3450 if (!(flags2 & 2))
3451 {
3452 if (!draw_vector_map)
3453 {
3454 // dont clean bg of screen when drawing prerendered tiles
3455 flags2 = flags2 + 2;
3456 }
3457 }
3458 //DBG dbg(0,"call graphics_displaylist_draw 3")
3459 //dbg(0,"# MT:002 #\n");
3460 graphics_displaylist_draw(displaylist->dc.gra, displaylist, displaylist->dc.trans, displaylist->layout, flags2);
3461 //dbg(0,"# MT:003 #\n");
3462 }
3463
3464 #ifdef NAVIT_MEASURE_TIME_DEBUG
3465 debug_mrp("do_draw:draw", debug_measure_end(s_));
3466 #endif
3467
3468 #ifdef HAVE_API_ANDROID
3469 if (cur_mapdraw_time_index < 11)
3470 {
3471 mapdraw_time[cur_mapdraw_time_index] = debug_measure_end_tsecs(s_);
3472 // dbg(0,"maptime: %d\n", mapdraw_time[cur_mapdraw_time_index]);
3473 cur_mapdraw_time_index++;
3474 }
3475
3476 if (cur_mapdraw_time_index > 10)
3477 {
3478 cur_mapdraw_time_index = 0;
3479 int jk;
3480 int mean_time = 0;
3481 for (jk=0;jk<11;jk++)
3482 {
3483 mean_time = mean_time + mapdraw_time[jk];
3484 }
3485 android_return_generic_int(6, (int)((float)mean_time / (float)10));
3486 }
3487 #endif
3488
3489
3490 //dbg(0,"set:0:displaylist->busy=%d\n",displaylist->busy);
3491 displaylist->busy = 0;
3492
3493 //DBG dbg(0, "XXXXXYYYYYYY Draw: 006\n");
3494
3495 map_rect_destroy(displaylist->mr);
3496 if (!route_selection)
3497 {
3498 map_selection_destroy(displaylist->sel);
3499 }
3500 mapset_close(displaylist->msh);
3501 displaylist->mr = NULL;
3502 displaylist->sel = NULL;
3503 displaylist->m = NULL;
3504 displaylist->msh = NULL;
3505 //profile(1, "callback\n");
3506 callback_call_1(displaylist->cb, cancel);
3507 //profile(0, "end\n");
3508
3509 //dbg(0,"leave\n");
3510
3511 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3512 dbg(0,"+#+:leave\n");
3513 #endif
3514
3515 }
3516
3517 /**
3518 * FIXME
3519 * @param <>
3520 * @returns <>
3521 * @author Martin Schaller (04/2008)
3522 */
3523 void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, struct layout *l, int flags)
3524 {
3525 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3526 dbg(0,"+#+:enter\n");
3527 #endif
3528
3529 // dbg(0,"ooo enter ooo flags=%d\n", flags);
3530
3531 int order = transform_get_order(trans);
3532 displaylist->dc.trans = trans;
3533 displaylist->dc.gra = gra;
3534
3535
3536 // *********DISABLED*******
3537 // *********DISABLED*******
3538 // *********DISABLED*******
3539 // set min. distanct of 2 points on line at which a point will be left out when zoomed out too much!!
3540 // *********DISABLED******* displaylist->dc.mindist = transform_get_scale(trans) / 2;
3541 //dbg(0,"mindist would be:%d\n", (int)(transform_get_scale(trans) / 2));
3542 displaylist->dc.mindist = 0;
3543 if (order < 13)
3544 {
3545 displaylist->dc.mindist = transform_get_scale(trans);
3546 }
3547 // *********DISABLED*******
3548 // *********DISABLED*******
3549 // *********DISABLED*******
3550
3551
3552
3553 // FIXME find a better place to set the background color
3554 if (l)
3555 {
3556 graphics_gc_set_background(gra->gc[0], &l->color);
3557 graphics_gc_set_foreground(gra->gc[0], &l->color);
3558 gra->default_font = g_strdup(l->font);
3559 }
3560 graphics_background_gc(gra, gra->gc[0]);
3561 if (flags & 1)
3562 {
3563 // calls -> navit.c navit_predraw --> draw all vehicles
3564 callback_list_call_attr_0(gra->cbl, attr_predraw);
3565 }
3566 gra->meth.draw_mode(gra->priv, (flags & 8) ? draw_mode_begin_clear : draw_mode_begin);
3567 if (!(flags & 2))
3568 {
3569 // clear the gfx object pipeline ------------------------------
3570 dbg(0,"clear the gfx object pipeline\n");
3571 gra->meth.draw_lines4(gra->priv, NULL, NULL, NULL, 1, 1, 98);
3572
3573 // clear the display/screen/whatever here
3574 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);
3575 }
3576 if (l)
3577 {
3578 // draw the mapitems
3579 // dbg(0,"o , l->d = %d , %d\n",order,l->order_delta);
3580 xdisplay_draw(displaylist, gra, l, order + l->order_delta);
3581 }
3582 if (flags & 1)
3583 {
3584 callback_list_call_attr_0(gra->cbl, attr_postdraw);
3585 }
3586 if (!(flags & 4))
3587 {
3588 gra->meth.draw_mode(gra->priv, draw_mode_end);
3589 }
3590
3591 #ifdef NAVIT_FUNC_CALLS_DEBUG_PRINT
3592 dbg(0,"+#+:leave\n");
3593 #endif
3594
3595 }
3596
3597 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)
3598 {
3599 int order = transform_get_order(trans);
3600
3601 //dbg(0,"enter displaylist->busy=%d\n",displaylist->busy);
3602 //dbg(0,"async=%d\n",async);
3603 if (displaylist->busy)
3604 {
3605 if (async == 1)
3606 {
3607 //dbg(0,"**draw 1.a\n");
3608 return;
3609 }
3610 ///dbg(0,"**draw 1\n");
3611 return;
3612 //do_draw(displaylist, 1, flags);
3613 }
3614 xdisplay_free(displaylist);
3615
3616 displaylist->dc.gra = gra;
3617 displaylist->ms = mapset;
3618 displaylist->dc.trans = trans;
3619 displaylist->workload = async ? 100 : 0;
3620 displaylist->cb = cb;
3621 displaylist->seq++;
3622
3623 if (l)
3624 {
3625 order += l->order_delta;
3626 }
3627 displaylist->order = order;
3628 //dbg(0,"set:1:displaylist->busy=%d\n",displaylist->busy);
3629 displaylist->busy = 1;
3630 displaylist->layout = l;
3631
3632
3633 // ---------- DISABLED ------ no more async!!
3634 /*
3635 if (async)
3636 {
3637 //DBG dbg(0,"§§async");
3638 if (!displaylist->idle_cb)
3639 {
3640 //DBG dbg(0,"§§async --> callback");
3641 displaylist->idle_cb = callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3642 }
3643 //DBG dbg(0,"§§async --> add idle");
3644 displaylist->idle_ev = event_add_idle(50, displaylist->idle_cb);
3645 }
3646 else
3647 {
3648 //DBG dbg(0,"@@sync");
3649 do_draw(displaylist, 0, flags);
3650 }
3651 */
3652
3653
3654 if (async)
3655 {
3656 if (! displaylist->idle_cb)
3657 {
3658 //dbg(0,"**draw 2.b1\n");
3659 displaylist->idle_cb=callback_new_3(callback_cast(do_draw), displaylist, 0, flags);
3660 //dbg(0,"**draw 2.b2\n");
3661 }
3662 //dbg(0,"**draw 2.b3\n");
3663 displaylist->idle_ev = event_add_idle(1000, displaylist->idle_cb);
3664 dbg(0,"**draw 2.b4 %p\n", displaylist->idle_ev);
3665 }
3666 else
3667 {
3668 //dbg(0,"**draw 2.b5\n");
3669 do_draw(displaylist, 0, flags);
3670 }
3671 }
3672
3673 /**
3674 * FIXME
3675 * @param <>
3676 * @returns <>
3677 * @author Martin Schaller (04/2008)
3678 */
3679 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)
3680 {
3681 //dbg(0,"ooo enter ooo\n");
3682
3683 graphics_load_mapset(gra, displaylist, mapset, trans, l, async, cb, flags);
3684 }
3685
3686 int graphics_draw_cancel(struct graphics *gra, struct displaylist *displaylist)
3687 {
3688 //DBG dbg(0,"ooo enter ooo\n");
3689
3690 if (!displaylist->busy)
3691 return 0;
3692 do_draw(displaylist, 1, 0);
3693 return 1;
3694 }
3695
3696 /**
3697 * FIXME
3698 * @param <>
3699 * @returns <>
3700 * @author Martin Schaller (04/2008)
3701 */
3702 struct displaylist_handle
3703 {
3704 struct displaylist *dl;
3705 struct displayitem *di;
3706 int hashidx;
3707 };
3708
3709 /**
3710 * FIXME
3711 * @param <>
3712 * @returns <>
3713 * @author Martin Schaller (04/2008)
3714 */
3715 struct displaylist_handle * graphics_displaylist_open(struct displaylist *displaylist)
3716 {
3717 struct displaylist_handle *ret;
3718
3719 ret=g_new0(struct displaylist_handle, 1);
3720 ret->dl = displaylist;
3721
3722 return ret;
3723 }
3724
3725 /**
3726 * FIXME
3727 * @param <>
3728 * @returns <>
3729 * @author Martin Schaller (04/2008)
3730 */
3731 struct displayitem * graphics_displaylist_next(struct displaylist_handle *dlh)
3732 {
3733 struct displayitem *ret;
3734 if (!dlh)
3735 return NULL;
3736 for (;;)
3737 {
3738 if (dlh->di)
3739 {
3740 ret = dlh->di;
3741 dlh->di = ret->next;
3742 break;
3743 }
3744 if (dlh->hashidx == HASH_SIZE_GRAPHICS_)
3745 {
3746 ret = NULL;
3747 break;
3748 }
3749 if (dlh->dl->hash_entries[dlh->hashidx].type)
3750 dlh->di = dlh->dl->hash_entries[dlh->hashidx].di;
3751 dlh->hashidx++;
3752 }
3753 return ret;
3754 }
3755
3756 /**
3757 * FIXME
3758 * @param <>
3759 * @returns <>
3760 * @author Martin Schaller (04/2008)
3761 */
3762 void graphics_displaylist_close(struct displaylist_handle *dlh)
3763 {
3764 g_free(dlh);
3765 }
3766
3767 /**
3768 * FIXME
3769 * @param <>
3770 * @returns <>
3771 * @author Martin Schaller (04/2008)
3772 */
3773 struct displaylist * graphics_displaylist_new(void)
3774 {
3775 struct displaylist *ret=g_new0(struct displaylist, 1);
3776
3777 ret->dc.maxlen = 16384;
3778 ret->busy = 0;
3779
3780 return ret;
3781 }
3782
3783 /**
3784 * FIXME
3785 * @param <>
3786 * @returns <>
3787 * @author Martin Schaller (04/2008)
3788 */
3789 struct item * graphics_displayitem_get_item(struct displayitem *di)
3790 {
3791 return &di->item;
3792 }
3793
3794 int graphics_displayitem_get_coord_count(struct displayitem *di)
3795 {
3796 return di->count;
3797 }
3798
3799 /**
3800 * FIXME
3801 * @param <>
3802 * @returns <>
3803 * @author Martin Schaller (04/2008)
3804 */
3805 char * graphics_displayitem_get_label(struct displayitem *di)
3806 {
3807 return di->label;
3808 }
3809
3810 int graphics_displayitem_get_displayed(struct displayitem *di)
3811 {
3812 return 1;
3813 }
3814
3815 /**
3816 * FIXME
3817 * @param <>
3818 * @returns <>
3819 * @author Martin Schaller (04/2008)
3820 */
3821 static int within_dist_point(struct point *p0, struct point *p1, int dist)
3822 {
3823 if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
3824 return 0;
3825 if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
3826 return 0;
3827 if ((p0->x - p1->x) * (p0->x - p1->x) + (p0->y - p1->y) * (p0->y - p1->y) <= dist * dist)
3828 {
3829 return 1;
3830 }
3831 return 0;
3832 }
3833
3834 /**
3835 * FIXME
3836 * @param <>
3837 * @returns <>
3838 * @author Martin Schaller (04/2008)
3839 */
3840 static int within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
3841 {
3842 int vx, vy, wx, wy;
3843 int c1, c2;
3844 struct point line_p;
3845
3846 if (line_p0->x < line_p1->x)
3847 {
3848 if (p->x < line_p0->x - dist)
3849 return 0;
3850 if (p->x > line_p1->x + dist)
3851 return 0;
3852 }
3853 else
3854 {
3855 if (p->x < line_p1->x - dist)
3856 return 0;
3857 if (p->x > line_p0->x + dist)
3858 return 0;
3859 }
3860 if (line_p0->y < line_p1->y)
3861 {
3862 if (p->y < line_p0->y - dist)
3863 return 0;
3864 if (p->y > line_p1->y + dist)
3865 return 0;
3866 }
3867 else
3868 {
3869 if (p->y < line_p1->y - dist)
3870 return 0;
3871 if (p->y > line_p0->y + dist)
3872 return 0;
3873 }
3874
3875 vx = line_p1->x - line_p0->x;
3876 vy = line_p1->y - line_p0->y;
3877 wx = p->x - line_p0->x;
3878 wy = p->y - line_p0->y;
3879
3880 c1 = vx * wx + vy * wy;
3881 if (c1 <= 0)
3882 return within_dist_point(p, line_p0, dist);
3883 c2 = vx * vx + vy * vy;
3884 if (c2 <= c1)
3885 return within_dist_point(p, line_p1, dist);
3886
3887 line_p.x = line_p0->x + vx * c1 / c2;
3888 line_p.y = line_p0->y + vy * c1 / c2;
3889 return within_dist_point(p, &line_p, dist);
3890 }
3891
3892 /**
3893 * FIXME
3894 * @param <>
3895 * @returns <>
3896 * @author Martin Schaller (04/2008)
3897 */
3898 static int within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
3899 {
3900 int i;
3901 for (i = 0; i < count - 1; i++)
3902 {
3903 if (within_dist_line(p, line_pnt + i, line_pnt + i + 1, dist))
3904 {
3905 return 1;
3906 }
3907 }
3908 if (close)
3909 return (within_dist_line(p, line_pnt, line_pnt + count - 1, dist));
3910 return 0;
3911 }
3912
3913 /**
3914 * FIXME
3915 * @param <>
3916 * @returns <>
3917 * @author Martin Schaller (04/2008)
3918 */
3919 static int within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
3920 {
3921 int i, j, c = 0;
3922 for (i = 0, j = count - 1; i < count; j = i++)
3923 {
3924 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))
3925 c = !c;
3926 }
3927 if (!c)
3928 return within_dist_polyline(p, poly_pnt, count, dist, 1);
3929 return c;
3930 }
3931
3932 /**
3933 * FIXME
3934 * @param <>
3935 * @returns <>
3936 * @author Martin Schaller (04/2008)
3937 */
3938 int graphics_displayitem_within_dist(struct displaylist *displaylist, struct displayitem *di, struct point *p, int dist)
3939 {
3940 struct point *pa = g_alloca(sizeof(struct point) * displaylist->dc.maxlen);
3941 int count;
3942
3943 count = transform(displaylist->dc.trans, displaylist->dc.pro, di->c, pa, di->count, 1, 0, NULL);
3944
3945 if (di->item.type < type_line)
3946 {
3947 return within_dist_point(p, &pa[0], dist);
3948 }
3949 if (di->item.type < type_area)
3950 {
3951 return within_dist_polyline(p, pa, count, dist, 0);
3952 }
3953 return within_dist_polygon(p, pa, count, dist);
3954 }
3955
3956 static void graphics_process_selection_item(struct displaylist *dl, struct item *item)
3957 {
3958 #if 0 /* FIXME */
3959 struct displayitem di,*di_res;
3960 GHashTable *h;
3961 int count,max=dl->dc.maxlen;
3962 struct coord ca[max];
3963 struct attr attr;
3964 struct map_rect *mr;
3965
3966 di.item=*item;
3967 di.label=NULL;
3968 di.count=0;
3969 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
3970 if (h)
3971 {
3972 di_res=g_hash_table_lookup(h, &di);
3973 if (di_res)
3974 {
3975 di.item.type=(enum item_type)item->priv_data;
3976 display_add(dl, &di.item, di_res->count, di_res->c, NULL, 0);
3977 return;
3978 }
3979 }
3980 mr=map_rect_new(item->map, NULL);
3981 item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
3982 count=item_coord_get(item, ca, item->type < type_line ? 1: max);
3983 if (!item_attr_get(item, attr_label, &attr))
3984 attr.u.str=NULL;
3985 if (dl->conv && attr.u.str && attr.u.str[0])
3986 {
3987 char *str=map_convert_string(item->map, attr.u.str);
3988 display_add(dl, item, count, ca, &str, 1);
3989 map_convert_free(str);
3990 }
3991 else
3992 display_add(dl, item, count, ca, &attr.u.str, 1);
3993 map_rect_destroy(mr);
3994 #endif
3995 }
3996
3997 void graphics_add_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
3998 {
3999 struct item *item_dup=g_new(struct item, 1);
4000 *item_dup = *item;
4001 item_dup->priv_data = (void *) type;
4002 gra->selection = g_list_append(gra->selection, item_dup);
4003 if (dl)
4004 graphics_process_selection_item(dl, item_dup);
4005 }
4006
4007 void graphics_remove_selection(struct graphics *gra, struct item *item, enum item_type type, struct displaylist *dl)
4008 {
4009 GList *curr;
4010 int found;
4011
4012 for (;;)
4013 {
4014 curr = gra->selection;
4015 found = 0;
4016 while (curr)
4017 {
4018 struct item *sitem = curr->data;
4019 if (item_is_equal(*item, *sitem))
4020 {
4021 if (dl)
4022 {
4023 struct displayitem di;
4024 /* Unused Variable
4025 GHashTable *h; */
4026 di.item = *sitem;
4027 di.label = NULL;
4028 di.count = 0;
4029 di.item.type = type;
4030 #if 0 /* FIXME */
4031 h=g_hash_table_lookup(dl->dl, GINT_TO_POINTER(di.item.type));
4032 if (h)
4033 g_hash_table_remove(h, &di);
4034 #endif
4035 }
4036 g_free(sitem);
4037 gra->selection = g_list_remove(gra->selection, curr->data);
4038 found = 1;
4039 break;
4040 }
4041 }
4042 if (!found)
4043 return;
4044 }
4045 }
4046
4047 void graphics_clear_selection(struct graphics *gra, struct displaylist *dl)
4048 {
4049 while (gra->selection)
4050 {
4051 struct item *item = (struct item *) gra->selection->data;
4052 graphics_remove_selection(gra, item, (enum item_type) item->priv_data, dl);
4053 }
4054 }
4055
4056 static void graphics_process_selection(struct graphics *gra, struct displaylist *dl)
4057 {
4058 GList *curr;
4059
4060 curr = gra->selection;
4061 while (curr)
4062 {
4063 struct item *item = curr->data;
4064 graphics_process_selection_item(dl, item);
4065 curr = g_list_next(curr);
4066 }
4067 }

   
Visit the ZANavi Wiki