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