changed render levels for labels/place names
[navit-package] / src / data / binfile / binfile.c
1 #include <glib.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <math.h>
6 #include "config.h"
7 #include "debug.h"
8 #include "plugin.h"
9 #include "projection.h"
10 #include "map.h"
11 #include "maptype.h"
12 #include "item.h"
13 #include "attr.h"
14 #include "coord.h"
15 #include "transform.h"
16 #include "file.h"
17 #include "zipfile.h"
18 #include "endianess.h"
19
20 static int map_id;
21
22
23 struct minmax {
24         short min;
25         short max;
26 };
27
28 struct tile {
29         int *start;
30         int *end;
31         int *pos;
32         int *pos_coord_start;
33         int *pos_coord;
34         int *pos_attr_start;
35         int *pos_attr;
36         int *pos_next;
37         int zipfile_num;
38 };
39
40 struct map_priv {
41         int id;
42         char *filename;
43         struct file *fi;
44         struct zip_cd *index_cd;
45         int cde_size;
46         struct zip_eoc *eoc;
47         int zip_members;
48 };
49
50 struct map_rect_priv {
51         int *start;
52         int *end;
53         enum attr_type attr_last;
54         int label;
55         int *label_attr[2];
56         struct map_selection *sel;
57         struct map_priv *m;
58         struct item item;
59         int tile_depth;
60         struct tile tiles[8];
61         struct tile *t;
62         int country_id;
63 };
64
65 struct map_search_priv {
66         struct map_rect_priv *mr;
67         struct attr *search;
68         struct map_selection *ms;
69         int partial;
70         GHashTable *search_results;
71 };
72
73
74 static void minmax_to_cpu(struct minmax * mima) {
75         g_assert(mima  != NULL);
76         mima->min = le16_to_cpu(mima->min);
77         mima->max = le16_to_cpu(mima->max);
78 }
79
80 static void lfh_to_cpu(struct zip_lfh *lfh) {
81         g_assert(lfh != NULL);
82         lfh->ziplocsig = le32_to_cpu(lfh->ziplocsig);
83         lfh->zipver    = le16_to_cpu(lfh->zipver);
84         lfh->zipgenfld = le16_to_cpu(lfh->zipgenfld);
85         lfh->zipmthd   = le16_to_cpu(lfh->zipmthd);
86         lfh->ziptime   = le16_to_cpu(lfh->ziptime);
87         lfh->zipdate   = le16_to_cpu(lfh->zipdate);
88         lfh->zipcrc    = le32_to_cpu(lfh->zipcrc);
89         lfh->zipsize   = le32_to_cpu(lfh->zipsize);
90         lfh->zipuncmp  = le32_to_cpu(lfh->zipuncmp);
91         lfh->zipfnln   = le16_to_cpu(lfh->zipfnln);
92         lfh->zipxtraln = le16_to_cpu(lfh->zipxtraln);
93 }
94
95 static void cd_to_cpu(struct zip_cd *zcd) {
96         g_assert(zcd != NULL);
97         zcd->zipccrc   = le32_to_cpu(zcd->zipccrc);
98         zcd->zipcsiz   = le32_to_cpu(zcd->zipcsiz);
99         zcd->zipcunc   = le32_to_cpu(zcd->zipcunc);
100         zcd->zipcfnl   = le16_to_cpu(zcd->zipcfnl);
101         zcd->zipcxtl   = le16_to_cpu(zcd->zipcxtl);
102         zcd->zipccml   = le16_to_cpu(zcd->zipccml);
103         zcd->zipdsk    = le16_to_cpu(zcd->zipdsk);
104         zcd->zipint    = le16_to_cpu(zcd->zipint);
105         zcd->zipext    = le32_to_cpu(zcd->zipext);
106         zcd->zipofst   = le32_to_cpu(zcd->zipofst);
107 }
108
109 static void eoc_to_cpu(struct zip_eoc *eoc) {
110         g_assert(eoc != NULL);
111         eoc->zipesig   = le32_to_cpu(eoc->zipesig);
112         eoc->zipedsk   = le16_to_cpu(eoc->zipedsk);
113         eoc->zipecen   = le16_to_cpu(eoc->zipecen);
114         eoc->zipenum   = le16_to_cpu(eoc->zipenum);
115         eoc->zipecenn  = le16_to_cpu(eoc->zipecenn);
116         eoc->zipecsz   = le32_to_cpu(eoc->zipecsz);
117         eoc->zipeofst  = le32_to_cpu(eoc->zipeofst);
118         eoc->zipecoml  = le16_to_cpu(eoc->zipecoml);
119 }
120
121 static void
122 map_destroy_binfile(struct map_priv *m)
123 {
124         dbg(1,"map_destroy_binfile\n");
125         g_free(m);
126 }
127
128 static void
129 binfile_coord_rewind(void *priv_data)
130 {
131         struct map_rect_priv *mr=priv_data;
132         struct tile *t=mr->t;
133         t->pos_coord=t->pos_coord_start;
134 }
135
136 static int
137 binfile_coord_get(void *priv_data, struct coord *c, int count)
138 {
139         struct map_rect_priv *mr=priv_data;
140         struct tile *t=mr->t;
141         int ret=0;
142         dbg(2,"binfile_coord_get %d\n",count);
143         while (count--) {
144                 dbg(2,"%p vs %p\n", t->pos_coord, t->pos_attr_start);
145                 if (t->pos_coord >= t->pos_attr_start)
146                         break;
147                 c->x=le32_to_cpu(*(t->pos_coord++));
148                 c->y=le32_to_cpu(*(t->pos_coord++));
149                 c++;
150                 ret++;
151         }
152         return ret;
153 }
154
155 static void
156 binfile_attr_rewind(void *priv_data)
157 {
158         struct map_rect_priv *mr=priv_data;
159         struct tile *t=mr->t;
160         t->pos_attr=t->pos_attr_start;
161         
162 }
163
164 static int
165 binfile_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
166 {       
167         struct map_rect_priv *mr=priv_data;
168         struct tile *t=mr->t;
169         enum attr_type type;
170         int i,size;
171
172         if (attr_type != mr->attr_last) {
173                 t->pos_attr=t->pos_attr_start;
174                 mr->attr_last=attr_type;
175         }
176         while (t->pos_attr < t->pos_next) {
177                 size=le32_to_cpu(*(t->pos_attr++));
178                 type=le32_to_cpu(t->pos_attr[0]);
179                 if (type == attr_label) 
180                         mr->label=1;
181                 if (type == attr_town_name)
182                         mr->label_attr[0]=t->pos_attr;
183                 if (type == attr_street_name)
184                         mr->label_attr[0]=t->pos_attr;
185                 if (type == attr_street_name_systematic)
186                         mr->label_attr[1]=t->pos_attr;
187                 if (type == attr_type || attr_type == attr_any) {
188                         if (attr_type == attr_any) {
189                                 dbg(1,"pos %p attr %s size %d\n", t->pos_attr-1, attr_to_name(type), size);
190                         }
191                         attr->type=type;
192                         attr_data_set(attr, t->pos_attr+1);
193                         t->pos_attr+=size;
194                         return 1;
195                 } else {
196                         t->pos_attr+=size;
197                 }
198         }
199         if (!mr->label && (attr_type == attr_any || attr_type == attr_label)) {
200                 for (i = 0 ; i < sizeof(mr->label_attr)/sizeof(int *) ; i++) {
201                         if (mr->label_attr[i]) {
202                                 mr->label=1;
203                                 attr->type=attr_label;
204                                 attr_data_set(attr, mr->label_attr[i]+1);
205                                 return 1;
206                         }
207                 }
208         }
209         return 0;
210 }
211
212 static struct item_methods methods_binfile = {
213         binfile_coord_rewind,
214         binfile_coord_get,
215         binfile_attr_rewind,
216         binfile_attr_get,
217 };
218
219 static void
220 push_tile(struct map_rect_priv *mr, struct tile *t)
221 {
222         g_assert(mr->tile_depth < 8);
223         mr->t=&mr->tiles[mr->tile_depth++];
224         *(mr->t)=*t;
225         mr->t->pos=mr->t->pos_next=mr->t->start;
226 }
227
228 static int
229 pop_tile(struct map_rect_priv *mr)
230 {
231         if (mr->tile_depth <= 1)
232                 return 0;
233         file_data_free(mr->m->fi, (unsigned char *)(mr->t->start));
234         mr->t=&mr->tiles[--mr->tile_depth-1];
235         return 1;
236 }
237
238
239 static int
240 zipfile_to_tile(struct file *f, struct zip_cd *cd, struct tile *t)
241 {
242         char buffer[1024];
243         struct zip_lfh *lfh;
244         char *zipfn;
245         dbg(1,"enter %p %p %p\n", f, cd, t);
246         dbg(1,"cd->zipofst=0x%x\n", cd->zipofst);
247         t->start=NULL;
248         lfh=(struct zip_lfh *)(file_data_read(f,cd->zipofst,sizeof(struct zip_lfh)));
249         lfh_to_cpu(lfh);
250         zipfn=(char *)(file_data_read(f,cd->zipofst+sizeof(struct zip_lfh), lfh->zipfnln));
251         strncpy(buffer, zipfn, lfh->zipfnln);
252         buffer[lfh->zipfnln]='\0';
253         dbg(1,"0x%x '%s' %d %d,%d\n", lfh->ziplocsig, buffer, sizeof(*cd)+cd->zipcfnl, lfh->zipsize, lfh->zipuncmp);
254         switch (lfh->zipmthd) {
255         case 0:
256                 t->start=(int *)(file_data_read(f,cd->zipofst+sizeof(struct zip_lfh)+lfh->zipfnln, lfh->zipuncmp));
257                 t->end=t->start+lfh->zipuncmp/4;
258                 break;
259         case 8:
260                 t->start=(int *)(file_data_read_compressed(f,cd->zipofst+sizeof(struct zip_lfh)+lfh->zipfnln, lfh->zipsize, lfh->zipuncmp));
261                 t->end=t->start+lfh->zipuncmp/4;
262                 break;
263         default:
264                 dbg(0,"Unknown compression method %d\n", lfh->zipmthd);
265         }
266         file_data_free(f, (unsigned char *)zipfn);
267         file_data_free(f, (unsigned char *)lfh);
268         return t->start != NULL;
269 }
270
271 static void
272 push_zipfile_tile(struct map_rect_priv *mr, int zipfile)
273 {
274         struct map_priv *m=mr->m;
275         struct file *f=m->fi;
276         struct tile t;
277         struct zip_cd *cd=(struct zip_cd *)(file_data_read(f, m->eoc->zipeofst + zipfile*m->cde_size, sizeof(struct zip_cd)));
278         cd_to_cpu(cd);
279         dbg(1,"enter %p %d\n", mr, zipfile);
280         t.zipfile_num=zipfile;
281         if (zipfile_to_tile(f, cd, &t))
282                 push_tile(mr, &t);
283         file_data_free(f, (unsigned char *)cd);
284 }
285
286 static struct map_rect_priv *
287 map_rect_new_binfile(struct map_priv *map, struct map_selection *sel)
288 {
289         struct map_rect_priv *mr;
290         struct tile t;
291
292         dbg(1,"map_rect_new_binfile\n");
293         mr=g_new0(struct map_rect_priv, 1);
294         mr->m=map;
295         mr->sel=sel;
296         mr->item.id_hi=0;
297         mr->item.id_lo=0;
298         dbg(1,"zip_members=%d\n", map->zip_members);
299         if (map->eoc) 
300                 push_zipfile_tile(mr, map->zip_members-1);
301         else {
302                 unsigned char *d=file_data_read(map->fi, 0, map->fi->size);
303                 t.start=(int *)d;
304                 t.end=(int *)(d+map->fi->size);
305                 t.zipfile_num=0;
306                 push_tile(mr, &t);
307         }
308         mr->item.meth=&methods_binfile;
309         mr->item.priv_data=mr;
310         return mr;
311 }
312
313
314 static void
315 map_rect_destroy_binfile(struct map_rect_priv *mr)
316 {
317         while (pop_tile(mr));
318         file_data_free(mr->m->fi, (unsigned char *)(mr->tiles[0].start));
319         g_free(mr);
320 }
321
322 static void
323 setup_pos(struct map_rect_priv *mr)
324 {
325         int size,coord_size;
326         struct tile *t=mr->t;
327         size=le32_to_cpu(*(t->pos++));
328         if (size > 1024*1024 || size < 0) {
329                 fprintf(stderr,"size=0x%x\n", size);
330 #if 0
331                 fprintf(stderr,"offset=%d\n", (unsigned char *)(mr->pos)-mr->m->f->begin);
332 #endif
333                 g_error("size error");
334         }
335         t->pos_next=t->pos+size;
336         mr->item.type=le32_to_cpu(*(t->pos++));
337         coord_size=le32_to_cpu(*(t->pos++));
338         t->pos_coord_start=t->pos_coord=t->pos;
339         t->pos_attr_start=t->pos_attr=t->pos_coord+coord_size;
340 }
341
342 static int
343 selection_contains(struct map_selection *sel, struct coord_rect *r, struct minmax *mima)
344 {
345         int order;
346         if (! sel)
347                 return 1;
348         while (sel) {
349                 if (coord_rect_overlap(r, &sel->u.c_rect)) {
350                         order=sel->order[0];
351                         if (sel->order[1] > order)
352                                 order=sel->order[1];
353                         if (sel->order[2] > order)
354                                 order=sel->order[2];
355                         dbg(1,"min %d max %d order %d\n", mima->min, mima->max, order);
356                         if (!mima->min && !mima->max)
357                                 return 1;
358                         if (order >= mima->min && order <= mima->max)
359                                 return 1;
360                 }
361                 sel=sel->next;
362         }
363         return 0;
364 }
365
366 static void
367 map_parse_country_binfile(struct map_rect_priv *mr)
368 {
369         struct attr at;
370         if (binfile_attr_get(mr->item.priv_data, attr_country_id, &at)) {
371                 if (at.u.num == mr->country_id)
372                 {
373                         if (binfile_attr_get(mr->item.priv_data, attr_zipfile_ref, &at))
374                         {
375                                 push_zipfile_tile(mr, at.u.num);
376                         }
377                 }
378         }
379 }
380
381 static struct item *
382 map_rect_get_item_binfile(struct map_rect_priv *mr)
383 {
384         struct tile *t;
385         struct minmax *mima;
386         for (;;) {
387                 t=mr->t;
388                 if (! t)
389                         return NULL;
390                 t->pos=t->pos_next;
391                 if (t->pos >= t->end) {
392                         if (pop_tile(mr))
393                                 continue;
394                         return NULL;
395                 }
396                 mr->item.id_hi=t->zipfile_num;
397                 mr->item.id_lo=t->pos-t->start;
398                 mr->label=0;
399                 memset(mr->label_attr, 0, sizeof(mr->label_attr));
400                 setup_pos(mr);
401                 if ((mr->item.type == type_submap) && (!mr->country_id)) {
402                         struct coord_rect r;
403                         r.lu.x=le32_to_cpu(t->pos_coord[0]);
404                         r.lu.y=le32_to_cpu(t->pos_coord[3]);
405                         r.rl.x=le32_to_cpu(t->pos_coord[2]);
406                         r.rl.y=le32_to_cpu(t->pos_coord[1]);
407                         mima=(struct minmax *)(t->pos_attr+2);
408                         minmax_to_cpu(mima);
409                         if (!mr->m->eoc || !selection_contains(mr->sel, &r, mima)) {
410                                 continue;
411                         }
412                         dbg(1,"pushing zipfile %d from %d\n", le32_to_cpu(t->pos_attr[5]), t->zipfile_num);
413                         push_zipfile_tile(mr, le32_to_cpu(t->pos_attr[5]));
414                         continue;
415                                 
416                 }
417                 if (mr->country_id)
418                 {
419                         if (mr->item.type == type_countryindex) {
420                                 map_parse_country_binfile(mr);
421                         }
422                         if (mr->item.type >= type_town_label && mr->item.type <= type_district_label_1e7)
423                         {
424                                 return &mr->item;
425                         } else {
426                                 continue;
427                         }
428                 }
429                 return &mr->item;
430         }
431 }
432
433 static struct item *
434 map_rect_get_item_byid_binfile(struct map_rect_priv *mr, int id_hi, int id_lo)
435 {
436         struct tile *t;
437         if (mr->m->eoc) 
438                 push_zipfile_tile(mr, id_hi);
439         t=mr->t;
440         t->pos=t->start+id_lo;
441         mr->item.id_hi=id_hi;
442         mr->item.id_lo=id_lo;
443         mr->label=0;
444         memset(mr->label_attr, 0, sizeof(mr->label_attr));
445         setup_pos(mr);
446         return &mr->item;
447 }
448
449 static struct map_search_priv *
450 binmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
451 {
452         struct map_rect_priv *map_rec;
453         struct map_search_priv *msp;
454         struct map_selection *ms;
455         struct item *town;
456         int i;
457         
458         switch (search->type) {
459                 case attr_country_name:
460                         break;
461                 case attr_town_name:
462                         msp = g_new(struct map_search_priv, 1);
463                         msp->search_results = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
464                         map_rec = map_rect_new_binfile(map, NULL);
465                         map_rec->country_id = item->id_lo;
466                         msp->mr = map_rec;
467                         msp->search = search;
468                         msp->partial = partial;
469                         return msp;
470                         break;
471                 case attr_town_postal:
472                         break;
473                 case attr_street_name:
474                         ms = g_new(struct map_selection, 1);
475                         ms->next = NULL;
476                         for (i = 0; i < layer_end; i++)
477                         {
478                                 ms->order[i] = 18;
479                         }
480                         map_rec = map_rect_new_binfile(map, ms);
481                         town = map_rect_get_item_byid_binfile(map_rec, item->id_hi, item->id_lo);
482                         if (town) {
483                                 struct map_search_priv *msp = g_new(struct map_search_priv, 1);
484                                 struct coord *c = g_new(struct coord, 1);
485                                 int size = 10000;
486                                 switch (town->type) {
487                                         case type_town_label_2e5:
488                                                 size = 10000;
489                                                 break;
490                                         case type_town_label_2e4:
491                                                 size = 2500;
492                                                 break;
493                                         case type_town_label_2e3:
494                                                 size = 1000;
495                                                 break;
496                                         case type_town_label_2e2:
497                                                 size = 1000;
498                                                 break;
499                                         default:
500                                                 break;
501                                 }
502                                 item_coord_get(town, c, 1);
503                                 ms->u.c_rect.lu.x = c->x-size;
504                                 ms->u.c_rect.lu.y = c->y+size;
505                                 ms->u.c_rect.rl.x = c->x+size;
506                                 ms->u.c_rect.rl.y = c->y-size;
507                                 
508                                 map_rect_destroy_binfile(map_rec);
509                                 map_rec = map_rect_new_binfile(map, ms);
510                                 msp->mr = map_rec;
511                                 msp->search = search;
512                                 msp->partial = partial;
513                                 msp->search_results = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
514                                 return msp;
515                         }
516                         map_rect_destroy_binfile(map_rec);
517                         g_free(ms);
518                         break;
519                 default:
520                         break;
521         }
522         return NULL;
523 }
524 static int
525 ascii_cmp(char *name, char *match, int partial)
526 {
527         if (partial)
528                 return g_ascii_strncasecmp(name, match, strlen(match));
529         else
530                 return g_ascii_strcasecmp(name, match);
531 }
532
533 static struct item *
534 binmap_search_get_item(struct map_search_priv *map_search)
535 {
536         struct item* it;
537         while ((it  = map_rect_get_item_binfile(map_search->mr))) {
538                 if (map_search->search->type == attr_town_name) {
539                         if ((it->type >= type_town_label) && (it->type <= type_town_label_1e7)) {
540                                 struct attr at;
541                                 if (binfile_attr_get(it->priv_data, attr_label, &at)) {
542                                         if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial)) {
543                                                 return it;
544                                         }
545                                 }
546                         }
547                 } else if (map_search->search->type == attr_street_name) {
548                         if ((it->type == type_street_3_city) || (it->type == type_street_2_city) || (it->type == type_street_1_city)) {
549                                 struct attr at;
550                                 if (binfile_attr_get(it->priv_data, attr_label, &at)) {
551                                         if (!ascii_cmp(at.u.str, map_search->search->u.str, map_search->partial)) {
552                                                 if (!g_hash_table_lookup(map_search->search_results, at.u.str)) {
553                                                         g_hash_table_insert(map_search->search_results, g_strdup(at.u.str), "");
554                                                         return it;
555                                                 }
556                                         }
557                                 }
558                         }
559                 }
560         }
561         return NULL;
562 }
563
564 static void
565 binmap_search_destroy(struct map_search_priv *ms)
566 {
567         g_hash_table_destroy(ms->search_results);
568         g_free(ms->mr->sel);
569         map_rect_destroy_binfile(ms->mr);
570         g_free(ms);
571 }
572
573 static struct map_methods map_methods_binfile = {
574         projection_mg,
575         "utf-8",
576         map_destroy_binfile,
577         map_rect_new_binfile,
578         map_rect_destroy_binfile,
579         map_rect_get_item_binfile,
580         map_rect_get_item_byid_binfile,
581         binmap_search_new,
582         binmap_search_destroy,
583         binmap_search_get_item
584 };
585
586 static struct map_priv *
587 map_new_binfile(struct map_methods *meth, struct attr **attrs)
588 {
589         struct map_priv *m;
590         struct attr *data=attr_search(attrs, NULL, attr_data);
591         struct file_wordexp *wexp;
592         struct zip_cd *first_cd;
593         char **wexp_data;
594         int *magic,cde_index_size;
595         if (! data)
596                 return NULL;
597
598         wexp=file_wordexp_new(data->u.str);
599         wexp_data=file_wordexp_get_array(wexp);
600         dbg(1,"map_new_binfile %s\n", data->u.str);     
601         *meth=map_methods_binfile;
602
603         m=g_new0(struct map_priv, 1);
604         m->id=++map_id;
605         m->filename=g_strdup(wexp_data[0]);
606         dbg(0,"file_create %s\n", m->filename);
607         m->fi=file_create(m->filename);
608         if (! m->fi) {
609                 dbg(0,"Failed to load %s\n", m->filename);
610                 g_free(m);
611                 return NULL;
612         }
613         file_wordexp_destroy(wexp);
614         magic=(int *)file_data_read(m->fi, 0, 4);
615         *magic = le32_to_cpu(*magic);
616         if (*magic == 0x04034b50) {
617                 cde_index_size=sizeof(struct zip_cd)+sizeof("index")-1;
618                 m->eoc=(struct zip_eoc *)file_data_read(m->fi,m->fi->size-sizeof(struct zip_eoc), sizeof(struct zip_eoc));
619                 eoc_to_cpu(m->eoc);
620                 printf("magic 0x%x\n", m->eoc->zipesig);
621                 m->index_cd=(struct zip_cd *)file_data_read(m->fi,m->fi->size-sizeof(struct zip_eoc)-cde_index_size, cde_index_size);
622                 cd_to_cpu(m->index_cd);
623                 first_cd=(struct zip_cd *)file_data_read(m->fi,m->eoc->zipeofst, sizeof(struct zip_cd));
624                 cd_to_cpu(first_cd);
625                 m->cde_size=sizeof(struct zip_cd)+first_cd->zipcfnl;
626                 m->zip_members=(m->eoc->zipecsz-cde_index_size)/m->cde_size+1;
627                 printf("cde_size %d\n", m->cde_size);
628                 printf("members %d\n",m->zip_members);
629                 printf("0x%x\n", m->eoc->zipesig);
630                 printf("0x%x\n", m->index_cd->zipcensig);
631                 file_data_free(m->fi, (unsigned char *)first_cd);
632         } else 
633                 file_mmap(m->fi);
634         file_data_free(m->fi, (unsigned char *)magic);
635         return m;
636 }
637
638 void
639 plugin_init(void)
640 {
641         dbg(1,"binfile: plugin_init\n");
642         plugin_register_map_type("binfile", map_new_binfile);
643 }
644