/[zanavi_public1]/navit/navit/map/garmin_img/garmin_img.c
ZANavi

Contents of /navit/navit/map/garmin_img/garmin_img.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 34693 byte(s)
import files
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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 #include <glib.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <math.h>
25 #include "config.h"
26 #include "plugin.h"
27 #include "data.h"
28 #include "projection.h"
29 #include "map.h"
30 #include "maptype.h"
31 #include "item.h"
32 #include "attr.h"
33 #include "coord.h"
34 #include "transform.h"
35 #include <stdio.h>
36 #include "attr.h"
37 #include "coord.h"
38
39 struct file {
40 FILE *f;
41 int offset;
42 };
43
44
45 int shift=5;
46 int subdiv_next=0x10;
47
48
49 static void *
50 file_read(struct file *f, int offset, int size)
51 {
52 void *ptr;
53 int ret;
54
55 ptr=calloc(size, 1);
56 if (! ptr)
57 return ptr;
58 fseek(f->f, f->offset+offset, SEEK_SET);
59 ret=fread(ptr, size, 1, f->f);
60 if (ret != 1) {
61 printf("fread %d vs %d offset %d+%d(0x%x)\n", ret, size, f->offset, offset,offset);
62 g_assert(1==0);
63 }
64 return ptr;
65 }
66
67 static void
68 file_free(void *ptr)
69 {
70 free(ptr);
71 }
72
73 struct offset_len {
74 int offset;
75 int length;
76 } __attribute ((packed));
77
78 static void
79 dump_offset_len(struct offset_len *off_len)
80 {
81 printf("offset: 0x%x(%d) length 0x%x(%d)\n", off_len->offset, off_len->offset, off_len->length, off_len->length);
82 }
83
84 struct timestamp {
85 short creation_year;
86 char creation_month;
87 char creation_day;
88 char creation_hour;
89 char creation_minute;
90 char creation_second;
91 } __attribute__((packed));
92
93 struct img_header {
94 char xor;
95 char zero1[9];
96 char update_month;
97 char update_year;
98 char zero2[3];
99 char checksum[1];
100 char signature[7];
101 char unknown1[1];
102 char unknown2[2];
103 char unknown3[2];
104 char unknown4[2];
105 char unknown5[2];
106 char zero3[25];
107 struct timestamp ts;
108 char unknown6;
109 char map_file_identifier[7];
110 char unknown12;
111 char map_description1[20];
112 short unknown13;
113 short unknown14;
114 char e1;
115 char e2;
116 char other[413];
117 char zero4[512];
118 char unknown7;
119 char unknown8[11];
120 int file_offset;
121 char unknown9;
122 char unknown10[15];
123 char unknown11[480];
124 } __attribute__((packed));
125
126 static void
127 dump_ts(struct timestamp *ts)
128 {
129 printf("%d-%02d-%02d %02d:%02d:%02d\n", ts->creation_year, ts->creation_month, ts->creation_day, ts->creation_hour, ts->creation_minute, ts->creation_second);
130 }
131
132 #if 0
133 static void
134 dump_img(struct img_header *img_hdr)
135 {
136 printf("signature: '%s'\n", img_hdr->signature);
137 printf("creation: ");
138 dump_ts(&img_hdr->ts);
139 printf("map_file_identifier: '%s'\n", img_hdr->map_file_identifier);
140 printf("file_offset: 0x%x\n", img_hdr->file_offset);
141 printf("e1: 0x%x(%d)\n", img_hdr->e1, img_hdr->e1);
142 printf("e2: 0x%x(%d)\n", img_hdr->e2, img_hdr->e2);
143 printf("offset 0x%x\n", (int) &img_hdr->e1 - (int) img_hdr);
144 printf("size %d\n", sizeof(*img_hdr));
145 }
146 #endif
147
148 struct fat_block {
149 char flag;
150 char filename[8];
151 char type[3];
152 int size;
153 char zero1;
154 char part;
155 char zero[14];
156 unsigned short blocks[240];
157 } __attribute__((packed));
158
159 #if 0
160 static void
161 dump_fat_block(struct fat_block *fat_blk)
162 {
163 int i=0;
164 char name[9];
165 char type[4];
166 printf("flag: 0x%x(%d)\n", fat_blk->flag, fat_blk->flag);
167 strcpy(name, fat_blk->filename);
168 name[8]='\0';
169 strcpy(type, fat_blk->type);
170 type[3]='\0';
171 printf("name: '%s.%s'\n", name, type);
172 printf("size: 0x%x(%d)\n", fat_blk->size, fat_blk->size);
173 printf("part: 0x%x(%d)\n", fat_blk->part, fat_blk->part);
174 printf("blocks: ");
175 while (i < 240) {
176 printf("0x%x(%d) ",fat_blk->blocks[i], fat_blk->blocks[i]);
177 if (fat_blk->blocks[i] == 0xffff)
178 break;
179 i++;
180 }
181 printf("size: %d\n", sizeof(*fat_blk));
182
183 }
184 #endif
185
186 struct file_header {
187 short header_len;
188 char type[10];
189 char unknown1;
190 char unknown2;
191 struct timestamp ts;
192 } __attribute__((packed));
193
194 static void
195 dump_file(struct file_header *fil_hdr)
196 {
197 printf("header_len: %d\n", fil_hdr->header_len);
198 printf("type: '%s'\n", fil_hdr->type);
199 printf("unknown1: 0x%x(%d)\n", fil_hdr->unknown1, fil_hdr->unknown1);
200 printf("unknown2: 0x%x(%d)\n", fil_hdr->unknown2, fil_hdr->unknown2);
201 printf("creation: ");
202 dump_ts(&fil_hdr->ts);
203 printf("size %d\n", sizeof(*fil_hdr));
204 }
205
206 struct region_header {
207 struct file_header fil_hdr;
208 struct offset_len offset_len;
209 } __attribute__((packed));
210
211 #if 0
212 static void
213 dump_region(struct region_header *rgn_hdr)
214 {
215 dump_offset_len(&rgn_hdr->offset_len);
216 }
217 #endif
218
219 struct map_priv {
220 int id;
221 char *filename;
222 };
223
224 struct map_rect_priv {
225 struct coord_rect r;
226 int limit;
227
228 struct file tre;
229 struct tree_header *tre_hdr;
230 struct file rgn;
231 struct region_header *rgn_hdr;
232 struct file lbl;
233 struct label_header *lbl_hdr;
234 char *label;
235
236 int subdiv_level_count;
237 int subdiv_pos;
238 char *subdiv;
239
240 int rgn_offset;
241 int rgn_end;
242 struct rgn_point *pnt;
243 struct rgn_poly *ply;
244 unsigned char *ply_data;
245 int ply_bitpos;
246 int ply_bitcount;
247 int ply_lngbits;
248 int ply_latbits;
249 int ply_lng;
250 int ply_lat;
251 int ply_lnglimit;
252 int ply_latlimit;
253 int ply_lngsign;
254 int ply_latsign;
255 struct offset_len rgn_items[4];
256 int rgn_type;
257
258 int count;
259
260 FILE *f;
261 long pos;
262 char line[256];
263 int attr_pos;
264 enum attr_type attr_last;
265 char attrs[256];
266 char attr[256];
267 double lat,lng;
268 char lat_c,lng_c;
269 int eoc;
270 struct map_priv *m;
271 struct item item;
272 };
273
274 static int map_id;
275
276 static int
277 contains_coord(char *line)
278 {
279 return g_ascii_isdigit(line[0]);
280 }
281
282 static int debug=1;
283
284 static int
285 get_tag(char *line, char *name, int *pos, char *ret)
286 {
287 int len,quoted;
288 char *p,*e,*n;
289
290 if (debug)
291 printf("get_tag %s from %s\n", name, line);
292 if (! name)
293 return 0;
294 len=strlen(name);
295 if (pos)
296 p=line+*pos;
297 else
298 p=line;
299 for(;;) {
300 while (*p == ' ') {
301 p++;
302 }
303 if (! *p)
304 return 0;
305 n=p;
306 e=index(p,'=');
307 if (! e)
308 return 0;
309 p=e+1;
310 quoted=0;
311 while (*p) {
312 if (*p == ' ' && !quoted)
313 break;
314 if (*p == '"')
315 quoted=1-quoted;
316 p++;
317 }
318 if (e-n == len && !strncmp(n, name, len)) {
319 e++;
320 len=p-e;
321 if (e[0] == '"') {
322 e++;
323 len-=2;
324 }
325 strncpy(ret, e, len);
326 ret[len]='\0';
327 if (pos)
328 *pos=p-line;
329 return 1;
330 }
331 }
332 return 0;
333 }
334
335 static void
336 get_line(struct map_rect_priv *mr)
337 {
338 mr->pos=ftell(mr->f);
339 fgets(mr->line, 256, mr->f);
340 }
341
342 static void
343 map_destroy_garmin_img(struct map_priv *m)
344 {
345 if (debug)
346 printf("map_destroy_garmin_img\n");
347 g_free(m);
348 }
349
350 static char *
351 map_charset_garmin_img(struct map_priv *m)
352 {
353 return "iso8859-1";
354 }
355
356 static enum projection
357 map_projection_garmin_img(struct map_priv *m)
358 {
359 return projection_garmin;
360 }
361
362 struct label_data_offset {
363 struct offset_len offset_len;
364 char multiplier;
365 char data;
366 } __attribute ((packed));
367
368 #if 0
369 static void
370 dump_label_data_offset(struct label_data_offset *lbl_dat)
371 {
372 dump_offset_len(&lbl_dat->offset_len);
373 printf("multiplier 0x%x(%d)\n", lbl_dat->multiplier, lbl_dat->multiplier);
374 printf("data 0x%x(%d)\n", lbl_dat->data, lbl_dat->data);
375 }
376 #endif
377
378 struct label_data {
379 struct offset_len offset_len;
380 short size;
381 int zero;
382 } __attribute ((packed));
383
384 static void
385 dump_label_data(struct label_data *lbl_dat)
386 {
387 dump_offset_len(&lbl_dat->offset_len);
388 printf("size 0x%x(%d)\n", lbl_dat->size, lbl_dat->size);
389 }
390
391 struct tree_header {
392 struct file_header fil_hdr;
393 char boundary[12];
394 struct offset_len level;
395 struct offset_len subdivision;
396 struct label_data copyright;
397 struct offset_len tre7;
398 short unknown1;
399 char zero1;
400 struct label_data polyline;
401 struct label_data polygon;
402 struct label_data point;
403 int mapid;
404 };
405
406 static void
407 dump_tree_header(struct tree_header *tre_hdr)
408 {
409 printf("tree_header:\n");
410 dump_file(&tre_hdr->fil_hdr);
411 printf("level: "); dump_offset_len(&tre_hdr->level);
412 printf("subdivision: "); dump_offset_len(&tre_hdr->subdivision);
413 printf("copyright: "); dump_label_data(&tre_hdr->copyright);
414 printf("polyline: "); dump_label_data(&tre_hdr->polyline);
415 printf("polygon: "); dump_label_data(&tre_hdr->polygon);
416 printf("point: "); dump_label_data(&tre_hdr->point);
417 printf("len: 0x%x(%d)\n", sizeof(*tre_hdr), sizeof(*tre_hdr));
418 }
419
420 struct label_header {
421 struct file_header fil_hdr;
422 struct label_data_offset label;
423 struct label_data country;
424 struct label_data region;
425 struct label_data city;
426 struct label_data poi_index;
427 struct label_data_offset poi_properties;
428 short zero1;
429 char zero2;
430 struct label_data poi_types;
431 struct label_data zip;
432 struct label_data hway;
433 struct label_data exit;
434 struct label_data hway_data;
435 int unknown1;
436 short unknown2;
437 struct offset_len sort_descriptor;
438 struct label_data lbl13;
439 struct label_data lbl14;
440 } __attribute((packed));
441
442 #if 0
443 static void
444 dump_label(struct label_header *lbl_hdr)
445 {
446 dump_file(&lbl_hdr->fil_hdr);
447 printf("label:\n");
448 dump_label_data_offset(&lbl_hdr->label);
449 printf("country:\n");
450 dump_label_data(&lbl_hdr->country);
451 printf("region:\n");
452 dump_label_data(&lbl_hdr->region);
453 printf("city:\n");
454 dump_label_data(&lbl_hdr->city);
455 printf("poi_index:\n");
456 dump_label_data(&lbl_hdr->poi_index);
457 printf("poi_properties:\n");
458 dump_label_data_offset(&lbl_hdr->poi_properties);
459 printf("poi_types:\n");
460 dump_label_data(&lbl_hdr->poi_types);
461 printf("zip:\n");
462 dump_label_data(&lbl_hdr->zip);
463 printf("hway:\n");
464 dump_label_data(&lbl_hdr->hway);
465 printf("exit:\n");
466 dump_label_data(&lbl_hdr->exit);
467 printf("hway_data:\n");
468 dump_label_data(&lbl_hdr->hway_data);
469 printf("lbl13:\n");
470 dump_label_data(&lbl_hdr->lbl13);
471 printf("lbl14:\n");
472 dump_label_data(&lbl_hdr->lbl14);
473 printf("len: 0x%x(%d)\n", sizeof(*lbl_hdr), sizeof(*lbl_hdr));
474 }
475 #endif
476
477 struct triple {
478 unsigned char data[3];
479 } __attribute((packed));
480
481 static unsigned int
482 triple_u(struct triple *t)
483 {
484 return t->data[0] | (t->data[1] << 8) | (t->data[2] << 16);
485 }
486
487 static int
488 triple(struct triple *t)
489 {
490 int ret=t->data[0] | (t->data[1] << 8) | (t->data[2] << 16);
491 if (ret > 1<<23)
492 ret=ret-(1<<24);
493 return ret;
494 }
495
496 static void
497 dump_triple_u(struct triple *t)
498 {
499 int val=triple_u(t);
500 printf("0x%x(%d)\n", val, val);
501 }
502
503 struct tcoord {
504 struct triple lng,lat;
505 } __attribute((packed));
506
507 static void
508 dump_tcoord(struct tcoord *t)
509 {
510 printf ("0x%x(%d),0x%x(%d)\n", triple_u(&t->lng), triple_u(&t->lng), triple_u(&t->lat), triple_u(&t->lat));
511 }
512
513 struct level {
514 unsigned char zoom;
515 unsigned char bits_per_coord;
516 unsigned short subdivisions;
517 } __attribute((packed));
518
519 static void
520 dump_level(struct level *lvl)
521 {
522 printf("level:\n");
523 printf("\tzoom 0x%x(%d)\n", lvl->zoom, lvl->zoom);
524 printf("\tbits_per_coord 0x%x(%d)\n", lvl->bits_per_coord, lvl->bits_per_coord);
525 printf("\tsubdivisions 0x%x(%d)\n", lvl->subdivisions, lvl->subdivisions);
526 }
527
528 struct subdivision {
529 struct triple rgn_offset;
530 unsigned char types;
531 struct tcoord center;
532 unsigned short width;
533 unsigned short height;
534 unsigned short next;
535 } __attribute((packed));
536
537 static void
538 dump_subdivision(struct subdivision *sub)
539 {
540 printf("subdivision:\n");
541 printf("\trgn_offset: "); dump_triple_u(&sub->rgn_offset);
542 printf("\ttypes: 0x%x(%d)\n", sub->types, sub->types);
543 printf("\tcenter: "); dump_tcoord(&sub->center);
544 printf("\tsize: 0x%x(%d)x0x%x(%d) %s\n",sub->width & 0x7fff, sub->width & 0x7fff, sub->height, sub->height, sub->width & 0x8000 ? "Terminating" : "");
545 printf("\tnext: 0x%x(%d)\n",sub->next, sub->next);
546
547 printf("\tlen: 0x%x(%d)\n", sizeof(*sub), sizeof(*sub));
548 }
549
550 struct rgn_point {
551 unsigned char info;
552 struct triple lbl_offset;
553 short lng_delta;
554 short lat_delta;
555 unsigned char subtype;
556 } __attribute((packed));
557
558 static void
559 dump_point(struct rgn_point *pnt)
560 {
561 printf("point:\n");
562 printf("\tinfo 0x%x(%d)\n", pnt->info, pnt->info);
563 printf("\tlbl_offset 0x%x(%d)\n", triple_u(&pnt->lbl_offset), triple_u(&pnt->lbl_offset));
564 printf("\tlng_delta 0x%x(%d)\n", pnt->lng_delta, pnt->lng_delta);
565 printf("\tlat_delta 0x%x(%d)\n", pnt->lat_delta, pnt->lat_delta);
566 printf("\tsubtype 0x%x(%d)\n", pnt->subtype, pnt->subtype);
567 printf("\tlen: 0x%x(%d)\n", sizeof(*pnt), sizeof(*pnt));
568 }
569
570 struct rgn_poly {
571 unsigned char info;
572 struct triple lbl_offset;
573 short lng_delta;
574 short lat_delta;
575 union {
576 struct {
577 unsigned char bitstream_len;
578 unsigned char bitstream_info;
579 } __attribute((packed)) p1;
580 struct {
581 unsigned short bitstream_len;
582 unsigned char bitstream_info;
583 } __attribute((packed)) p2;
584 } __attribute((packed)) u;
585 } __attribute((packed));
586
587 static void
588 dump_poly(struct rgn_poly *ply)
589 {
590 printf("poly:\n");
591 printf("\tinfo 0x%x(%d)\n", ply->info, ply->info);
592 printf("\tlbl_offset 0x%x(%d)\n", triple_u(&ply->lbl_offset), triple_u(&ply->lbl_offset));
593 printf("\tlng_delta 0x%x(%d)\n", ply->lng_delta, ply->lng_delta);
594 printf("\tlat_delta 0x%x(%d)\n", ply->lat_delta, ply->lat_delta);
595 if (ply->info & 0x80) {
596 printf("\tbitstream_len 0x%x(%d)\n", ply->u.p2.bitstream_len, ply->u.p2.bitstream_len);
597 printf("\tbitstream_info 0x%x(%d)\n", ply->u.p2.bitstream_info, ply->u.p2.bitstream_info);
598 } else {
599 printf("\tbitstream_len 0x%x(%d)\n", ply->u.p1.bitstream_len, ply->u.p1.bitstream_len);
600 printf("\tbitstream_info 0x%x(%d)\n", ply->u.p1.bitstream_info, ply->u.p1.bitstream_info);
601 }
602 printf("\tlen: 0x%x(%d)\n", sizeof(*ply), sizeof(*ply));
603 }
604
605 static void
606 dump_hex(void *ptr, int len)
607 {
608 unsigned char *c=ptr;
609 while (len--) {
610 printf("%02x ", *c++);
611 }
612 printf("\n");
613 }
614
615 static void
616 dump_hex_r(void *ptr, int len, int rec)
617 {
618 unsigned char *c=ptr;
619 int l=rec;
620 while (len--) {
621 printf("%02x ", *c++);
622 if (! --l) {
623 printf("\n");
624 l=rec;
625 }
626 }
627 printf("\n");
628 }
629
630 #if 0
631 static void
632 dump_label_offset(struct map_rect_priv *mr, int offset)
633 {
634 void *p;
635 p=file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128);
636 printf("%s\n", (char *)p);
637 }
638 #endif
639
640
641 #if 0
642 static void
643 dump_region_item(struct subdivision *sub, struct file *rgn, struct map_rect_priv *mr)
644 {
645 int offset,item_offset,i,j;
646 unsigned short count=0;
647 unsigned short *offsets[4];
648 unsigned short *file_offsets;
649 struct rgn_point *pnt;
650
651 offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset;
652 file_offsets=file_read(rgn, offset, 90*sizeof(unsigned short));
653 printf("0x%x ", offset); dump_hex(file_offsets, 90);
654 for (i=0 ; i < 4 ; i++) {
655 printf("i=%d\n", i);
656 if (sub->types & (0x10 << i)) {
657 if (count) {
658 offsets[i]=&file_offsets[count-1];
659 } else
660 offsets[i]=&count;
661 count++;
662 } else
663 offsets[i]=NULL;
664
665 }
666 count--;
667 count*=2;
668 for (i=0 ; i < 4 ; i++) {
669 printf("i=%d\n", i);
670 if (offsets[i]) {
671 printf("offset[%d]=0x%x(%d)\n", i, *offsets[i], *offsets[i]);
672 switch (i) {
673 case 0:
674 printf("point\n");
675 break;
676 case 1:
677 printf("indexed point\n");
678 break;
679 case 2:
680 printf("polyline\n");
681 break;
682 case 3:
683 printf("polygon\n");
684 break;
685 }
686 item_offset=offset+*offsets[i];
687 switch (i) {
688 case 0:
689 case 1:
690 for (j = 0 ; j < 10 ; j++) {
691 struct coord_geo g;
692 char buffer[1024];
693 double conv=180.0/(1UL<<23);
694 pnt=file_read(rgn, item_offset, sizeof(*pnt)*20);
695 // printf("0x%x ", item_offset); dump_hex(pnt, 32);
696 dump_point(pnt);
697 g.lng=(triple(&sub->center.lng)+(pnt->lng_delta << shift))*conv;
698 g.lat=(triple(&sub->center.lat)+(pnt->lat_delta << shift))*conv;
699 printf("%f %f\n", g.lng, g.lat);
700 coord_format(g.lat,g.lng,DEGREES_MINUTES_SECONDS,
701 buffer,sizeof(buffer));
702 printf("%s\n", buffer);
703 dump_label_offset(mr, triple_u(&pnt->lbl_offset));
704 if (pnt->info & 0x80)
705 item_offset+=sizeof(*pnt);
706 else
707 item_offset+=sizeof(*pnt)-1;
708 }
709 }
710 } else {
711 printf("offset[%d] doesn't exist\n", i);
712 }
713 }
714 file_free(file_offsets);
715 }
716
717 #endif
718
719 static void
720 dump_levels(struct map_rect_priv *mr)
721 {
722 int i,offset;
723 struct level *lvl;
724
725 offset=mr->tre_hdr->level.offset;
726 for (i = 0 ; i < mr->tre_hdr->level.length/sizeof(*lvl) ; i++) {
727 lvl=file_read(&mr->tre, offset, sizeof(*lvl));
728 dump_level(lvl);
729 offset+=sizeof(*lvl);
730 }
731 }
732
733 #if 0
734 static void
735 dump_tree(struct file *f, struct file *rgn, struct map_rect_priv *mr)
736 {
737 struct tree_header *tre_hdr;
738 struct subdivision *sub;
739 int i,offset;
740
741 tre_hdr=file_read(f, 0, sizeof(*tre_hdr));
742 dump_tree_header(tre_hdr);
743 offset=tre_hdr->subdivision.offset;
744 sub=file_read(f, offset, sizeof(*sub));
745 dump_subdivision(sub);
746 offset+=sizeof(*sub);
747 for (i = 1 ; i < tre_hdr->subdivision.length/sizeof(*sub) ; i++) {
748 printf("i=%d\n", i);
749 sub=file_read(f, offset, sizeof(*sub));
750 dump_subdivision(sub);
751 dump_region_item(sub, rgn, mr);
752 if (sub->width & 0x8000)
753 break;
754 offset+=sizeof(*sub);
755 }
756 file_free(tre_hdr);
757 }
758 #endif
759
760 #if 0
761 static void
762 dump_labels(struct file *f)
763 {
764 struct label_header *lbl_hdr;
765
766 lbl_hdr=file_read(f, 0, sizeof(*lbl_hdr));
767 printf("**labels**\n");
768 dump_label(lbl_hdr);
769 file_free(lbl_hdr);
770 #if 0
771 labels=alloca(lbl_hdr.label_length);
772 file_read(f, lbl_hdr.label_offset, labels, lbl_hdr.label_length);
773 l=labels;
774 while (l < labels+lbl_hdr.label_length) {
775 printf("'%s'(%d)\n", l, strlen(l));
776 l+=strlen(l)+1;
777 }
778 #endif
779
780 }
781 #endif
782
783 static void
784 garmin_img_coord_rewind(void *priv_data)
785 {
786 }
787
788 static void
789 parse_line(struct map_rect_priv *mr)
790 {
791 int pos=0;
792 sscanf(mr->line,"%lf %c %lf %c %n",&mr->lat,&mr->lat_c,&mr->lng,&mr->lng_c,&pos);
793 if (pos < strlen(mr->line)) {
794 strcpy(mr->attrs, mr->line+pos);
795 }
796 }
797
798 static int
799 get_bits(struct map_rect_priv *mr, int bits)
800 {
801 unsigned long ret;
802 ret=L(*((unsigned long *)(mr->ply_data+mr->ply_bitpos/8)));
803 ret >>= (mr->ply_bitpos & 7);
804 ret &= (1 << bits)-1;
805 mr->ply_bitpos+=bits;
806 return ret;
807 }
808
809 static int
810 garmin_img_coord_get(void *priv_data, struct coord *c, int count)
811 {
812 struct map_rect_priv *mr=priv_data;
813 struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos);
814 int ret=0;
815 int debug=0;
816 if (debug)
817 printf("garmin_img_coord_get %d\n",count);
818 if (debug)
819 dump_subdivision(sub);
820 while (count--) {
821 if (mr->rgn_type < 2) {
822 c->x=triple(&sub->center.lng)+(mr->pnt->lng_delta << shift);
823 c->y=triple(&sub->center.lat)+(mr->pnt->lat_delta << shift);
824 } else {
825 if (! mr->ply_bitpos) {
826 if (mr->ply->info & 0x80) {
827 mr->ply_bitcount=mr->ply->u.p2.bitstream_len*8;
828 mr->ply_lngbits=mr->ply->u.p2.bitstream_info & 0xf;
829 mr->ply_latbits=mr->ply->u.p2.bitstream_info >> 4;
830 } else {
831 mr->ply_bitcount=mr->ply->u.p1.bitstream_len*8;
832 mr->ply_lngbits=mr->ply->u.p1.bitstream_info & 0xf;
833 mr->ply_latbits=mr->ply->u.p1.bitstream_info >> 4;
834 }
835 if (mr->ply_lngbits <= 9)
836 mr->ply_lngbits+=2;
837 if (mr->ply_latbits <= 9)
838 mr->ply_latbits+=2;
839 if (! get_bits(mr,1)) {
840 mr->ply_lngbits+=1;
841 mr->ply_lngsign=0;
842 } else
843 if (get_bits(mr, 1))
844 mr->ply_lngsign=-1;
845 else
846 mr->ply_lngsign=1;
847 if (! get_bits(mr,1)) {
848 mr->ply_latbits+=1;
849 mr->ply_latsign=0;
850 } else
851 if (get_bits(mr, 1))
852 mr->ply_latsign=-1;
853 else
854 mr->ply_latsign=1;
855 mr->ply_lnglimit=1 << (mr->ply_lngbits-1);
856 mr->ply_latlimit=1 << (mr->ply_latbits-1);
857 mr->ply_lng=mr->ply->lng_delta;
858 mr->ply_lat=mr->ply->lat_delta;
859 if (debug)
860 printf("lngbits %d latbits %d bitcount %d\n", mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount);
861 c->x=0;
862 c->y=0;
863 } else {
864 if (mr->ply_bitpos + mr->ply_lngbits + mr->ply_latbits > mr->ply_bitcount) {
865 if (debug)
866 printf("out of bits %d + %d + %d >= %d\n", mr->ply_bitpos, mr->ply_lngbits, mr->ply_latbits, mr->ply_bitcount);
867 return ret;
868 }
869 c->x=0;
870 c->y=0;
871 int x,y;
872 for (;;) {
873 x=get_bits(mr,mr->ply_lngbits);
874 if (debug)
875 printf("x %d ", x);
876 if (mr->ply_lngsign || x != mr->ply_lnglimit)
877 break;
878 c->x += x-1;
879 }
880 if (mr->ply_lngsign) {
881 c->x=x*mr->ply_lngsign;
882 } else {
883 if (x >= mr->ply_lnglimit)
884 c->x = x - (mr->ply_lnglimit << 1) - c->x;
885 else
886 c->x +=x;
887 }
888 for (;;) {
889 y=get_bits(mr,mr->ply_latbits);
890 if (debug)
891 printf("y %d ", y);
892 if (mr->ply_latsign || y != mr->ply_latlimit)
893 break;
894 c->y += y-1;
895 }
896 if (mr->ply_latsign) {
897 c->y=y*mr->ply_latsign;
898 } else {
899 if (y >= mr->ply_latlimit)
900 c->y = y - (mr->ply_latlimit << 1) - c->y;
901 else
902 c->y +=y;
903 }
904 mr->ply_lng += c->x;
905 mr->ply_lat += c->y;
906 }
907 if (debug)
908 printf(": x %d y %d\n", c->x, c->y);
909
910 c->x=triple(&sub->center.lng)+(mr->ply_lng << shift);
911 c->y=triple(&sub->center.lat)+(mr->ply_lat << shift);
912 }
913 #if 0
914 c->x-=0x6f160;
915 c->y-=0x181f59;
916 c->x+=0x168ca1;
917 c->y+=0x68d815;
918 #endif
919 c++;
920 ret++;
921 if (mr->rgn_type < 2)
922 return ret;
923 }
924 return ret;
925 }
926
927 static char *
928 get_label_offset(struct map_rect_priv *mr, int offset)
929 {
930 g_assert(offset < mr->lbl_hdr->label.offset_len.length);
931 return file_read(&mr->lbl, mr->lbl_hdr->label.offset_len.offset+offset, 128);
932 }
933
934 static void
935 garmin_img_attr_rewind(void *priv_data)
936 {
937 }
938
939 static int
940 garmin_img_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
941 {
942 struct map_rect_priv *mr=priv_data;
943 int debug=0;
944
945 if (debug)
946 printf("garmin_img_attr_get\n");
947 if (attr_type == attr_label) {
948 if (debug)
949 printf("garmin_img_attr_get label\n");
950 attr->type=attr_type;
951 if (mr->rgn_type < 2) {
952 if (mr->label)
953 file_free(mr->label);
954 mr->label=get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff);
955 attr->u.str=mr->label;
956 } else {
957 attr->u.str="";
958 }
959 return 1;
960 }
961 return 0;
962 }
963
964 static struct item_methods methods_garmin_img = {
965 garmin_img_coord_rewind,
966 garmin_img_coord_get,
967 garmin_img_attr_rewind,
968 garmin_img_attr_get,
969 };
970
971 static int rgn_next_type(struct map_rect_priv *mr)
972 {
973 while (mr->rgn_type < 3) {
974 mr->rgn_type++;
975 if (mr->rgn_items[mr->rgn_type].offset && mr->rgn_items[mr->rgn_type].length != 0) {
976 mr->rgn_offset=mr->rgn_items[mr->rgn_type].offset;
977 mr->rgn_end=mr->rgn_offset+mr->rgn_items[mr->rgn_type].length;
978 return 0;
979 }
980 }
981 return 1;
982 }
983
984 static int
985 sub_next(struct map_rect_priv *mr, int next)
986 {
987 int i,offset,first=-1,last=-1,count=-1;
988 int end;
989 unsigned short *offsets;
990 int debug=0;
991
992 if (mr->subdiv_level_count <= 0)
993 return 1;
994 if (debug)
995 printf("%d left\n", mr->subdiv_level_count);
996 mr->subdiv_level_count--;
997
998 #if 0
999 if (next && mr->subdiv[mr->subdiv_current].width & 0x8000)
1000 return 1;
1001 #endif
1002 if (debug)
1003 dump_hex_r(mr->subdiv+mr->subdiv_pos, 64, 14);
1004 mr->subdiv_pos+=next;
1005 if (debug)
1006 printf("subdiv_pos 0x%x\n", mr->subdiv_pos);
1007 if (mr->subdiv_pos > mr->tre_hdr->subdivision.length)
1008 return 1;
1009 struct subdivision *sub=(struct subdivision *)(mr->subdiv+mr->subdiv_pos);
1010 offset=triple_u(&sub->rgn_offset)+mr->rgn_hdr->offset_len.offset;
1011 if (debug) {
1012 printf("offset=0x%x\n", offset);
1013 dump_subdivision(sub);
1014 }
1015 offsets=file_read(&mr->rgn, offset, 3*sizeof(unsigned short));
1016
1017 if (! next)
1018 next=subdiv_next;
1019 if (mr->subdiv_pos+next < mr->tre_hdr->subdivision.length)
1020 end=triple_u(&((struct subdivision *)(mr->subdiv+mr->subdiv_pos+next))->rgn_offset)+mr->rgn_hdr->offset_len.offset;
1021 else
1022 end=mr->rgn_hdr->offset_len.offset+mr->rgn_hdr->offset_len.length;
1023 if (debug) {
1024 dump_subdivision(sub);
1025 dump_hex(offsets, 6);
1026 }
1027 for (i=0 ; i < 4 ; i++) {
1028 if (debug)
1029 printf("i=%d ", i);
1030 if (sub->types & (0x10 << i)) {
1031 if (debug)
1032 printf("+ ");
1033 if (first == -1) {
1034 first=i;
1035 mr->rgn_items[i].offset=offset;
1036 if (debug)
1037 printf("\n");
1038 } else {
1039 mr->rgn_items[i].offset=offset+offsets[count];
1040 if (debug)
1041 printf("0x%x\n", offsets[count]);
1042 mr->rgn_items[last].length=mr->rgn_items[i].offset-mr->rgn_items[last].offset;
1043 }
1044 last=i;
1045 count++;
1046 } else {
1047 if (debug)
1048 printf("-\n");
1049 mr->rgn_items[i].offset=0;
1050 mr->rgn_items[i].length=0;
1051 }
1052
1053 }
1054 if (first != -1) {
1055 mr->rgn_items[first].offset+=count*2;
1056 mr->rgn_items[first].length-=count*2;
1057 mr->rgn_items[last].length=end-mr->rgn_items[last].offset;
1058 }
1059 if (debug) {
1060 for (i=0 ; i < 4 ; i++) {
1061 printf("%d 0x%x 0x%x\n", i, mr->rgn_items[i].offset, mr->rgn_items[i].length);
1062 }
1063 }
1064 mr->rgn_type=-1;
1065 rgn_next_type(mr);
1066 if (debug)
1067 printf("*** offset 0x%x\n", mr->rgn_offset);
1068 file_free(offsets);
1069 return 0;
1070 }
1071
1072 int item_count;
1073
1074 static struct map_rect_priv *
1075 map_rect_new_garmin_img(struct map_priv *map, struct coord_rect *r, struct layer *layers, int limit)
1076 {
1077 struct map_rect_priv *mr;
1078 struct img_header img;
1079
1080 if (debug)
1081 printf("map_rect_new_garmin_img\n");
1082 mr=g_new0(struct map_rect_priv, 1);
1083 mr->m=map;
1084 if (r)
1085 mr->r=*r;
1086 mr->limit=limit;
1087 mr->item.id_hi=0;
1088 mr->item.id_lo=0;
1089 mr->item.meth=&methods_garmin_img;
1090 mr->item.priv_data=mr;
1091 mr->f=fopen(map->filename, "r");
1092
1093 fread(&img, sizeof(img), 1, mr->f);
1094 #if 0
1095 dump_img(&img);
1096 for (i = 0 ; i < (img.file_offset-sizeof(img))/sizeof(fat_blk) ; i++) {
1097 fread(&fat_blk, sizeof(fat_blk), 1, mr->f);
1098 if (!fat_blk.flag)
1099 break;
1100 dump_fat_block(&fat_blk);
1101 }
1102 #endif
1103 mr->rgn.offset=0xa*2048;
1104 mr->rgn.f=mr->f;
1105 mr->rgn_hdr=file_read(&mr->rgn, 0, sizeof(*mr->rgn_hdr));
1106
1107 mr->tre.offset=0x62b*2048;
1108 mr->tre.f=mr->f;
1109 mr->tre_hdr=file_read(&mr->tre, 0, sizeof(*mr->tre_hdr));
1110
1111 mr->lbl.offset=0x64a*2048;
1112 mr->lbl.f=mr->f;
1113 mr->lbl_hdr=file_read(&mr->lbl, 0, sizeof(*mr->lbl_hdr));
1114
1115 mr->subdiv=file_read(&mr->tre, mr->tre_hdr->subdivision.offset, mr->tre_hdr->subdivision.length);
1116 #if 0
1117 dump_hex_r(mr->subdiv, mr->tre_hdr->subdivision.length, 16);
1118 #endif
1119 dump_tree_header(mr->tre_hdr);
1120
1121 dump_levels(mr);
1122
1123
1124 printf("limit=%d\n", limit);
1125 if (limit < 3) {
1126 mr->subdiv_pos=0;
1127 mr->subdiv_level_count=1;
1128 shift=11;
1129 } else if (limit < 6) {
1130 mr->subdiv_pos=1*sizeof(struct subdivision);
1131 mr->subdiv_level_count=5;
1132 shift=9;
1133 } else if (limit < 8) {
1134 mr->subdiv_pos=6*sizeof(struct subdivision);
1135 mr->subdiv_level_count=9;
1136 shift=7;
1137 } else if (limit < 10) {
1138 mr->subdiv_pos=15*sizeof(struct subdivision);
1139 mr->subdiv_level_count=143;
1140 shift=5;
1141 } else {
1142 mr->subdiv_pos=158*sizeof(struct subdivision);
1143 mr->subdiv_level_count=4190;
1144 shift=2;
1145 subdiv_next=14;
1146 }
1147
1148 #if 0
1149 mr->rgn_offset=triple_u(&mr->subdiv[mr->subdiv_current].rgn_offset)+mr->rgn_hdr->offset_len.offset+4;
1150 mr->rgn_type=1;
1151 mr->rgn_end=mr->rgn_offset+20*8;
1152 #endif
1153 mr->count=0;
1154 item_count=0;
1155
1156 #if 0
1157 printf("*** offset 0x%x\n", 0x656c-mr->rgn.offset);
1158 printf("*** offset 0x%x\n", mr->rgn_offset);
1159 #endif
1160 #if 1
1161 sub_next(mr, 0);
1162 #endif
1163 #if 0
1164 {
1165 struct rgn_point *pnt;
1166 int i;
1167 int offset=0x65cc;
1168 for (i = 0 ; i < 26 ; i++) {
1169 pnt=file_read(&mr->rgn, 0x656c+8*i-mr->rgn.offset, sizeof(*pnt));
1170 // dump_hex(pnt, sizeof(*pnt));
1171 dump_point(pnt);
1172 dump_label_offset(mr, triple_u(&pnt->lbl_offset));
1173 }
1174 }
1175 exit(0);
1176 #endif
1177 #if 0
1178 dump_tree(&mr->tre,&mr->rgn,mr);
1179 #endif
1180
1181 #if 0
1182 f.offset=0x64a*2048;
1183 f.f=mr->f;
1184 dump_labels(&f);
1185 #endif
1186 #if 0
1187 fseek(mr->f, img.file_offset, SEEK_SET);
1188 fread(&fil, sizeof(fil), 1, mr->f);
1189 dump_file(&fil);
1190 fread(&rgn, sizeof(rgn), 1, mr->f);
1191 dump_region(&rgn);
1192 fseek(mr->f, rgn.data_length, SEEK_CUR);
1193 fread(&fil, sizeof(fil), 1, mr->f);
1194 dump_file(&fil);
1195 #endif
1196 return mr;
1197 }
1198
1199
1200 static void
1201 map_rect_destroy_garmin_img(struct map_rect_priv *mr)
1202 {
1203 fclose(mr->f);
1204 g_free(mr);
1205 }
1206
1207
1208 static struct item *
1209 map_rect_get_item_garmin_img(struct map_rect_priv *mr)
1210 {
1211 char *p,type[256];
1212 int ptype;
1213 int debug=0;
1214
1215 item_count++;
1216
1217 if (debug)
1218 printf("map_rect_get_item_garmin_img\n");
1219 for (;;) {
1220 if (mr->rgn_offset < mr->rgn_end) {
1221 if (debug)
1222 printf("data available\n");
1223 if (mr->rgn_type >= 2) {
1224 int len;
1225 if (debug)
1226 printf("polyline %d\n", mr->count);
1227 if (mr->ply)
1228 file_free(mr->ply);
1229 mr->ply=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->ply)*3);
1230 if(triple_u(&mr->ply->lbl_offset) >= mr->lbl_hdr->label.offset_len.length) {
1231 printf("item_count %d\n", item_count);
1232 dump_poly(mr->ply);
1233 dump_hex(mr->ply, 32);
1234 printf("%d vs %d\n", triple_u(&mr->ply->lbl_offset), mr->lbl_hdr->label.offset_len.length);
1235 }
1236 g_assert(triple_u(&mr->ply->lbl_offset) < mr->lbl_hdr->label.offset_len.length);
1237 if (debug) {
1238 dump_hex(mr->ply, 16);
1239 dump_poly(mr->ply);
1240 }
1241 if (mr->ply_data)
1242 file_free(mr->ply_data);
1243 mr->rgn_offset+=10;
1244 if (mr->ply->info & 0x80) {
1245 mr->rgn_offset++;
1246 len=mr->ply->u.p2.bitstream_len;
1247 } else
1248 len=mr->ply->u.p1.bitstream_len;
1249
1250 mr->ply_data=file_read(&mr->rgn, mr->rgn_offset, len);
1251 mr->rgn_offset += len;
1252 mr->ply_bitpos=0;
1253 // dump_hex(mr->ply_data, 32);
1254 if (mr->rgn_type == 3) {
1255 switch(mr->ply->info & 0x7f) {
1256 case 0x1: /* large urban area (>200k) */
1257 mr->item.type=type_town_poly;
1258 break;
1259 case 0xd: /* reservation */
1260 mr->item.type=type_park_poly;
1261 break;
1262 case 0xe: /* airport runway */
1263 mr->item.type=type_airport_poly;
1264 break;
1265 case 0x14: /* national park */
1266 mr->item.type=type_park_poly;
1267 break;
1268 case 0x32: /* sea */
1269 case 0x3d: /* large lake (77-250km2) */
1270 case 0x4c: /* intermittend water */
1271 mr->item.type=type_water_poly;
1272 break;
1273 case 0x4b: /* background */
1274 continue;
1275 default:
1276 printf("unknown polygon: 0x%x\n", mr->ply->info);
1277 mr->item.type=type_street_3_city;
1278 }
1279 } else {
1280 switch(mr->ply->info & 0x3f) {
1281 case 0x1: /* major highway */
1282 mr->item.type=type_highway_land;
1283 break;
1284 case 0x2: /* principal highway */
1285 mr->item.type=type_street_3_land;
1286 break;
1287 case 0x6: /* residental street */
1288 mr->item.type=type_street_2_land;
1289 break;
1290 case 0x16: /* walkway/trail */
1291 mr->item.type=type_street_1_land;
1292 break;
1293 case 0x1e: /* international boundary */
1294 mr->item.type=type_border_country;
1295 break;
1296 case 0x20: /* minor land contour 1/10 */
1297 mr->item.type=type_height_line_1;
1298 break;
1299 case 0x21: /* major land contour 1/2 */
1300 mr->item.type=type_height_line_2;
1301 break;
1302 default:
1303 printf("unknown polyline: 0x%x\n", mr->ply->info);
1304 mr->item.type=type_street_3_city;
1305 }
1306 }
1307 return &mr->item;
1308 }
1309 if (mr->pnt)
1310 file_free(mr->pnt);
1311 mr->pnt=file_read(&mr->rgn, mr->rgn_offset, sizeof(*mr->pnt));
1312 mr->item.type=type_none;
1313 int subtype=mr->pnt->subtype;
1314 if (mr->pnt->lbl_offset.data[2] & 0x80)
1315 mr->rgn_offset+=9;
1316 else {
1317 mr->rgn_offset+=8;
1318 subtype=0;
1319 }
1320 switch(mr->pnt->info) {
1321 case 0x3: /* large city 2-5M */
1322 mr->item.type=type_town_label_2e6;
1323 break;
1324 case 0xa: /* small city/town 10-20k */
1325 mr->item.type=type_town_label_1e4;
1326 break;
1327 case 0xd: /* settlement 1-2K */
1328 mr->item.type=type_town_label_1e3;
1329 break;
1330 case 0x11: /* settlement less 100 */
1331 mr->item.type=type_town_label_5e1;
1332 break;
1333 case 0x1c:
1334 switch(subtype) {
1335 case 0x01:
1336 mr->item.type=type_poi_wreck;
1337 break;
1338 }
1339 break;
1340 case 0x20:
1341 mr->item.type=type_highway_exit;
1342 break;
1343 case 0x25:
1344 mr->item.type=type_poi_toll_booth;
1345 break;
1346 case 0x2b:
1347 switch(subtype) {
1348 case 0x01:
1349 mr->item.type=type_poi_hotel;
1350 break;
1351 case 0x03:
1352 mr->item.type=type_poi_camp_rv;
1353 break;
1354 }
1355 break;
1356 case 0x2c:
1357 switch(subtype) {
1358 case 0x00:
1359 mr->item.type=type_poi_attraction;
1360 break;
1361 case 0x02:
1362 mr->item.type=type_poi_museum_history;
1363 break;
1364 }
1365 break;
1366 case 0x2e:
1367 mr->item.type=type_poi_shopping;
1368 break;
1369 case 0x2f:
1370 switch(subtype) {
1371 case 0x01:
1372 mr->item.type=type_poi_fuel;
1373 break;
1374 case 0x07:
1375 mr->item.type=type_poi_car_dealer_parts;
1376 break;
1377 case 0x0b:
1378 mr->item.type=type_poi_car_parking;
1379 break;
1380 case 0x15:
1381 mr->item.type=type_poi_public_utilities;
1382 break;
1383 }
1384 break;
1385 case 0x30:
1386 switch(subtype) {
1387 case 0x02:
1388 mr->item.type=type_poi_hospital;
1389 break;
1390 }
1391 break;
1392 case 0x43:
1393 mr->item.type=type_poi_marina;
1394 break;
1395 case 0x46:
1396 mr->item.type=type_poi_bar;
1397 break;
1398 case 0x48:
1399 mr->item.type=type_poi_camping;
1400 break;
1401 case 0x49:
1402 mr->item.type=type_poi_park;
1403 break;
1404 case 0x4a:
1405 mr->item.type=type_poi_picnic;
1406 break;
1407 case 0x59: /* airport */
1408 mr->item.type=type_poi_airport;
1409 break;
1410 case 0x64:
1411 switch(subtype) {
1412 case 0x1:
1413 mr->item.type=type_poi_bridge;
1414 break;
1415 case 0x2:
1416 mr->item.type=type_poi_building;
1417 break;
1418 case 0x15:
1419 mr->item.type=type_town_ghost;
1420 break;
1421 }
1422 break;
1423 case 0x65:
1424 switch(subtype) {
1425 case 0x0:
1426 mr->item.type=type_poi_water_feature;
1427 break;
1428 case 0xc:
1429 mr->item.type=type_poi_island;
1430 break;
1431 case 0xd:
1432 mr->item.type=type_poi_lake;
1433 break;
1434 }
1435 break;
1436 case 0x66:
1437 switch(subtype) {
1438 case 0x0:
1439 mr->item.type=type_poi_land_feature;
1440 break;
1441 case 0x6:
1442 mr->item.type=type_poi_cape;
1443 break;
1444 case 0x14:
1445 mr->item.type=type_poi_rock;
1446 break;
1447 }
1448 break;
1449 }
1450 if (mr->item.type == type_none) {
1451 printf("unknown point: 0x%x 0x%x\n", mr->pnt->info, mr->pnt->subtype);
1452 dump_point(mr->pnt);
1453 printf("label: %s\n", get_label_offset(mr, triple_u(&mr->pnt->lbl_offset) & 0x3fffff));
1454 mr->item.type=type_town_label;
1455 }
1456 return &mr->item;
1457 }
1458 if (debug)
1459 printf("out of data for type\n");
1460 if (rgn_next_type(mr)) {
1461 if (debug)
1462 printf("out of data for region\n");
1463 if (sub_next(mr, subdiv_next)) {
1464 if (debug)
1465 printf("out of data for subdivision\n");
1466 return NULL;
1467 }
1468 }
1469 }
1470 }
1471
1472 static struct item *
1473 map_rect_get_item_byid_garmin_img(struct map_rect_priv *mr, int id_hi, int id_lo)
1474 {
1475 fseek(mr->f, id_lo, SEEK_SET);
1476 get_line(mr);
1477 mr->item.id_hi=id_hi;
1478 return map_rect_get_item_garmin_img(mr);
1479 }
1480
1481 static struct map_methods map_methods_garmin_img = {
1482 projection_garmin,
1483 "iso8859-1",
1484 map_destroy_garmin_img,
1485 map_charset_garmin_img,
1486 map_projection_garmin_img,
1487 map_rect_new_garmin_img,
1488 map_rect_destroy_garmin_img,
1489 map_rect_get_item_garmin_img,
1490 map_rect_get_item_byid_garmin_img,
1491 };
1492
1493 static struct map_priv *
1494 map_new_garmin_img(struct map_methods *meth, struct attr **attrs)
1495 {
1496 struct map_priv *m;
1497 struct attr *data=attr_search(attrs, NULL, attr_data);
1498 if (! data)
1499 return NULL;
1500
1501 *meth=map_methods_garmin_img;
1502 m=g_new(struct map_priv, 1);
1503 m->id=++map_id;
1504 m->filename=g_strdup(data->u.str);
1505 return m;
1506 }
1507
1508 void
1509 plugin_init(void)
1510 {
1511 plugin_register_map_type("garmin_img", map_new_garmin_img);
1512 }
1513

   
Visit the ZANavi Wiki