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

Contents of /navit/navit/graphics.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki