added missing files.
[swftools.git] / pdf2swf / ttf2pt1 / ttf.c
1 /*
2  * True Type Font to Adobe Type 1 font converter 
3  * By Mark Heath <mheath@netspace.net.au> 
4  * Based on ttf2pfa by Andrew Weeks <ccsaw@bath.ac.uk> 
5  * With help from Frank M. Siegert <fms@this.net> 
6  *
7  * see COPYRIGHT
8  *
9  */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <time.h>
17 #include <ctype.h>
18 #include <math.h>
19
20 #ifndef WIN32
21 #       include <unistd.h>
22 #       include <netinet/in.h>
23 #else
24 #       include "windows.h"
25 #endif
26
27 #include "ttf.h"
28 #include "pt1.h"
29 #include "global.h"
30
31 /* prototypes of call entries */
32 static void openfont(char *fname, char *arg);
33 static void closefont( void);
34 static int getnglyphs ( void);
35 static int glnames( GLYPH *glyph_list);
36 static void glmetrics( GLYPH *glyph_list);
37 static int glenc( GLYPH *glyph_list, int *encoding, int *unimap);
38 static void fnmetrics( struct font_metrics *fm);
39 static void glpath( int glyphno, GLYPH *glyph_list);
40 static void kerning( GLYPH *glyph_list);
41
42 /* globals */
43
44 /* front-end descriptor */
45 struct frontsw ttf_sw = {
46         /*name*/       "ttf",
47         /*descr*/      "built-in TTF support",
48         /*suffix*/     { "ttf" },
49         /*open*/       openfont,
50         /*close*/      closefont,
51         /*nglyphs*/    getnglyphs,
52         /*glnames*/    glnames,
53         /*glmetrics*/  glmetrics,
54         /*glenc*/      glenc,
55         /*fnmetrics*/  fnmetrics,
56         /*glpath*/     glpath,
57         /*kerning*/    kerning,
58 };
59
60 /* statics */
61
62 static FILE    *ttf_file;
63 static int      ttf_nglyphs, long_offsets;
64
65 static TTF_DIRECTORY *directory;
66 static TTF_DIR_ENTRY *dir_entry;
67 static char    *filebuffer;
68 static char    *filebuffer_end;
69 static TTF_NAME *name_table = NULL;
70 static TTF_NAME_REC *name_record;
71 static TTF_HEAD *head_table = NULL;
72 static TTF_HHEA *hhea_table = NULL;
73 static TTF_KERN *kern_table = NULL;
74 static TTF_CMAP *cmap_table = NULL;
75 static LONGHORMETRIC *hmtx_table = NULL;
76 static TTF_GLYF *glyf_table;
77 static BYTE    *glyf_start = NULL;
78 static TTF_MAXP *maxp_table = NULL;
79 static TTF_POST_HEAD *post_table = NULL;
80 static union {
81         USHORT *sp;
82         ULONG  *lp;
83 } loca_table;
84 #define short_loca_table        loca_table.sp
85 #define long_loca_table         loca_table.lp
86
87 static short    cmap_n_segs;
88 static USHORT  *cmap_seg_start, *cmap_seg_end;
89 static short   *cmap_idDelta, *cmap_idRangeOffset;
90 static TTF_CMAP_FMT0  *encoding0;
91 static int             enc_type;
92
93 static char     name_buffer[2000];
94 static char    *name_fields[8];
95
96 static int enc_found_ms, enc_found_mac;
97
98 static char    *mac_glyph_names[258] = {
99         ".notdef", ".null", "CR",
100         "space", "exclam", "quotedbl", "numbersign",
101         "dollar", "percent", "ampersand", "quotesingle",
102         "parenleft", "parenright", "asterisk", "plus",
103         "comma", "hyphen", "period", "slash",
104         "zero", "one", "two", "three",
105         "four", "five", "six", "seven",
106         "eight", "nine", "colon", "semicolon",
107         "less", "equal", "greater", "question",
108         "at", "A", "B", "C",
109         "D", "E", "F", "G",
110         "H", "I", "J", "K",
111         "L", "M", "N", "O",
112         "P", "Q", "R", "S",
113         "T", "U", "V", "W",
114         "X", "Y", "Z", "bracketleft",
115         "backslash", "bracketright", "asciicircum", "underscore",
116         "grave", "a", "b", "c",
117         "d", "e", "f", "g",
118         "h", "i", "j", "k",
119         "l", "m", "n", "o",
120         "p", "q", "r", "s",
121         "t", "u", "v", "w",
122         "x", "y", "z", "braceleft",
123         "bar", "braceright", "asciitilde", "Adieresis",
124         "Aring", "Ccedilla", "Eacute", "Ntilde",
125         "Odieresis", "Udieresis", "aacute", "agrave",
126         "acircumflex", "adieresis", "atilde", "aring",
127         "ccedilla", "eacute", "egrave", "ecircumflex",
128         "edieresis", "iacute", "igrave", "icircumflex",
129         "idieresis", "ntilde", "oacute", "ograve",
130         "ocircumflex", "odieresis", "otilde", "uacute",
131         "ugrave", "ucircumflex", "udieresis", "dagger",
132         "degree", "cent", "sterling", "section",
133         "bullet", "paragraph", "germandbls", "registered",
134         "copyright", "trademark", "acute", "dieresis",
135         "notequal", "AE", "Oslash", "infinity",
136         "plusminus", "lessequal", "greaterequal", "yen",
137         "mu", "partialdiff", "summation", "product",
138         "pi", "integral", "ordfeminine", "ordmasculine",
139         "Omega", "ae", "oslash", "questiondown",
140         "exclamdown", "logicalnot", "radical", "florin",
141         "approxequal", "increment", "guillemotleft", "guillemotright",
142         "ellipsis", "nbspace", "Agrave", "Atilde",
143         "Otilde", "OE", "oe", "endash",
144         "emdash", "quotedblleft", "quotedblright", "quoteleft",
145         "quoteright", "divide", "lozenge", "ydieresis",
146         "Ydieresis", "fraction", "currency", "guilsinglleft",
147         "guilsinglright", "fi", "fl", "daggerdbl",
148         "periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
149         "Acircumflex", "Ecircumflex", "Aacute", "Edieresis",
150         "Egrave", "Iacute", "Icircumflex", "Idieresis",
151         "Igrave", "Oacute", "Ocircumflex", "applelogo",
152         "Ograve", "Uacute", "Ucircumflex", "Ugrave",
153         "dotlessi", "circumflex", "tilde", "macron",
154         "breve", "dotaccent", "ring", "cedilla",
155         "hungarumlaut", "ogonek", "caron", "Lslash",
156         "lslash", "Scaron", "scaron", "Zcaron",
157         "zcaron", "brokenbar", "Eth", "eth",
158         "Yacute", "yacute", "Thorn", "thorn",
159         "minus", "multiply", "onesuperior", "twosuperior",
160         "threesuperior", "onehalf", "onequarter", "threequarters",
161         "franc", "Gbreve", "gbreve", "Idot",
162         "Scedilla", "scedilla", "Cacute", "cacute",
163         "Ccaron", "ccaron", "dmacron"
164 };
165
166 /* other prototypes */
167 static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
168         double *matrix, int level);
169 static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, 
170         double *matrix);
171 static double f2dot14( short x);
172
173 /* get the TTF description table address and length for this index */
174
175 static void
176 get_glyf_table(
177         int glyphno,
178         TTF_GLYF **tab,
179         int *len
180 )
181 {
182         if(tab!=NULL) {
183                 if (long_offsets) {
184                         *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
185                 } else {
186                         *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
187                 }
188         }
189         if(len!=NULL) {
190                 if (long_offsets) {
191                         *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
192                 } else {
193                         *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
194                 }
195         }
196 }
197
198 static void
199 handle_name(void)
200 {
201         int             j, k, lang, len, platform;
202         char           *p, *string_area;
203         char           *nbp = name_buffer;
204         int             found3 = 0;
205
206         string_area = (char *) name_table + ntohs(name_table->offset);
207         name_record = &(name_table->nameRecords);
208
209         for (j = 0; j < 8; j++) {
210                 name_fields[j] = ""; 
211         }
212
213         for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
214
215                 platform = ntohs(name_record->platformID);
216
217                 if (platform == 3) {
218
219                         found3 = 1;
220                         lang = ntohs(name_record->languageID) & 0xff;
221                         len = ntohs(name_record->stringLength);
222                         if (lang == 0 || lang == 9) {
223                                 k = ntohs(name_record->nameID);
224                                 if (k < 8) {
225                                         name_fields[k] = nbp;
226
227                                         p = string_area + ntohs(name_record->stringOffset);
228                                         for (k = 0; k < len; k++) {
229                                                 if (p[k] != '\0') {
230                                                         if (p[k] == '(') {
231                                                                 *nbp = '[';
232                                                         } else if (p[k] == ')') {
233                                                                 *nbp = ']';
234                                                         } else {
235                                                                 *nbp = p[k];
236                                                         }
237                                                         nbp++;
238                                                 }
239                                         }
240                                         *nbp = '\0';
241                                         nbp++;
242                                 }
243                         }
244                 }
245                 name_record++;
246         }
247
248         string_area = (char *) name_table + ntohs(name_table->offset);
249         name_record = &(name_table->nameRecords);
250
251         if (!found3) {
252                 for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
253
254                         platform = ntohs(name_record->platformID);
255
256                         if (platform == 1) {
257
258                                 found3 = 1;
259                                 lang = ntohs(name_record->languageID) & 0xff;
260                                 len = ntohs(name_record->stringLength);
261                                 if (lang == 0 || lang == 9) {
262                                         k = ntohs(name_record->nameID);
263                                         if (k < 8) {
264                                                 name_fields[k] = nbp;
265
266                                                 p = string_area + ntohs(name_record->stringOffset);
267                                                 for (k = 0; k < len; k++) {
268                                                         if (p[k] != '\0') {
269                                                                 if (p[k] == '(') {
270                                                                         *nbp = '[';
271                                                                 } else if (p[k] == ')') {
272                                                                         *nbp = ']';
273                                                                 } else {
274                                                                         *nbp = p[k];
275                                                                 }
276                                                                 nbp++;
277                                                         }
278                                                 }
279                                                 *nbp = '\0';
280                                                 nbp++;
281                                         }
282                                 }
283                         }
284                         name_record++;
285                 }
286         }
287         if (!found3) {
288                 fprintf(stderr, "**** Cannot decode font name fields ****\n");
289                 exit(1);
290         }
291         if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
292                 name_fields[4] = name_fields[1];
293         }
294         if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */
295                 name_fields[6] = name_fields[4];
296                 if (name_fields[6][0] == 0) { /* oops, empty again */
297                         WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n");
298                         name_fields[6] = "Unknown";
299                 }
300         }
301         p = name_fields[6];
302         /* must not start with a digit */
303         if(isdigit(*p))
304                 *p+= 'A'-'0'; /* change to a letter */
305         while (*p != '\0') {
306                 if (!isalnum(*p) || *p=='_') {
307                         *p = '-';
308                 }
309                 p++;
310         }
311 }
312
313 static void
314 handle_head(void)
315 {
316         long_offsets = ntohs(head_table->indexToLocFormat);
317         if (long_offsets != 0 && long_offsets != 1) {
318                 fprintf(stderr, "**** indexToLocFormat wrong ****\n");
319                 exit(1);
320         }
321 }
322
323 /* limit the recursion level to avoid cycles */
324 #define MAX_COMPOSITE_LEVEL 20
325
326 static void
327 draw_composite_glyf(
328         GLYPH *g,
329         GLYPH *glyph_list,
330         int glyphno,
331         double *orgmatrix,
332         int level
333 )
334 {
335         int len;
336         short           ncontours;
337         USHORT          flagbyte, glyphindex;
338         double          arg1, arg2;
339         BYTE           *ptr;
340         char           *bptr;
341         SHORT          *sptr;
342         double          matrix[6], newmatrix[6];
343
344         get_glyf_table(glyphno, &glyf_table, &len);
345
346         if(len<=0) /* nothing to do */
347                 return;
348
349         ncontours = ntohs(glyf_table->numberOfContours);
350         if (ncontours >= 0) { /* simple case */
351                 draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
352                 return;
353         }
354
355         if(ISDBG(COMPOSITE) && level ==0)
356                 fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name,
357                         orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3],
358                         orgmatrix[4], orgmatrix[5]);
359
360         /* complex case */
361         if(level >= MAX_COMPOSITE_LEVEL) {
362                 WARNING_1 fprintf(stderr, 
363                         "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
364                         g->name, level);
365                 return;
366         }
367
368         ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
369         sptr = (SHORT *) ptr;
370         do {
371                 flagbyte = ntohs(*sptr);
372                 sptr++;
373                 glyphindex = ntohs(*sptr);
374                 sptr++;
375
376                 if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
377                         arg1 = (short)ntohs(*sptr);
378                         sptr++;
379                         arg2 = (short)ntohs(*sptr);
380                         sptr++;
381                 } else {
382                         bptr = (char *) sptr;
383                         arg1 = (signed char) bptr[0];
384                         arg2 = (signed char) bptr[1];
385                         sptr++;
386                 }
387                 matrix[1] = matrix[2] = 0.0;
388
389                 if (flagbyte & WE_HAVE_A_SCALE) {
390                         matrix[0] = matrix[3] = f2dot14(*sptr);
391                         sptr++;
392                 } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
393                         matrix[0] = f2dot14(*sptr);
394                         sptr++;
395                         matrix[3] = f2dot14(*sptr);
396                         sptr++;
397                 } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
398                         matrix[0] = f2dot14(*sptr);
399                         sptr++;
400                         matrix[2] = f2dot14(*sptr);
401                         sptr++;
402                         matrix[1] = f2dot14(*sptr);
403                         sptr++;
404                         matrix[3] = f2dot14(*sptr);
405                         sptr++;
406                 } else {
407                         matrix[0] = matrix[3] = 1.0;
408                 }
409
410                 /*
411                  * See *
412                  * http://fonts.apple.com/TTRefMan/RM06/Chap6g
413                  * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
414                  */
415
416                 if (fabs(matrix[0]) > fabs(matrix[1]))
417                         matrix[4] = fabs(matrix[0]);
418                 else
419                         matrix[4] = fabs(matrix[1]);
420                 if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
421                         matrix[4] *= 2.0;
422
423                 if (fabs(matrix[2]) > fabs(matrix[3]))
424                         matrix[5] = fabs(matrix[2]);
425                 else
426                         matrix[5] = fabs(matrix[3]);
427                 if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
428                         matrix[5] *= 2.0;
429
430                 /*
431                  * fprintf (stderr,"Matrix Opp %hd
432                  * %hd\n",arg1,arg2);
433                  */
434 #if 0
435                 fprintf(stderr, "Matrix: %f %f %f %f %f %f\n",
436                  matrix[0], matrix[1], matrix[2], matrix[3],
437                         matrix[4], matrix[5]);
438                 fprintf(stderr, "Offset: %f %f (%s)\n",
439                         arg1, arg2,
440                         ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
441 #endif
442
443                 if (flagbyte & ARGS_ARE_XY_VALUES) {
444                         matrix[4] *= arg1;
445                         matrix[5] *= arg2;
446                 } else {
447                         WARNING_1 fprintf(stderr, 
448                                 "*** Glyph %s: reusing scale from another glyph is unsupported\n",
449                                 g->name);
450                         /*
451                          * must extract values from a glyph
452                          * but it seems to be too much pain
453                          * and it's not clear now that it
454                          * would be really used in any
455                          * interesting font
456                          */
457                 }
458
459                 /* at this point arg1,arg2 contain what logically should be matrix[4,5] */
460
461                 /* combine matrices */
462
463                 newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
464                 newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
465
466                 newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
467                 newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
468
469                 newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4];
470                 newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5];
471
472                 if(ISDBG(COMPOSITE)) {
473                         fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
474                                 level+1, ' ', level, glyph_list[glyphindex].name,
475                                 matrix[0], matrix[1], matrix[2], matrix[3],
476                                 matrix[4], matrix[5]);
477                         fprintf(stderr, "%*c        = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n",
478                                 level+1, ' ',
479                                 newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
480                                 newmatrix[4], newmatrix[5]);
481                 }
482                 draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
483
484         } while (flagbyte & MORE_COMPONENTS);
485 }
486
487 static void
488 draw_simple_glyf(
489         GLYPH *g,
490         GLYPH *glyph_list,
491         int glyphno,
492         double *matrix
493 )
494 {
495         int             i, j, k, k1, len, first, cs, ce;
496         /* We assume that hsbw always sets to(0, 0) */
497         double          xlast = 0, ylast = 0;
498         int             finished, nguide, contour_start, contour_end;
499         short           ncontours, n_inst, last_point;
500         USHORT         *contour_end_pt;
501         BYTE           *ptr;
502 #define GLYFSZ  2000
503         short           xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
504         double          xcoord[GLYFSZ], ycoord[GLYFSZ];
505         BYTE            flags[GLYFSZ];
506         double          tx, ty;
507         int             needreverse = 0;        /* transformation may require
508                                                  * that */
509         GENTRY         *lge;
510
511         lge = g->lastentry;
512
513         get_glyf_table(glyphno, &glyf_table, &len);
514
515         if (len <= 0) {
516                 WARNING_1 fprintf(stderr,
517                         "**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
518                         g->name,
519                         glyph_list[glyphno].name);
520                 return;
521         }
522         ncontours = ntohs(glyf_table->numberOfContours);
523         if (ncontours < 0) {
524                 WARNING_1 fprintf(stderr,
525                         "**** Composite glyph %s refers to composite glyph %s, ignored\n",
526                         g->name,
527                         glyph_list[glyphno].name);
528                 return;
529         }
530         contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
531
532         last_point = ntohs(contour_end_pt[ncontours - 1]);
533         n_inst = ntohs(contour_end_pt[ncontours]);
534
535         ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
536         j = k = 0;
537         while (k <= last_point) {
538                 flags[k] = ptr[j];
539
540                 if (ptr[j] & REPEAT) {
541                         for (k1 = 0; k1 < ptr[j + 1]; k1++) {
542                                 k++;
543                                 flags[k] = ptr[j];
544                         }
545                         j++;
546                 }
547                 j++;
548                 k++;
549         }
550
551         for (k = 0; k <= last_point; k++) {
552                 if (flags[k] & XSHORT) {
553                         if (flags[k] & XSAME) {
554                                 xrel[k] = ptr[j];
555                         } else {
556                                 xrel[k] = -ptr[j];
557                         }
558                         j++;
559                 } else if (flags[k] & XSAME) {
560                         xrel[k] = 0.0;
561                 } else {
562                         xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
563                         j += 2;
564                 }
565                 if (k == 0) {
566                         xabs[k] = xrel[k];
567                 } else {
568                         xabs[k] = xrel[k] + xabs[k - 1];
569                 }
570
571         }
572
573         for (k = 0; k <= last_point; k++) {
574                 if (flags[k] & YSHORT) {
575                         if (flags[k] & YSAME) {
576                                 yrel[k] = ptr[j];
577                         } else {
578                                 yrel[k] = -ptr[j];
579                         }
580                         j++;
581                 } else if (flags[k] & YSAME) {
582                         yrel[k] = 0;
583                 } else {
584                         yrel[k] = ptr[j] * 256 + ptr[j + 1];
585                         j += 2;
586                 }
587                 if (k == 0) {
588                         yabs[k] = yrel[k];
589                 } else {
590                         yabs[k] = yrel[k] + yabs[k - 1];
591                 }
592         }
593
594         if (matrix) {
595                 for (i = 0; i <= last_point; i++) {
596                         tx = xabs[i];
597                         ty = yabs[i];
598                         xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]);
599                         ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]);
600                 }
601         } else {
602                 for (i = 0; i <= last_point; i++) {
603                         xcoord[i] = fscale(xabs[i]);
604                         ycoord[i] = fscale(yabs[i]);
605                 }
606         }
607
608         i = j = 0;
609         first = 1;
610
611         while (i <= ntohs(contour_end_pt[ncontours - 1])) {
612                 contour_end = ntohs(contour_end_pt[j]);
613
614                 if (first) {
615                         fg_rmoveto(g, xcoord[i], ycoord[i]);
616                         xlast = xcoord[i];
617                         ylast = ycoord[i];
618                         contour_start = i;
619                         first = 0;
620                 } else if (flags[i] & ONOROFF) {
621                         fg_rlineto(g, xcoord[i], ycoord[i]);
622                         xlast = xcoord[i];
623                         ylast = ycoord[i];
624                 } else {
625                         cs = i - 1;
626                         finished = nguide = 0;
627                         while (!finished) {
628                                 if (i == contour_end + 1) {
629                                         ce = contour_start;
630                                         finished = 1;
631                                 } else if (flags[i] & ONOROFF) {
632                                         ce = i;
633                                         finished = 1;
634                                 } else {
635                                         i++;
636                                         nguide++;
637                                 }
638                         }
639
640                         switch (nguide) {
641                         case 0:
642                                 fg_rlineto(g, xcoord[ce], ycoord[ce]);
643                                 xlast = xcoord[ce];
644                                 ylast = ycoord[ce];
645                                 break;
646
647                         case 1:
648                                 fg_rrcurveto(g,
649                                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
650                                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
651                                       (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0,
652                                       (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0,
653                                             xcoord[ce],
654                                             ycoord[ce]
655                                         );
656                                 xlast = xcoord[ce];
657                                 ylast = ycoord[ce];
658
659                                 break;
660
661                         case 2:
662                                 fg_rrcurveto(g,
663                                      (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0,
664                                      (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0,
665                                       (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0,
666                                       (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0,
667                                             xcoord[ce],
668                                             ycoord[ce]
669                                         );
670                                 xlast = xcoord[ce];
671                                 ylast = ycoord[ce];
672                                 break;
673
674                         case 3:
675                                 fg_rrcurveto(g,
676                                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
677                                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
678                                   (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
679                                   (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
680                                       (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
681                                       (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
682                                         );
683
684                                 fg_rrcurveto(g,
685                                   (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0,
686                                   (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0,
687                                   (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0,
688                                   (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0,
689                                       (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0,
690                                       (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0
691                                         );
692
693                                 fg_rrcurveto(g,
694                                   (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0,
695                                   (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0,
696                                       (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0,
697                                       (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0,
698                                             xcoord[ce],
699                                             ycoord[ce]
700                                         );
701                                 ylast = ycoord[ce];
702                                 xlast = xcoord[ce];
703
704                                 break;
705
706                         default:
707                                 k1 = cs + nguide;
708                                 fg_rrcurveto(g,
709                                       (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0,
710                                       (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0,
711                                   (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0,
712                                   (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0,
713                                       (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0,
714                                       (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0
715                                         );
716
717                                 for (k = cs + 2; k <= k1 - 1; k++) {
718                                         fg_rrcurveto(g,
719                                         (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0,
720                                         (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0,
721                                         (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0,
722                                         (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0,
723                                             (xcoord[k] + xcoord[k + 1]) / 2.0,
724                                              (ycoord[k] + ycoord[k + 1]) / 2.0
725                                                 );
726
727                                 }
728
729                                 fg_rrcurveto(g,
730                                       (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0,
731                                       (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0,
732                                           (2.0 * xcoord[k1] + xcoord[ce]) / 3.0,
733                                           (2.0 * ycoord[k1] + ycoord[ce]) / 3.0,
734                                             xcoord[ce],
735                                             ycoord[ce]
736                                         );
737                                 xlast = xcoord[ce];
738                                 ylast = ycoord[ce];
739
740                                 break;
741                         }
742                 }
743                 if (i >= contour_end) {
744                         g_closepath(g);
745                         first = 1;
746                         i = contour_end + 1;
747                         j++;
748                 } else {
749                         i++;
750                 }
751         }
752
753         if (matrix) {
754                 /* guess whether do we need to reverse the results */
755
756                 double             x[3], y[3];
757                 int                max = 0, from, to;
758
759                 /* transform a triangle going in proper direction */
760                 /*
761                  * the origin of triangle is in (0,0) so we know it in
762                  * advance
763                  */
764
765                 x[0] = y[0] = 0;
766                 x[1] = matrix[0] * 0 + matrix[2] * 300;
767                 y[1] = matrix[1] * 0 + matrix[3] * 300;
768                 x[2] = matrix[0] * 300 + matrix[2] * 0;
769                 y[2] = matrix[1] * 300 + matrix[3] * 0;
770
771                 /* then find the topmost point */
772                 for (i = 0; i < 3; i++)
773                         if (y[i] > y[max])
774                                 max = i;
775                 from = (max + 3 - 1) % 3;
776                 to = (max + 1) % 3;
777
778                 needreverse = 0;
779
780                 /* special cases for horizontal lines */
781                 if (y[max] == y[from]) {
782                         if (x[max] < y[from])
783                                 needreverse = 1;
784                 } else if (y[to] == y[from]) {
785                         if (x[to] < x[max])
786                                 needreverse = 1;
787                 } else {        /* generic case */
788                         if ((x[to] - x[max]) * (y[max] - y[from])
789                             > (x[max] - x[from]) * (y[to] - y[max]))
790                                 needreverse = 1;
791                 }
792
793                 if (needreverse) {
794                         if (lge) {
795                                 assertpath(lge->next, __FILE__, __LINE__, g->name);
796                                 reversepathsfromto(lge->next, NULL);
797                         } else {
798                                 assertpath(g->entries, __FILE__, __LINE__, g->name);
799                                 reversepaths(g);
800                         }
801                 }
802         }
803 }
804
805 static double
806 f2dot14(
807         short x
808 )
809 {
810         short           y = ntohs(x);
811         return (y >> 14) + ((y & 0x3fff) / 16384.0);
812 }
813
814
815 /* check that the pointer points within the file */
816 /* returns 0 if pointer is good, 1 if bad */
817 static int
818 badpointer(
819         void *ptr
820 )
821 {
822         return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
823 }
824
825 /*
826  * Externally accessible methods
827  */
828
829 /*
830  * Open font and prepare to return information to the main driver.
831  * May print error and warning messages.
832  * Exit on error.
833  */
834
835 static void
836 openfont(
837         char *fname,
838         char *arg /* unused now */
839 )
840 {
841         int             i, j;
842         struct stat     statbuf;
843         static struct {
844                 void **tbpp; /* pointer to pointer to the table */
845                 char name[5]; /* table name */
846                 char optional; /* flag: table may be missing */
847         } tables[] = {
848                 { (void **)&name_table, "name", 0 },
849                 { (void **)&head_table, "head", 0 },
850                 { (void **)&hhea_table, "hhea", 0 },
851                 { (void **)&post_table, "post", 0 },
852                 { (void **)&glyf_start, "glyf", 0 },
853                 { (void **)&cmap_table, "cmap", 0 },
854                 { (void **)&kern_table, "kern", 1 },
855                 { (void **)&maxp_table, "maxp", 0 },
856                 { (void **)&hmtx_table, "hmtx", 0 },
857                 { (void **)&long_loca_table, "loca", 0 },
858                 { NULL, "", 0 } /* end of table */
859         };
860
861         if (stat(fname, &statbuf) == -1) {
862                 fprintf(stderr, "**** Cannot access %s ****\n", fname);
863                 exit(1);
864         }
865         if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
866                 fprintf(stderr, "**** Cannot malloc space for file ****\n");
867                 exit(1);
868         }
869
870         filebuffer_end = filebuffer + statbuf.st_size;
871
872         if ((ttf_file = fopen(fname, "rb")) == NULL) {
873                 fprintf(stderr, "**** Cannot open file '%s'\n", fname);
874                 exit(1);
875         } else {
876                 WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
877         }
878
879         if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
880                 fprintf(stderr, "**** Could not read whole file \n");
881                 exit(1);
882         }
883         fclose(ttf_file);
884
885         directory = (TTF_DIRECTORY *) filebuffer;
886
887         if (ntohl(directory->sfntVersion) != 0x00010000) {
888                 fprintf(stderr,
889                         "**** Unknown File Version number [%x], or not a TrueType file\n",
890                         directory->sfntVersion);
891                 exit(1);
892         }
893
894         /* clear the tables */
895         for(j=0; tables[j].tbpp != NULL; j++)
896                 *(tables[j].tbpp) = NULL;
897
898         dir_entry = &(directory->list);
899
900         for (i = 0; i < ntohs(directory->numTables); i++) {
901
902                 for(j=0; tables[j].tbpp != NULL; j++)
903                         if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) {
904                                 *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset));
905                                 break;
906                         }
907
908                 if (memcmp(dir_entry->tag, "EBDT", 4) == 0 ||
909                            memcmp(dir_entry->tag, "EBLC", 4) == 0 ||
910                            memcmp(dir_entry->tag, "EBSC", 4) == 0) {
911                         WARNING_1 fprintf(stderr, "Font contains bitmaps\n");
912                 }
913                 dir_entry++;
914         }
915
916         for(j=0; tables[j].tbpp != NULL; j++)
917                 if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) {
918                         fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name);
919                         exit(1);
920                 }
921
922         handle_name();
923
924         handle_head();
925
926         ttf_nglyphs = ntohs(maxp_table->numGlyphs);
927
928         enc_found_ms = enc_found_mac = 0;
929 }
930
931 /*
932  * Close font.
933  * Exit on error.
934  */
935
936 static void
937 closefont(
938         void
939 )
940 {
941         return; /* empty operation */
942 }
943
944 /*
945  * Get the number of glyphs in font.
946  */
947
948 static int
949 getnglyphs (
950         void
951 )
952 {
953         return ttf_nglyphs;
954 }
955
956 /*
957  * Get the names of the glyphs.
958  * Returns 0 if the names were assigned, non-zero if the font
959  * provides no glyph names.
960  */
961
962 static int
963 glnames(
964         GLYPH *glyph_list
965 )
966 {
967         int             i, len, n, npost;
968         unsigned int    format;
969         USHORT         *name_index;
970         char           *ptr, *p;
971         char          **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
972         int             n_ps_names;
973         int             ps_fmt_3 = 0;
974
975         format = ntohl(post_table->formatType);
976
977         if (format == 0x00010000) {
978                 for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
979                         glyph_list[i].name = mac_glyph_names[i];
980                 }
981         } else if (format == 0x00020000) {
982                 npost = ntohs(post_table->numGlyphs);
983                 if (ttf_nglyphs != npost) {
984                         /* This is an error in the font, but we can now cope */
985                         WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n",
986                                 npost, ttf_nglyphs);
987                 }
988                 n_ps_names = 0;
989                 name_index = &(post_table->glyphNameIndex);
990
991                 /* This checks the integrity of the post table */       
992                 for (i=0; i<npost; i++) {
993                     n = ntohs(name_index[i]);
994                     if (n > n_ps_names + 257) {
995                         n_ps_names = n - 257;
996                     }
997                 }
998
999                 ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
1000                 i = 0;
1001                 while (*ptr > 0 && i < n_ps_names) {
1002                         len = *ptr;
1003                         /* previously the program wrote nulls into the table. If the table
1004                            was corrupt, this could put zeroes anywhere, leading to obscure bugs,
1005                            so now I malloc space for the names. Yes it is much less efficient */
1006                            
1007                         if ((p = malloc(len+1)) == NULL) {
1008                             fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1009                             exit(255);
1010                         }
1011                         
1012                         ps_name_ptr[i] = p;
1013                         strncpy(p, ptr+1, len);
1014                         p[len] = '\0';
1015                         i ++;
1016                         ptr += len + 1;
1017                 }
1018         
1019                 if (i != n_ps_names)
1020                 {
1021                     WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
1022                              i, n_ps_names);
1023                     n_ps_names = i;
1024                 }
1025
1026                 /*
1027                  * for (i=0; i<n_ps_names; i++) { fprintf(stderr, "i=%d,
1028                  * len=%d, name=%s\n", i, ps_name_len[i], ps_name_ptr[i]); }
1029                  */
1030
1031                 for (i = 0; i < npost; i++) {
1032                         n = ntohs(name_index[i]);
1033                         if (n < 258) {
1034                                 glyph_list[i].name = mac_glyph_names[n];
1035                         } else if (n < 258 + n_ps_names) {
1036                                 glyph_list[i].name = ps_name_ptr[n - 258];
1037                         } else {
1038                                 glyph_list[i].name = malloc(16);
1039                                 sprintf(glyph_list[i].name, "_g_%d", i);
1040                                 WARNING_2 fprintf(stderr,
1041                                         "Glyph No. %d has no postscript name, becomes %s\n",
1042                                         i, glyph_list[i].name);
1043                         }
1044                 }
1045                 /* Now fake postscript names for all those beyond the end of the table */
1046                 if (npost < ttf_nglyphs) {
1047                     for (i=npost; i<ttf_nglyphs; i++) {
1048                         if ((glyph_list[i].name = malloc(16)) == NULL)
1049                         {
1050                             fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1051                             exit(255);
1052                         }
1053                         sprintf(glyph_list[i].name, "_g_%d", i);
1054                         WARNING_2 fprintf(stderr,
1055                                 "Glyph No. %d has no postscript name, becomes %s\n",
1056                                 i, glyph_list[i].name);
1057                     }
1058                 }
1059         } else if (format == 0x00030000) {
1060                 WARNING_3 fputs("No postscript table, using default\n", stderr);
1061                 ps_fmt_3 = 1;
1062         } else if (format == 0x00028000) {
1063                 ptr = (char *) &(post_table->numGlyphs);
1064                 for (i = 0; i < ttf_nglyphs; i++) {
1065                         glyph_list[i].name = mac_glyph_names[i + ptr[i]];
1066                 }
1067         } else {
1068                 fprintf(stderr,
1069                         "**** Postscript table in wrong format %x ****\n",
1070                         format);
1071                 exit(1);
1072         }
1073
1074         return ps_fmt_3;
1075 }
1076
1077 /*
1078  * Get the metrics of the glyphs.
1079  */
1080
1081 static void
1082 glmetrics(
1083         GLYPH *glyph_list
1084 )
1085 {
1086         int             i;
1087         int             n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
1088         GLYPH          *g;
1089         LONGHORMETRIC  *hmtx_entry = hmtx_table;
1090         FWORD          *lsblist;
1091
1092         for (i = 0; i < n_hmetrics; i++) {
1093                 g = &(glyph_list[i]);
1094                 g->width = ntohs(hmtx_entry->advanceWidth);
1095                 g->lsb = ntohs(hmtx_entry->lsb);
1096                 hmtx_entry++;
1097         }
1098
1099         lsblist = (FWORD *) hmtx_entry;
1100         hmtx_entry--;
1101
1102         for (i = n_hmetrics; i < ttf_nglyphs; i++) {
1103                 g = &(glyph_list[i]);
1104                 g->width = ntohs(hmtx_entry->advanceWidth);
1105                 g->lsb = ntohs(lsblist[i - n_hmetrics]);
1106         }
1107
1108         for (i = 0; i < ttf_nglyphs; i++) {
1109                 g = &(glyph_list[i]);
1110                 get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
1111
1112                 g->xMin = (short)ntohs(glyf_table->xMin);
1113                 g->xMax = (short)ntohs(glyf_table->xMax);
1114                 g->yMin = (short)ntohs(glyf_table->yMin);
1115                 g->yMax = (short)ntohs(glyf_table->yMax);
1116         }
1117
1118 }
1119
1120
1121 static void
1122 handle_ms_encoding(
1123         GLYPH *glyph_list,
1124         int *encoding,
1125         int *unimap
1126 )
1127 {
1128         int             j, k, kk, set_ok;
1129         USHORT          start, end, ro;
1130         short           delta, n;
1131
1132         for (j = 0; j < cmap_n_segs - 1; j++) {
1133                 start = ntohs(cmap_seg_start[j]);
1134                 end = ntohs(cmap_seg_end[j]);
1135                 delta = ntohs(cmap_idDelta[j]);
1136                 ro = ntohs(cmap_idRangeOffset[j]);
1137
1138                 for (k = start; k <= end; k++) {
1139                         if (ro == 0) {
1140                                 n = k + delta;
1141                         } else {
1142                                 n = ntohs(*((ro >> 1) + (k - start) +
1143                                  &(cmap_idRangeOffset[j])));
1144                                 if (delta != 0)
1145                                 {
1146                                         /*  Not exactly sure how to deal with this circumstance,
1147                                                 I suspect it never occurs */
1148                                         n += delta;
1149                                         fprintf (stderr,
1150                                                  "rangeoffset and delta both non-zero - %d/%d",
1151                                                  ro, delta);
1152                                 }
1153                         }
1154                         if(n<0 || n>=ttf_nglyphs) {
1155                                 WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
1156                                 continue;
1157                         }
1158                         if (glyph_list[n].orig_code != -1) {
1159 #if 0
1160                                 if (strcmp(glyph_list[n].name, ".notdef") != 0) {
1161                                         WARNING_2 fprintf(stderr,
1162                                                 "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n",
1163                                          glyph_list[n].name,
1164                                                 glyph_list[n].orig_code,
1165                                                 k);
1166                                 }
1167 #endif
1168                                 set_ok = 0;
1169                         } else {
1170                                 set_ok = 1;
1171                         }
1172                         if (enc_type==1 || forcemap) {
1173                                 kk = unicode_rev_lookup(k);
1174                                 if(ISDBG(UNICODE))
1175                                         fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
1176                                 if (set_ok) {
1177                                         glyph_list[n].orig_code = k;
1178                                         /* glyph_list[n].char_no = kk; */
1179                                 }
1180                                 if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
1181                                         encoding[kk] = n;
1182                         } else {
1183                                 if ((k & 0xff00) == 0xf000) {
1184                                         if( encoding[k & 0x00ff] == -1 ) {
1185                                                 encoding[k & 0x00ff] = n;
1186                                                 if (set_ok) {
1187                                                         /* glyph_list[n].char_no = k & 0x00ff; */
1188                                                         glyph_list[n].orig_code = k;
1189                                                 }
1190                                         }
1191                                 } else {
1192                                         if (set_ok) {
1193                                                 /* glyph_list[n].char_no = k; */
1194                                                 glyph_list[n].orig_code = k;
1195                                         }
1196                                         WARNING_2 fprintf(stderr,
1197                                                 "Glyph %s has non-symbol encoding %4.4x\n",
1198                                          glyph_list[n].name,
1199                                                 k & 0xffff);
1200                                         /*
1201                                          * just use the code
1202                                          * as it is
1203                                          */
1204                                         if ((k & ~0xff) == 0 && encoding[k] == -1 )
1205                                                 encoding[k] = n;
1206                                 }
1207                         }
1208                 }
1209         }
1210 }
1211
1212 static void
1213 handle_mac_encoding(
1214         GLYPH *glyph_list,
1215         int *encoding,
1216         int *unimap
1217 )
1218 {
1219         short           n;
1220         int             j, size;
1221
1222         size = ntohs(encoding0->length) - 6;
1223         for (j = 0; j < size; j++) {
1224                 n = encoding0->glyphIdArray[j];
1225                 if (glyph_list[n].char_no != -1) {
1226                         WARNING_2 fprintf(stderr,
1227                                 "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n",
1228                                 glyph_list[n].name,
1229                                   glyph_list[n].char_no,
1230                                 j);
1231                 } else {
1232                         if (j < ENCTABSZ) {
1233                                 if(encoding[j] == -1) {
1234                                         glyph_list[n].char_no = j;
1235                                         encoding[j] = n;
1236                                 }
1237                         }
1238                 }
1239         }
1240 }
1241
1242 /*
1243  * Get the original encoding of the font. 
1244  * Returns 1 for if the original encoding is Unicode, 2 if the
1245  * original encoding is other 16-bit, 0 if 8-bit.
1246  */
1247
1248 static int
1249 glenc(
1250         GLYPH *glyph_list,
1251         int *encoding,
1252         int *unimap
1253 )
1254 {
1255         int             num_tables = ntohs(cmap_table->numberOfEncodingTables);
1256         BYTE           *ptr;
1257         int             i, format, offset, seg_c2, found;
1258         int             platform, encoding_id;
1259         TTF_CMAP_ENTRY *table_entry;
1260         TTF_CMAP_FMT4  *encoding4;
1261
1262         if(enc_found_ms) {
1263                 handle_ms_encoding(glyph_list, encoding, unimap);
1264                 return enc_type;
1265         } else if(enc_found_mac) {
1266                 handle_mac_encoding(glyph_list, encoding, unimap);
1267                 return 0;
1268         }
1269
1270         if(force_pid != -1 && force_pid != 3) {
1271                 fputs("*** Only platform ID == 3 is supported\n", stderr);
1272                 exit(1);
1273         }
1274
1275         enc_type = 0;
1276         found = 0;
1277
1278         for (i = 0; i < num_tables && !found; i++) {
1279                 table_entry = &(cmap_table->encodingTable[i]);
1280                 offset = ntohl(table_entry->offset);
1281                 encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset);
1282                 format = ntohs(encoding4->format);
1283                 platform = ntohs(table_entry->platformID);
1284                 encoding_id = ntohs(table_entry->encodingID);
1285
1286                 if (platform == 3 && format == 4) {
1287                         if(force_pid == 3) {
1288                                 if(encoding_id != force_eid)
1289                                         continue;
1290                                 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", 
1291                                         force_pid, force_eid);
1292                                 enc_type = 1;
1293                         } else {
1294                                 switch (encoding_id) {
1295                                 case 0:
1296                                         WARNING_1 fputs("Found Symbol Encoding\n", stderr);
1297                                         break;
1298                                 case 1:
1299                                         WARNING_1 fputs("Found Unicode Encoding\n", stderr);
1300                                         enc_type = 1;
1301                                         break;
1302                                 default:
1303                                         WARNING_1 {
1304                                                 fprintf(stderr,
1305                                                 "****MS Encoding ID %d not supported****\n",
1306                                                         encoding_id);
1307                                                 fputs("Treating it like Symbol encoding\n", stderr);
1308                                         }
1309                                         break;
1310                                 }
1311                         }
1312
1313                         found = 1;
1314                         seg_c2 = ntohs(encoding4->segCountX2);
1315                         cmap_n_segs = seg_c2 >> 1;
1316                         ptr = (BYTE *) encoding4 + 14;
1317                         cmap_seg_end = (USHORT *) ptr;
1318                         cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2);
1319                         cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2);
1320                         cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2);
1321                         enc_found_ms = 1;
1322
1323                         handle_ms_encoding(glyph_list, encoding, unimap);
1324                 }
1325         }
1326
1327         if (!found) {
1328                 if(force_pid != -1) {
1329                         fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", 
1330                                 force_pid, force_eid);
1331                         exit(1);
1332                 }
1333
1334                 WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr);
1335                 for (i = 0; i < num_tables && !found; i++) {
1336                         table_entry = &(cmap_table->encodingTable[i]);
1337                         offset = ntohl(table_entry->offset);
1338                         encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset);
1339                         format = ntohs(encoding0->format);
1340                         platform = ntohs(table_entry->platformID);
1341                         encoding_id = ntohs(table_entry->encodingID);
1342
1343                         if (format == 0) {
1344                                 found = 1;
1345                                 enc_found_mac = 1;
1346
1347                                 handle_mac_encoding(glyph_list, encoding, unimap);
1348                         }
1349                 }
1350         }
1351         if (!found) {
1352                 fprintf(stderr, "**** No Recognised Encoding Table ****\n");
1353                 exit(1);
1354         }
1355
1356         return enc_type;
1357 }
1358
1359 /*
1360  * Get the font metrics
1361  */
1362 static void 
1363 fnmetrics(
1364         struct font_metrics *fm
1365 )
1366 {
1367         char *str;
1368         static int fieldstocheck[]= {2,4,6};
1369         int i, j, len;
1370
1371         fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) +
1372                 ((short) ntohs(post_table->italicAngle.lower) / 65536.0);
1373         fm->underline_position = (short) ntohs(post_table->underlinePosition);
1374         fm->underline_thickness = (short) ntohs(post_table->underlineThickness);
1375         fm->is_fixed_pitch = ntohl(post_table->isFixedPitch);
1376
1377         fm->ascender = (short)ntohs(hhea_table->ascender);
1378         fm->descender = (short)ntohs(hhea_table->descender);
1379
1380         fm->units_per_em =  ntohs(head_table->unitsPerEm);
1381
1382         fm->bbox[0] = (short) ntohs(head_table->xMin);
1383         fm->bbox[1] = (short) ntohs(head_table->yMin);
1384         fm->bbox[2] = (short) ntohs(head_table->xMax);
1385         fm->bbox[3] = (short) ntohs(head_table->yMax);
1386
1387         fm->name_copyright = name_fields[0];
1388         fm->name_family = name_fields[1];
1389         fm->name_style = name_fields[2];
1390         fm->name_full = name_fields[4];
1391         fm->name_version = name_fields[5];
1392         fm->name_ps = name_fields[6];
1393
1394         /* guess the boldness from the font names */
1395         fm->force_bold=0;
1396
1397         for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
1398                 str = name_fields[fieldstocheck[i]];
1399                 len = strlen(str);
1400                 for(j=0; j<len; j++) {
1401                         if( (str[j]=='B'
1402                                 || str[j]=='b' 
1403                                         && ( j==0 || !isalpha(str[j-1]) )
1404                                 )
1405                         && !strncmp("old",&str[j+1],3)
1406                         && (j+4 >= len || !islower(str[j+4]))
1407                         ) {
1408                                 fm->force_bold=1;
1409                                 break;
1410                         }
1411                 }
1412         }
1413 }
1414
1415 /*
1416  * Get the path of contrours for a glyph.
1417  */
1418
1419 static void
1420 glpath(
1421         int glyphno,
1422         GLYPH *glyf_list
1423 )
1424 {
1425         double          matrix[6];
1426         GLYPH          *g;
1427
1428         g = &glyph_list[glyphno];
1429
1430         matrix[0] = matrix[3] = 1.0;
1431         matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
1432         draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
1433 }
1434
1435 /*
1436  * Get the kerning data.
1437  */
1438
1439 static void
1440 kerning(
1441         GLYPH *glyph_list
1442 )
1443 {
1444         TTF_KERN_SUB   *subtable;
1445         TTF_KERN_ENTRY *kern_entry;
1446         int             i, j;
1447         int             ntables;
1448         int             npairs;
1449         char           *ptr;
1450
1451         if(kern_table == NULL) {
1452         WARNING_1 fputs("No Kerning data\n", stderr);
1453                 return;
1454         }
1455         if(badpointer(kern_table)) {
1456         fputs("**** Defective Kerning table, ignored\n", stderr);
1457                 return;
1458         }
1459
1460         ntables = ntohs(kern_table->nTables);
1461         ptr = (char *) kern_table + 4;
1462
1463         for (i = 0; i < ntables; i++) {
1464                 subtable = (TTF_KERN_SUB *) ptr;
1465                 if ((ntohs(subtable->coverage) & 0xff00) == 0) {
1466                         npairs = (short) ntohs(subtable->nPairs);
1467                         kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
1468
1469                         kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
1470                         for (j = 0; j < npairs; j++) {
1471                                 if( kern_entry->value != 0)
1472                                         addkernpair(ntohs(kern_entry->left), 
1473                                                 ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
1474                                 kern_entry++;
1475                         }
1476                 }
1477                 ptr += subtable->length;
1478         }
1479 }
1480