87ac5083ea6767c1bcee554557bdd27496841815
[navit-package] / src / graphics.c
1 #include <glib.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include "debug.h"
6 #include "string.h"
7 #include "draw_info.h"
8 #include "point.h"
9 #include "graphics.h"
10 #include "projection.h"
11 #include "map.h"
12 #include "coord.h"
13 #include "transform.h"
14 #include "plugin.h"
15 #include "profile.h"
16 #include "mapset.h"
17 #include "layout.h"
18 #include "route.h"
19 #include "util.h"
20
21 struct graphics
22 {
23         struct graphics_priv *priv;
24         struct graphics_methods meth;
25         struct graphics_font *font[16];
26         struct graphics_gc *gc[3];
27         int ready;
28 };
29
30 struct displaylist {
31         GHashTable *dl;
32 };
33
34 struct graphics *
35 graphics_new(const char *type, struct attr **attrs)
36 {
37         struct graphics *this_;
38         struct graphics_priv * (*new)(struct graphics_methods *meth, struct attr **attrs);
39
40         new=plugin_get_graphics_type(type);
41         if (! new)
42                 return NULL;    
43         this_=g_new0(struct graphics, 1);
44         this_->priv=(*new)(&this_->meth, attrs);
45         return this_;
46 }
47
48 struct graphics *
49 graphics_overlay_new(struct graphics *parent, struct point *p, int w, int h)
50 {
51         struct graphics *this_;
52         this_=g_new0(struct graphics, 1);
53         this_->priv=parent->meth.overlay_new(parent->priv, &this_->meth, p, w, h);
54         return this_;
55 }
56
57
58 void
59 graphics_init(struct graphics *this_)
60 {
61         this_->gc[0]=graphics_gc_new(this_);
62         graphics_gc_set_background(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 });
63         graphics_gc_set_foreground(this_->gc[0], &(struct color) { 0xffff, 0xefef, 0xb7b7 });
64         this_->gc[1]=graphics_gc_new(this_);
65         graphics_gc_set_background(this_->gc[1], &(struct color) { 0x0000, 0x0000, 0x0000 });
66         graphics_gc_set_foreground(this_->gc[1], &(struct color) { 0xffff, 0xffff, 0xffff });
67         this_->gc[2]=graphics_gc_new(this_);
68         graphics_gc_set_background(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff });
69         graphics_gc_set_foreground(this_->gc[2], &(struct color) { 0xffff, 0xffff, 0xffff });
70         this_->meth.background_gc(this_->priv, this_->gc[0]->priv);
71 }
72
73 void *
74 graphics_get_data(struct graphics *this_, char *type)
75 {
76         return (this_->meth.get_data(this_->priv, type));
77 }
78
79 void
80 graphics_register_resize_callback(struct graphics *this_, void (*callback)(void *data, int w, int h), void *data)
81 {
82         this_->meth.register_resize_callback(this_->priv, callback, data);
83 }
84
85 void
86 graphics_register_button_callback(struct graphics *this_, void (*callback)(void *data, int pressed, int button, struct point *p), void *data)
87 {
88         this_->meth.register_button_callback(this_->priv, callback, data);
89 }
90
91 void
92 graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data)
93 {
94         this_->meth.register_motion_callback(this_->priv, callback, data);
95 }
96
97 struct graphics_font *
98 graphics_font_new(struct graphics *gra, int size)
99 {
100         struct graphics_font *this_;
101
102         this_=g_new0(struct graphics_font,1);
103         this_->priv=gra->meth.font_new(gra->priv, &this_->meth, size);
104         return this_;
105 }
106
107 struct graphics_gc *
108 graphics_gc_new(struct graphics *gra)
109 {
110         struct graphics_gc *this_;
111
112         this_=g_new0(struct graphics_gc,1);
113         this_->priv=gra->meth.gc_new(gra->priv, &this_->meth);
114         return this_;
115 }
116
117 void
118 graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
119 {
120         gc->meth.gc_set_foreground(gc->priv, c);
121 }
122
123 void
124 graphics_gc_set_background(struct graphics_gc *gc, struct color *c)
125 {
126         gc->meth.gc_set_background(gc->priv, c);
127 }
128
129 void
130 graphics_gc_set_linewidth(struct graphics_gc *gc, int width)
131 {
132         gc->meth.gc_set_linewidth(gc->priv, width);
133 }
134
135 struct graphics_image *
136 graphics_image_new(struct graphics *gra, char *path)
137 {
138         struct graphics_image *this_;
139
140         this_=g_new0(struct graphics_image,1);
141         this_->priv=gra->meth.image_new(gra->priv, &this_->meth, path, &this_->width, &this_->height, &this_->hot);
142         if (! this_->priv) {
143                 g_free(this_);
144                 this_=NULL;
145         }
146         return this_;
147 }
148
149 void
150 graphics_draw_restore(struct graphics *this_, struct point *p, int w, int h)
151 {
152         this_->meth.draw_restore(this_->priv, p, w, h);
153 }
154
155 void
156 graphics_draw_mode(struct graphics *this_, enum draw_mode_num mode)
157 {
158         this_->meth.draw_mode(this_->priv, mode);
159 }
160
161 void
162 graphics_draw_lines(struct graphics *this_, struct graphics_gc *gc, struct point *p, int count)
163 {
164         this_->meth.draw_lines(this_->priv, gc->priv, p, count);
165 }
166
167 void
168 graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int r)
169 {
170         this_->meth.draw_circle(this_->priv, gc->priv, p, r);
171 }
172
173
174 void
175 graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h)
176 {
177         this_->meth.draw_rectangle(this_->priv, gc->priv, p, w, h);
178 }
179
180
181 #include "attr.h"
182 #include "popup.h"
183 #include <stdio.h>
184
185 #if 0
186 static void
187 popup_view_html(struct popup_item *item, char *file)
188 {
189         char command[1024];
190         sprintf(command,"firefox %s", file);
191         system(command);
192 }
193
194 static void
195 graphics_popup(struct display_list *list, struct popup_item **popup)
196 {
197         struct item *item;
198         struct attr attr;
199         struct map_rect *mr;
200         struct coord c;
201         struct popup_item *curr_item,*last=NULL;
202         item=list->data;
203         mr=map_rect_new(item->map, NULL, NULL, 0);
204         printf("id hi=0x%x lo=0x%x\n", item->id_hi, item->id_lo);
205         item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
206         if (item) {
207                 if (item_attr_get(item, attr_name, &attr)) {
208                         curr_item=popup_item_new_text(popup,attr.u.str,1);
209                         if (item_attr_get(item, attr_info_html, &attr)) {
210                                 popup_item_new_func(&last,"HTML Info",1, popup_view_html, g_strdup(attr.u.str));
211                         }
212                         if (item_attr_get(item, attr_price_html, &attr)) {
213                                 popup_item_new_func(&last,"HTML Preis",2, popup_view_html, g_strdup(attr.u.str));
214                         }
215                         curr_item->submenu=last;
216                 }
217         }
218         map_rect_destroy(mr);
219 }
220 #endif
221
222 struct displayitem {
223         struct item item;
224         char *label;
225         int displayed;
226         int count;
227         struct point pnt[0];
228 };
229
230 static int
231 xdisplay_free_list(gpointer key, gpointer value, gpointer user_data)
232 {
233         GList *h, *l;
234         h=value;
235         l=h;
236         while (l) {
237                 struct displayitem *di=l->data;
238                 if (! di->displayed && di->item.type < type_line) 
239                         dbg(1,"warning: item '%s' not displayed\n", item_to_name(di->item.type));
240                 g_free(l->data);
241                 l=g_list_next(l);
242         }
243         g_list_free(h);
244         return TRUE;
245 }
246
247 static void
248 xdisplay_free(GHashTable *display_list)
249 {
250         g_hash_table_foreach_remove(display_list, xdisplay_free_list, NULL);
251 }
252
253 void
254 display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label)
255 {
256         struct displayitem *di;
257         int len;
258         GList *l;
259         char *p;
260
261         len=sizeof(*di)+count*sizeof(*pnt);
262         if (label)
263                 len+=strlen(label)+1;
264
265         p=g_malloc(len);
266
267         di=(struct displayitem *)p;
268         di->displayed=0;
269         p+=sizeof(*di)+count*sizeof(*pnt);
270         di->item=*item;
271         if (label) {
272                 di->label=p;
273                 strcpy(di->label, label);
274         } else 
275                 di->label=NULL;
276         di->count=count;
277         memcpy(di->pnt, pnt, count*sizeof(*pnt));
278
279         l=g_hash_table_lookup(displaylist->dl, GINT_TO_POINTER(item->type));
280         l=g_list_prepend(l, di);
281         g_hash_table_insert(displaylist->dl, GINT_TO_POINTER(item->type), l);
282 }
283
284
285 static void
286 label_line(struct graphics *gra, struct graphics_gc *fg, struct graphics_gc *bg, struct graphics_font *font, struct point *p, int count, char *label)
287 {
288         int i,x,y,tl;
289         double dx,dy,l;
290         struct point p_t;
291
292         tl=strlen(label)*400;
293         for (i = 0 ; i < count-1 ; i++) {
294                 dx=p[i+1].x-p[i].x;
295                 dx*=100;
296                 dy=p[i+1].y-p[i].y;
297                 dy*=100;
298                 l=(int)sqrt((float)(dx*dx+dy*dy));
299                 if (l > tl) {
300                         x=p[i].x;
301                         y=p[i].y;
302                         if (dx < 0) {
303                                 dx=-dx;
304                                 dy=-dy;
305                                 x=p[i+1].x;
306                                 y=p[i+1].y;
307                         }
308                         x+=(l-tl)*dx/l/200;
309                         y+=(l-tl)*dy/l/200;
310                         x-=dy*45/l/10;
311                         y+=dx*45/l/10;
312                         p_t.x=x;
313                         p_t.y=y;
314         #if 0
315                         printf("display_text: '%s', %d, %d, %d, %d %d\n", label, x, y, dx*0x10000/l, dy*0x10000/l, l);
316         #endif
317                         gra->meth.draw_text(gra->priv, fg->priv, bg->priv, font->priv, label, &p_t, dx*0x10000/l, dy*0x10000/l);
318                 }
319         }
320 }
321
322
323 static void
324 xdisplay_draw_elements(struct graphics *gra, GHashTable *display_list, struct itemtype *itm)
325 {
326         struct element *e;
327         GList *l,*ls,*es,*types;
328         enum item_type type;
329         struct graphics_gc *gc;
330         struct graphics_image *img;
331         struct point p;
332
333         es=itm->elements;       
334         while (es) {
335                 e=es->data;
336                 types=itm->type;
337                 while (types) {
338                         type=GPOINTER_TO_INT(types->data);
339                         ls=g_hash_table_lookup(display_list, GINT_TO_POINTER(type));
340                         l=ls;
341                         gc=NULL;
342                         img=NULL;
343                         while (l) {
344                                 struct displayitem *di;
345                                 di=l->data;
346                                 di->displayed=1;
347                                 if (! gc) {
348                                         gc=graphics_gc_new(gra);
349                                         gc->meth.gc_set_foreground(gc->priv, &e->color);
350                                 }
351                                 switch (e->type) {
352                                 case element_polygon:
353                                         gra->meth.draw_polygon(gra->priv, gc->priv, di->pnt, di->count);
354                                         break;
355                                 case element_polyline:
356                                         if (e->u.polyline.width > 1) 
357                                                 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
358                                         gra->meth.draw_lines(gra->priv, gc->priv, di->pnt, di->count);
359                                         break;
360                                 case element_circle:
361                                         if (e->u.circle.width > 1) 
362                                                 gc->meth.gc_set_linewidth(gc->priv, e->u.polyline.width);
363                                         gra->meth.draw_circle(gra->priv, gc->priv, &di->pnt[0], e->u.circle.radius);
364                                         if (di->label && e->label_size) {
365                                                 p.x=di->pnt[0].x+3;
366                                                 p.y=di->pnt[0].y+10;
367                                                 if (! gra->font[e->label_size])
368                                                         gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20);
369                                                 gra->meth.draw_text(gra->priv, gra->gc[2]->priv, gra->gc[1]->priv, gra->font[e->label_size]->priv, di->label, &p, 0x10000, 0);
370                                         }
371                                         break;
372                                 case element_label:
373                                         if (di->label) {
374                                                 if (! gra->font[e->label_size])
375                                                         gra->font[e->label_size]=graphics_font_new(gra, e->label_size*20);
376                                                 label_line(gra, gra->gc[2], gra->gc[1], gra->font[e->label_size], di->pnt, di->count, di->label);
377                                         }
378                                         break;
379                                 case element_icon:
380                                         if (!img) {
381                                                 char *icon=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"), "/xpm/", e->u.icon.src, NULL);
382                                                 img=graphics_image_new(gra, icon);
383                                                 g_free(icon);
384                                                 if (! img)
385                                                         g_warning("failed to load icon '%s'\n", e->u.icon.src);
386                                         }
387                                         if (img) {
388                                                 p.x=di->pnt[0].x - img->hot.x;
389                                                 p.y=di->pnt[0].y - img->hot.y;
390                                                 gra->meth.draw_image(gra->priv, gra->gc[0]->priv, &p, img->priv);
391                                         }
392                                         break;
393                                 case element_image:
394                                         printf("image: '%s'\n", di->label);
395                                         gra->meth.draw_image_warp(gra->priv, gra->gc[0]->priv, di->pnt, di->count, di->label);
396                                         break;
397                                 default:
398                                         printf("Unhandled element type %d\n", e->type);
399                                 
400                                 }
401                                 l=g_list_next(l);
402                         }
403                         types=g_list_next(types);       
404                 }
405                 es=g_list_next(es);
406         }       
407 }
408
409 static void
410 xdisplay_draw_layer(GHashTable *display_list, struct graphics *gra, struct layer *lay, int order)
411 {
412         GList *itms;
413         struct itemtype *itm;
414
415         itms=lay->itemtypes;
416         while (itms) {
417                 itm=itms->data;
418                 if (order >= itm->order_min && order <= itm->order_max) 
419                         xdisplay_draw_elements(gra, display_list, itm);
420                 itms=g_list_next(itms);
421         }
422 }
423
424 static void
425 xdisplay_draw_layout(GHashTable *display_list, struct graphics *gra, struct layout *l, int order)
426 {
427         GList *lays;
428         struct layer *lay;
429         
430         lays=l->layers;
431         while (lays) {
432                 lay=lays->data;
433                 xdisplay_draw_layer(display_list, gra, lay, order);
434                 lays=g_list_next(lays);
435         }
436 }
437
438 static void
439 xdisplay_draw(GHashTable *display_list, struct graphics *gra, GList *layouts, int order)
440 {
441         struct layout *l;
442
443         while (layouts) {
444                 l=layouts->data;
445                 xdisplay_draw_layout(display_list, gra, l, order);
446                 return;
447                 layouts=g_list_next(layouts);
448         }
449 }
450
451 extern void *route_selection;
452
453 static void
454 do_draw_map(struct displaylist *displaylist, struct transformation *t, struct map *m, struct map_selection *sel)
455 {
456         enum projection pro;
457         struct map_rect *mr;
458         struct item *item;
459         struct coord c;
460         int i, conv,count,max=16384;
461         struct point pnt[max];
462         struct coord ca[max];
463         struct attr attr;
464         struct coord_rect r;
465
466         pro=map_projection(m);
467         conv=map_requires_conversion(m);
468         transform_rect(t, pro, &sel->u.c_rect);
469         if (route_selection)
470                 mr=map_rect_new(m, route_selection);
471         else
472                 mr=map_rect_new(m, sel);
473         while ((item=map_rect_get_item(mr))) {
474                 if (item->type < type_line) {
475                         item_coord_get(item, &c, 1);
476                         if (!transform(t, pro, &c, &pnt[0])) {
477                                 dbg(1,"not visible\n");
478                                 continue;
479                         }
480                         count=1;
481                 } else {
482                         count = item_coord_get(item, ca, max);
483                         if (count < 2)
484                                 continue;
485                         r.lu=ca[0];
486                         r.rl=ca[0];
487                         for (i=1; i < count; i++) {
488                                 coord_rect_extend(&r, &ca[i]);
489                         }
490                         if (!transform_contains(t, pro, &r)) {
491                                 dbg(1,"poly not visible\n");
492                                 continue;
493                         }
494                         count = transform_array(t, pro, ca, pnt, count, 1);
495                         if (count < 2)
496                                 continue;
497                         g_assert(count < max);
498                 }
499                 if (!item_attr_get(item, attr_label, &attr))
500                         attr.u.str=NULL;
501                 if (conv && attr.u.str && attr.u.str[0]) {
502                         char *str=map_convert_string(m, attr.u.str);
503                         display_add(displaylist, item, count, pnt, str);
504                         map_convert_free(str);
505                 } else
506                         display_add(displaylist, item, count, pnt, attr.u.str);
507         }
508         map_rect_destroy(mr);
509 }
510
511 static void
512 do_draw(struct displaylist *displaylist, struct transformation *t, GList *mapsets, int order, struct route *route)
513 {
514         struct map_selection sel;
515         struct mapset *ms;
516         struct map *m;
517         struct mapset_handle *h;
518
519         if (! mapsets)
520                 return;
521         sel.next=NULL;
522         sel.order[layer_town]=1*order;
523         sel.order[layer_street]=order;
524         sel.order[layer_poly]=1*order;
525         ms=mapsets->data;
526         h=mapset_open(ms);
527         while ((m=mapset_next(h, 1))) {
528                 do_draw_map(displaylist, t, m, &sel);
529         }
530         mapset_close(h);
531         if (route) {
532                 m = route_get_map(route);
533                 if (m)
534                         do_draw_map(displaylist, t, m, &sel);
535         }
536 }
537
538 int
539 graphics_ready(struct graphics *this_)
540 {
541         return this_->ready;
542 }
543
544 void
545 graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route)
546 {
547         int order=transform_get_order(trans);
548         gra->meth.draw_mode(gra->priv, draw_mode_begin);
549         if (route)
550                 route_draw(route, trans, displaylist);
551         xdisplay_draw(displaylist->dl, gra, layouts, order);
552         gra->meth.draw_mode(gra->priv, draw_mode_end);
553 }
554
555 void
556 graphics_displaylist_move(struct displaylist *displaylist, int dx, int dy)
557 {
558         struct displaylist_handle *dlh;
559         struct displayitem *di;
560         int i;
561
562         dlh=graphics_displaylist_open(displaylist);
563         while ((di=graphics_displaylist_next(dlh))) {
564                 for (i = 0 ; i < di->count ; i++) {
565                         di->pnt[i].x+=dx;
566                         di->pnt[i].y+=dy;
567                 }
568         }
569         graphics_displaylist_close(dlh);
570 }
571
572
573 void
574 graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route)
575 {
576         int order=transform_get_order(trans);
577
578         dbg(1,"enter");
579
580 #if 0
581         printf("scale=%d center=0x%x,0x%x mercator scale=%f\n", scale, co->trans->center.x, co->trans->center.y, transform_scale(co->trans->center.y));
582 #endif
583         
584         xdisplay_free(displaylist->dl);
585         dbg(1,"order=%d\n", order);
586
587
588 #if 0
589         for (i = 0 ; i < data_window_type_end; i++) {
590                 data_window_begin(co->data_window[i]);  
591         }
592 #endif
593         profile(0,NULL);
594         do_draw(displaylist, trans, mapsets, order, route);
595         profile(1,"do_draw");
596         graphics_displaylist_draw(gra, displaylist, trans, layouts, route);
597         profile(1,"xdisplay_draw");
598         profile(0,"end");
599   
600 #if 0
601         for (i = 0 ; i < data_window_type_end; i++) {
602                 data_window_end(co->data_window[i]);    
603         }
604 #endif
605         gra->ready=1;
606 }
607
608
609 struct displaylist_handle {
610         GList *hl_head,*hl,*l;
611 };
612
613
614 struct displaylist_handle *
615 graphics_displaylist_open(struct displaylist *displaylist)
616 {
617         struct displaylist_handle *ret;
618
619         ret=g_new0(struct displaylist_handle, 1);
620         ret->hl_head=ret->hl=g_hash_to_list(displaylist->dl);
621
622         return ret;
623 }
624
625 struct displayitem *
626 graphics_displaylist_next(struct displaylist_handle *dlh)
627 {
628         struct displayitem *ret;
629         if (! dlh->l) {
630                 if (!dlh->hl)
631                         return NULL;
632                 dlh->l=dlh->hl->data;
633                 dlh->hl=g_list_next(dlh->hl);
634         }
635         ret=dlh->l->data;
636         dlh->l=g_list_next(dlh->l);
637         return ret;
638 }
639
640 void
641 graphics_displaylist_close(struct displaylist_handle *dlh)
642 {
643         g_list_free(dlh->hl_head);
644         g_free(dlh);
645 }
646
647 struct displaylist *
648 graphics_displaylist_new(void)
649 {
650         struct displaylist *ret=g_new(struct displaylist, 1);
651
652         ret->dl=g_hash_table_new(NULL,NULL);
653
654         return ret;
655 }
656
657 struct item *
658 graphics_displayitem_get_item(struct displayitem *di)
659 {
660         return &di->item;       
661 }
662
663 char *
664 graphics_displayitem_get_label(struct displayitem *di)
665 {
666         return di->label;
667 }
668
669 static int
670 within_dist_point(struct point *p0, struct point *p1, int dist)
671 {
672         if (p0->x == 32767 || p0->y == 32767 || p1->x == 32767 || p1->y == 32767)
673                 return 0;
674         if (p0->x == -32768 || p0->y == -32768 || p1->x == -32768 || p1->y == -32768)
675                 return 0;
676         if ((p0->x-p1->x)*(p0->x-p1->x) + (p0->y-p1->y)*(p0->y-p1->y) <= dist*dist) {
677                 return 1;
678         }
679         return 0;
680 }
681
682 static int
683 within_dist_line(struct point *p, struct point *line_p0, struct point *line_p1, int dist)
684 {
685         int vx,vy,wx,wy;
686         int c1,c2;
687         struct point line_p;
688
689         vx=line_p1->x-line_p0->x;
690         vy=line_p1->y-line_p0->y;
691         wx=p->x-line_p0->x;
692         wy=p->y-line_p0->y;
693
694         c1=vx*wx+vy*wy;
695         if ( c1 <= 0 )
696                 return within_dist_point(p, line_p0, dist);
697         c2=vx*vx+vy*vy;
698         if ( c2 <= c1 )
699                 return within_dist_point(p, line_p1, dist);
700
701         line_p.x=line_p0->x+vx*c1/c2;
702         line_p.y=line_p0->y+vy*c1/c2;
703         return within_dist_point(p, &line_p, dist);
704 }
705
706 static int
707 within_dist_polyline(struct point *p, struct point *line_pnt, int count, int dist, int close)
708 {
709         int i;
710         for (i = 0 ; i < count-1 ; i++) {
711                 if (within_dist_line(p,line_pnt+i,line_pnt+i+1,dist)) {
712                         return 1;
713                 }
714         }
715         if (close)
716                 return (within_dist_line(p,line_pnt,line_pnt+count-1,dist));
717         return 0;
718 }
719
720 static int
721 within_dist_polygon(struct point *p, struct point *poly_pnt, int count, int dist)
722 {
723         int i, j, c = 0;
724         for (i = 0, j = count-1; i < count; j = i++) {
725                 if ((((poly_pnt[i].y <= p->y) && ( p->y < poly_pnt[j].y )) ||
726                 ((poly_pnt[j].y <= p->y) && ( p->y < poly_pnt[i].y))) &&
727                 (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)) 
728                         c = !c;
729         }
730         if (! c)
731                 return within_dist_polyline(p, poly_pnt, count, dist, 1);
732         return c;
733 }
734
735 int
736 graphics_displayitem_within_dist(struct displayitem *di, struct point *p, int dist)
737 {
738         if (di->item.type < type_line) {
739                 return within_dist_point(p, &di->pnt[0], dist);
740         }
741         if (di->item.type < type_area) {
742                 return within_dist_polyline(p, di->pnt, di->count, dist, 0);
743         }
744         return within_dist_polygon(p, di->pnt, di->count, dist);
745 }