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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki