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