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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki