1 /*
2 * misc.c - Misc funcitons.
3 *
4 Copyright (C) 2001 Yao Zhang
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * yaoz@users.sourceforge.net
20 */
21 #include <iconv.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "ot.h"
27
read_table(uint8_t * p,uint32_t length,char * file,uint32_t offset)28 void read_table(uint8_t *p, uint32_t length, char *file, uint32_t offset)
29 {
30 FILE *fp;
31
32 fp = fopen(file, "r");
33
34 fseek(fp, offset, SEEK_SET);
35 fread(p, 1, length, fp);
36
37 fclose(fp);
38 }
39
calc_table_checksum(uint8_t * p,uint32_t length)40 uint32_t calc_table_checksum(uint8_t *p, uint32_t length)
41 {
42 int i;
43 uint32_t sum;
44
45 sum = 0;
46 for (i = 0; i < length; i += 4) {
47 sum += p[i] <<24;
48 sum += p[i+1]<<16;
49 sum += p[i+2]<<8;
50 sum += p[i+3];
51 }
52 if (i < length) {
53 sum += p[i] <<24;
54 }
55 if ((i+1) < length) {
56 sum += p[i+1]<<16;
57 }
58 if ((i+2) < length) {
59 sum += p[i+2]<<8;
60 }
61 if ((i+3) < length) {
62 sum += p[i+3];
63 }
64
65 return sum;
66 }
67
to_utf8_string(char * from,char * buffer,int length,char * utf8,int utf8bytes)68 int to_utf8_string(char *from, char *buffer, int length,
69 char *utf8, int utf8bytes)
70 {
71 iconv_t cd;
72 int count;
73 char *s;
74 size_t inbytesleft, outbytesleft;
75 char *inbuf, *outbuf;
76
77 cd = iconv_open("UTF-8", from);
78 if (cd == (iconv_t)-1) {
79 return -1;
80 }
81
82 count = length;
83 s = (char *)calloc(count, 1);
84 if ((strcmp(from, "GBK") == 0)
85 || (strcmp(from, "BIG5") == 0)) {
86 int i;
87
88 /* We need to remove those 0x00s in name string. */
89 count = 0;
90 for (i = 0; i < length; i++) {
91 if (buffer[i] != 0x00) {
92 s[count] = buffer[i];
93 count++;
94 }
95 }
96 } else {
97 memcpy(s, buffer, count);
98 }
99
100 inbytesleft = count;
101 inbuf = s;
102 outbytesleft = utf8bytes;
103 outbuf = utf8;
104
105 iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
106 if (outbytesleft > 0) {
107 *outbuf = '\0';
108 }
109
110 free(s);
111
112 iconv_close(cd);
113
114 return 0;
115 }
116
from_utf8_string(char * to,char * utf8,int utf8bytes,char * buffer,int length)117 int from_utf8_string(char *to, char *utf8, int utf8bytes,
118 char *buffer, int length)
119 {
120 iconv_t cd;
121 int count;
122 uint8_t *s;
123 size_t inbytesleft, outbytesleft;
124 char *inbuf, *outbuf;
125 int outbytes;
126
127 cd = iconv_open(to, "UTF-8");
128 if (cd == (iconv_t)-1) {
129 return -1;
130 }
131
132 count = utf8bytes*2;
133 s = (uint8_t *)calloc(count, 1);
134
135 inbytesleft = utf8bytes;
136 inbuf = utf8;
137 outbytesleft = count;
138 outbuf = (char *)s;
139
140 iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
141 outbytes = count-outbytesleft;
142
143 if ((strcmp(to, "GBK") == 0)
144 || (strcmp(to, "BIG5") == 0)) {
145 int i;
146
147 /* We need to add those 0x00s for ASCII part in name string. */
148 count = 0;
149 i = 0;
150 while (1) {
151 if ((s[i]&0x80) == 0) {
152 buffer[count++] = 0x00;
153 if (count >= length) {
154 break;
155 }
156 buffer[count++] = s[i++];
157 if ((i >= outbytes) || (count >= length)) {
158 break;
159 }
160 } else {
161 buffer[count++] = s[i++];
162 if ((i >= outbytes) || (count >= length)) {
163 break;
164 }
165 buffer[count++] = s[i++];
166 if ((i >= outbytes) || (count >= length)) {
167 break;
168 }
169 }
170 }
171 count = count/2 * 2;
172 } else {
173 count = outbytes;
174 if (count > length) {
175 count = length;
176 }
177 memcpy(buffer, s, count);
178 }
179
180 free(s);
181
182 iconv_close(cd);
183
184 return count;
185 }
186
platform_string(int platformID)187 char *platform_string(int platformID)
188 {
189 char *s;
190
191 s = "(unknown platform)";
192 switch (platformID) {
193 case 0:
194 s = "Unicode";
195 break;
196 case 1:
197 s = "Macintosh";
198 break;
199 case 2:
200 s = "ISO [deprecated]";
201 break;
202 case 3:
203 s = "Microsoft";
204 break;
205 case 4:
206 s = "Custom";
207 break;
208 default:
209 break;
210 }
211
212 return s;
213 }
214
platform_specific_string(int platformID,int platformSpecificID)215 char *platform_specific_string(int platformID, int platformSpecificID)
216 {
217 char *s;
218
219 s = "(unknown platform specific)";
220 if (platformID == 0) { /* Unicode */
221 switch (platformSpecificID) {
222 case 0:
223 s = "Default semantics";
224 break;
225 case 1:
226 s = "Version 1.1 semantics";
227 break;
228 case 2:
229 s = "ISO 10646 1993 semantics (deprecated)";
230 break;
231 case 3:
232 s = "Unicode 2.0 or later semantics";
233 break;
234 default:
235 break;
236 }
237 } else if (platformID == 1) { /* Macintosh */
238 switch (platformSpecificID) {
239 case 0:
240 s = "Roman";
241 break;
242 case 1:
243 s = "Japanese";
244 break;
245 case 2:
246 s = "Traditianal Chinese";
247 break;
248 case 3:
249 s = "Korean";
250 break;
251 case 4:
252 s = "Arabic";
253 break;
254 case 5:
255 s = "Hebrew";
256 break;
257 case 6:
258 s = "Greek";
259 break;
260 case 7:
261 s = "Russian";
262 break;
263 case 8:
264 s = "RSymbol";
265 break;
266 case 9:
267 s = "Devanagari";
268 break;
269 case 10:
270 s = "Gurmukhi";
271 break;
272 case 11:
273 s = "Gujarati";
274 break;
275 case 12:
276 s = "Oriya";
277 break;
278 case 13:
279 s = "Bengali";
280 break;
281 case 14:
282 s = "Tamil";
283 break;
284 case 15:
285 s = "Telugu";
286 break;
287 case 16:
288 s = "Kannada";
289 break;
290 case 17:
291 s = "Malayalam";
292 break;
293 case 18:
294 s = "Sinhalese";
295 break;
296 case 19:
297 s = "Burmese";
298 break;
299 case 20:
300 s = "Khmer";
301 break;
302 case 21:
303 s = "Thai";
304 break;
305 case 22:
306 s = "Laotian";
307 break;
308 case 23:
309 s = "Georgian";
310 break;
311 case 24:
312 s = "Armenian";
313 break;
314 case 25:
315 s = "Simplified Chinese";
316 break;
317 case 26:
318 s = "Tibetan";
319 break;
320 case 27:
321 s = "Mongolian";
322 break;
323 case 28:
324 s = "Geez";
325 break;
326 case 29:
327 s = "Slavic";
328 break;
329 case 30:
330 s = "Vietnamese";
331 break;
332 case 31:
333 s = "Sindhi";
334 break;
335 case 32:
336 s = "(Uninterpreted)";
337 break;
338 default:
339 break;
340 }
341 } else if (platformID == 2) { /* ISO [deprecated] */
342 switch (platformSpecificID) {
343 case 0:
344 s = "7-bit ASCII";
345 break;
346 case 1:
347 s = "ISO 10646";
348 break;
349 case 2:
350 s = "ISO 8859-1";
351 break;
352 default:
353 break;
354 }
355 } else if (platformID == 3) { /* Microsoft */
356 switch (platformSpecificID) {
357 case 0:
358 s = "Symbol";
359 break;
360 case 1:
361 s = "Unicode";
362 break;
363 case 2:
364 s = "ShiftJIS";
365 break;
366 case 3:
367 s = "PRC";
368 break;
369 case 4:
370 s = "Big5";
371 break;
372 case 5:
373 s = "Wansung";
374 break;
375 case 6:
376 s = "Johab";
377 break;
378 case 7:
379 s = "Reserved 7";
380 break;
381 case 8:
382 s = "Reserved 8";
383 break;
384 case 9:
385 s = "Reserved 9";
386 break;
387 case 10:
388 s = "UCS-4";
389 break;
390 default:
391 break;
392 }
393 } else if (platformID == 4) { /* Custom */
394 if ((platformSpecificID >= 0)
395 && (platformSpecificID <= 255)) {
396 s = "OTF Windows NT compatibility mapping";
397 }
398 }
399
400 return s;
401 }
402
language_string(int platformID,int languageID)403 char *language_string(int platformID, int languageID)
404 {
405 char *s;
406
407 s = "(unknown language)";
408 if (platformID == 1) { /* Macintosh */
409 switch (languageID) {
410 case 0:
411 s = "English";
412 break;
413 case 1:
414 s = "French";
415 break;
416 case 2:
417 s = "German";
418 break;
419 case 3:
420 s = "Italian";
421 break;
422 case 4:
423 s = "Dutch";
424 break;
425 case 5:
426 s = "Swedish";
427 break;
428 case 6:
429 s = "Spanish";
430 break;
431 case 7:
432 s = "Danish";
433 break;
434 case 8:
435 s = "Portuguese";
436 break;
437 case 9:
438 s = "Norwegian";
439 break;
440 case 10:
441 s = "Hebrew";
442 break;
443 case 11:
444 s = "Japanese";
445 break;
446 case 12:
447 s = "Arabic";
448 break;
449 case 13:
450 s = "Finnish";
451 break;
452 case 14:
453 s = "Greek";
454 break;
455 case 15:
456 s = "Icelandic";
457 break;
458 case 16:
459 s = "Maltese";
460 break;
461 case 17:
462 s = "Turkish";
463 break;
464 case 18:
465 s = "Croatian";
466 break;
467 case 19:
468 s = "Chinese (Traditional)";
469 break;
470 case 20:
471 s = "Urdu";
472 break;
473 case 21:
474 s = "Hindi";
475 break;
476 case 22:
477 s = "Thai";
478 break;
479 case 23:
480 s = "Korean";
481 break;
482 case 24:
483 s = "Lithuanian";
484 break;
485 case 25:
486 s = "Polish";
487 break;
488 case 26:
489 s = "Hungarian";
490 break;
491 case 27:
492 s = "Estonian";
493 break;
494 case 28:
495 s = "Latvian";
496 break;
497 case 29:
498 s = "Sami";
499 break;
500 case 30:
501 s = "Faroese";
502 break;
503 case 31:
504 s = "Farsi/Persian";
505 break;
506 case 32:
507 s = "Russian";
508 break;
509 case 33:
510 s = "Chinese (Simplified)";
511 break;
512 case 34:
513 s = "Flemish";
514 break;
515 case 35:
516 s = "Irish Gaelic";
517 break;
518 case 36:
519 s = "Albanian";
520 break;
521 case 37:
522 s = "Romanian";
523 break;
524 case 38:
525 s = "Czech";
526 break;
527 case 39:
528 s = "Slovak";
529 break;
530 /*
531 TBD
532 */
533 default:
534 break;
535 }
536 } else if (platformID == 3) { /* Microsoft */
537 switch (languageID) {
538 case 0x0401:
539 s = "Arabic - Saudi Arabia";
540 break;
541 case 0x0801:
542 s = "Arabic - Iraq";
543 break;
544 case 0x0c01:
545 s = "Arabic - Egypt";
546 break;
547 case 0x1001:
548 s = "Arabic - Libya";
549 break;
550 case 0x1401:
551 s = "Arabic - Algeria";
552 break;
553 case 0x1801:
554 s = "Arabic - Morocco";
555 break;
556 case 0x1c01:
557 s = "Arabic - Tunisia";
558 break;
559 case 0x2001:
560 s = "Arabic - Oman";
561 break;
562 case 0x2401:
563 s = "Arabic - Yemen";
564 break;
565 case 0x2801:
566 s = "Arabic - Syria";
567 break;
568 case 0x2c01:
569 s = "Arabic - Jordan";
570 break;
571 case 0x3001:
572 s = "Arabic - Lebanon";
573 break;
574 case 0x3401:
575 s = "Arabic - Kuwait";
576 break;
577 case 0x3801:
578 s = "Arabic - U.A.E.";
579 break;
580 case 0x3c01:
581 s = "Arabic - Bahrain";
582 break;
583 case 0x4001:
584 s = "Arabic - Qatar";
585 break;
586 case 0x0402:
587 s = "Bulgarian - Bulgaria";
588 break;
589 case 0x0403:
590 s = "Catalan - Spain";
591 break;
592 case 0x0404:
593 s = "Chinese - Taiwan";
594 break;
595 case 0x0804:
596 s = "Chinese - PRC";
597 break;
598 case 0x0c04:
599 s = "Chinese - Hong Kong";
600 break;
601 case 0x1004:
602 s = "Chinese - Singapore";
603 break;
604 case 0x1404:
605 s = "Chinese - Macau";
606 break;
607 case 0x0405:
608 s = "Czech - Czech Republic";
609 break;
610 case 0x0406:
611 s = "Danish - Denmark";
612 break;
613 case 0x0407:
614 s = "German - Germany";
615 break;
616 case 0x0807:
617 s = "German - Switzerland";
618 break;
619 case 0x0c07:
620 s = "German - Austria";
621 break;
622 case 0x1007:
623 s = "German - Luxembourg";
624 break;
625 case 0x1407:
626 s = "German - Liechtenstein";
627 break;
628 case 0x0408:
629 s = "Greek - Greece";
630 break;
631 case 0x0409:
632 s = "English - United States";
633 break;
634 case 0x0809:
635 s = "English - United Kingdom";
636 break;
637 case 0x0c09:
638 s = "English - Australia";
639 break;
640 case 0x1009:
641 s = "English - Canada";
642 break;
643 case 0x1409:
644 s = "English - New Zealand";
645 break;
646 case 0x1809:
647 s = "English - Ireland";
648 break;
649 case 0x1c09:
650 s = "English - South Africa";
651 break;
652 case 0x2009:
653 s = "English - Jamaica";
654 break;
655 case 0x2409:
656 s = "English - Caribbean";
657 break;
658 case 0x2809:
659 s = "English - Belize";
660 break;
661 case 0x2c09:
662 s = "English - Trinidad";
663 break;
664 case 0x3009:
665 s = "English - Zimbabwe";
666 break;
667 case 0x3409:
668 s = "English - Philippines";
669 break;
670 /*
671 * TBD
672 */
673 default:
674 break;
675 }
676 }
677
678 return s;
679 }
680
name_string(int nameID)681 char *name_string(int nameID)
682 {
683 char *s;
684
685 s = "(unknown name)";
686 switch(nameID) {
687 case 0:
688 s = "Copyright notice";
689 break;
690 case 1:
691 s = "Font Family";
692 break;
693 case 2:
694 s = "Font Subfamily";
695 break;
696 case 3:
697 s = "Unique subfamily identification";
698 break;
699 case 4:
700 s = "Full name of the font";
701 break;
702 case 5:
703 s = "Version of the name table";
704 break;
705 case 6:
706 s = "PostScript name for the font";
707 break;
708 case 7:
709 s = "Trademark notice";
710 break;
711 case 8:
712 s = "Manufacturer Name";
713 break;
714 case 9:
715 s = "Designer";
716 break;
717 case 10:
718 s = "Description";
719 break;
720 case 11:
721 s = "URL of the font vendor";
722 break;
723 case 12:
724 s = "URL of the font designer";
725 break;
726 case 13:
727 s = "License description";
728 break;
729 case 14:
730 s = "License information URL";
731 break;
732 case 15:
733 s = "Reserved";
734 break;
735 case 16:
736 s = "Preferred Family";
737 break;
738 case 17:
739 s = "Preferred Subfamily";
740 break;
741 case 18:
742 s = "Compatible Full";
743 break;
744 case 19:
745 s = "Sample text";
746 break;
747 default:
748 break;
749 }
750
751 return s;
752 }
753