source: branches/2.2/filemanager/tp/dompdf/lib/ttf2ufm/ttf2ufm-src/ttf.c @ 3019

Revision 3019, 38.6 KB checked in by amuller, 14 years ago (diff)

Ticket #1135 - Corrigindo CSS e adicionando filemanager

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