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>
13 #include <sys/types.h>
22 # include <netinet/in.h>
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);
44 /* front-end descriptor */
45 struct frontsw ttf_sw = {
47 /*descr*/ "built-in TTF support",
51 /*nglyphs*/ getnglyphs,
53 /*glmetrics*/ glmetrics,
55 /*fnmetrics*/ fnmetrics,
62 static FILE *ttf_file;
63 static int ttf_nglyphs, long_offsets;
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;
84 #define short_loca_table loca_table.sp
85 #define long_loca_table loca_table.lp
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;
93 static char name_buffer[2000];
94 static char *name_fields[8];
96 static int enc_found_ms, enc_found_mac;
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",
114 "X", "Y", "Z", "bracketleft",
115 "backslash", "bracketright", "asciicircum", "underscore",
116 "grave", "a", "b", "c",
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"
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,
171 static double f2dot14( short x);
173 /* get the TTF description table address and length for this index */
184 *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno]));
186 *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1));
191 *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]);
193 *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1;
201 int j, k, lang, len, platform;
202 char *p, *string_area;
203 char *nbp = name_buffer;
206 string_area = (char *) name_table + ntohs(name_table->offset);
207 name_record = &(name_table->nameRecords);
209 for (j = 0; j < 8; j++) {
213 for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
215 platform = ntohs(name_record->platformID);
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);
225 name_fields[k] = nbp;
227 p = string_area + ntohs(name_record->stringOffset);
228 for (k = 0; k < len; k++) {
232 } else if (p[k] == ')') {
248 string_area = (char *) name_table + ntohs(name_table->offset);
249 name_record = &(name_table->nameRecords);
252 for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) {
254 platform = ntohs(name_record->platformID);
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);
264 name_fields[k] = nbp;
266 p = string_area + ntohs(name_record->stringOffset);
267 for (k = 0; k < len; k++) {
271 } else if (p[k] == ')') {
288 fprintf(stderr, "**** Cannot decode font name fields ****\n");
291 if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */
292 name_fields[4] = name_fields[1];
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";
302 /* must not start with a digit */
304 *p+= 'A'-'0'; /* change to a letter */
306 if (!isalnum(*p) || *p=='_') {
316 long_offsets = ntohs(head_table->indexToLocFormat);
317 if (long_offsets != 0 && long_offsets != 1) {
318 fprintf(stderr, "**** indexToLocFormat wrong ****\n");
323 /* limit the recursion level to avoid cycles */
324 #define MAX_COMPOSITE_LEVEL 20
337 USHORT flagbyte, glyphindex;
342 double matrix[6], newmatrix[6];
344 get_glyf_table(glyphno, &glyf_table, &len);
346 if(len<=0) /* nothing to do */
349 ncontours = ntohs(glyf_table->numberOfContours);
350 if (ncontours >= 0) { /* simple case */
351 draw_simple_glyf(g, glyph_list, glyphno, orgmatrix);
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]);
361 if(level >= MAX_COMPOSITE_LEVEL) {
362 WARNING_1 fprintf(stderr,
363 "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n",
368 ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF));
369 sptr = (SHORT *) ptr;
371 flagbyte = ntohs(*sptr);
373 glyphindex = ntohs(*sptr);
376 if (flagbyte & ARG_1_AND_2_ARE_WORDS) {
377 arg1 = (short)ntohs(*sptr);
379 arg2 = (short)ntohs(*sptr);
382 bptr = (char *) sptr;
383 arg1 = (signed char) bptr[0];
384 arg2 = (signed char) bptr[1];
387 matrix[1] = matrix[2] = 0.0;
389 if (flagbyte & WE_HAVE_A_SCALE) {
390 matrix[0] = matrix[3] = f2dot14(*sptr);
392 } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) {
393 matrix[0] = f2dot14(*sptr);
395 matrix[3] = f2dot14(*sptr);
397 } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) {
398 matrix[0] = f2dot14(*sptr);
400 matrix[1] = f2dot14(*sptr);
402 matrix[2] = f2dot14(*sptr);
404 matrix[3] = f2dot14(*sptr);
407 matrix[0] = matrix[3] = 1.0;
412 * http://fonts.apple.com/TTRefMan/RM06/Chap6g
413 * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n
416 if (fabs(matrix[0]) > fabs(matrix[1]))
417 matrix[4] = fabs(matrix[0]);
419 matrix[4] = fabs(matrix[1]);
420 if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.)
423 if (fabs(matrix[2]) > fabs(matrix[3]))
424 matrix[5] = fabs(matrix[2]);
426 matrix[5] = fabs(matrix[3]);
427 if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.)
431 * fprintf (stderr,"Matrix Opp %hd
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",
440 ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index"));
443 if (flagbyte & ARGS_ARE_XY_VALUES) {
447 WARNING_1 fprintf(stderr,
448 "*** Glyph %s: reusing scale from another glyph is unsupported\n",
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
459 /* at this point arg1,arg2 contain what logically should be matrix[4,5] */
461 /* combine matrices */
463 newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1];
464 newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3];
466 newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1];
467 newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3];
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];
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",
479 newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3],
480 newmatrix[4], newmatrix[5]);
482 draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1);
484 } while (flagbyte & MORE_COMPONENTS);
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;
503 short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ];
504 double xcoord[GLYFSZ], ycoord[GLYFSZ];
507 int needreverse = 0; /* transformation may require
513 get_glyf_table(glyphno, &glyf_table, &len);
516 WARNING_1 fprintf(stderr,
517 "**** Composite glyph %s refers to non-existent glyph %s, ignored\n",
519 glyph_list[glyphno].name);
522 ncontours = ntohs(glyf_table->numberOfContours);
524 WARNING_1 fprintf(stderr,
525 "**** Composite glyph %s refers to composite glyph %s, ignored\n",
527 glyph_list[glyphno].name);
530 contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF));
532 last_point = ntohs(contour_end_pt[ncontours - 1]);
533 n_inst = ntohs(contour_end_pt[ncontours]);
535 ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2;
537 while (k <= last_point) {
540 if (ptr[j] & REPEAT) {
541 for (k1 = 0; k1 < ptr[j + 1]; k1++) {
551 for (k = 0; k <= last_point; k++) {
552 if (flags[k] & XSHORT) {
553 if (flags[k] & XSAME) {
559 } else if (flags[k] & XSAME) {
562 xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] );
568 xabs[k] = xrel[k] + xabs[k - 1];
573 for (k = 0; k <= last_point; k++) {
574 if (flags[k] & YSHORT) {
575 if (flags[k] & YSAME) {
581 } else if (flags[k] & YSAME) {
584 yrel[k] = ptr[j] * 256 + ptr[j + 1];
590 yabs[k] = yrel[k] + yabs[k - 1];
595 for (i = 0; i <= last_point; 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]);
602 for (i = 0; i <= last_point; i++) {
603 xcoord[i] = fscale(xabs[i]);
604 ycoord[i] = fscale(yabs[i]);
611 while (i <= ntohs(contour_end_pt[ncontours - 1])) {
612 contour_end = ntohs(contour_end_pt[j]);
615 fg_rmoveto(g, xcoord[i], ycoord[i]);
620 } else if (flags[i] & ONOROFF) {
621 fg_rlineto(g, xcoord[i], ycoord[i]);
626 finished = nguide = 0;
628 if (i == contour_end + 1) {
631 } else if (flags[i] & ONOROFF) {
642 fg_rlineto(g, xcoord[ce], ycoord[ce]);
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,
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,
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
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
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,
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
717 for (k = cs + 2; k <= k1 - 1; k++) {
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
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,
743 if (i >= contour_end) {
754 /* guess whether do we need to reverse the results */
757 int max = 0, from, to;
759 /* transform a triangle going in proper direction */
761 * the origin of triangle is in (0,0) so we know it in
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;
771 /* then find the topmost point */
772 for (i = 0; i < 3; i++)
775 from = (max + 3 - 1) % 3;
780 /* special cases for horizontal lines */
781 if (y[max] == y[from]) {
782 if (x[max] < y[from])
784 } else if (y[to] == y[from]) {
787 } else { /* generic case */
788 if ((x[to] - x[max]) * (y[max] - y[from])
789 > (x[max] - x[from]) * (y[to] - y[max]))
795 assertpath(lge->next, __FILE__, __LINE__, g->name);
796 reversepathsfromto(lge->next, NULL);
798 assertpath(g->entries, __FILE__, __LINE__, g->name);
811 return (y >> 14) + ((y & 0x3fff) / 16384.0);
815 /* check that the pointer points within the file */
816 /* returns 0 if pointer is good, 1 if bad */
822 return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end);
826 * Externally accessible methods
830 * Open font and prepare to return information to the main driver.
831 * May print error and warning messages.
838 char *arg /* unused now */
844 void **tbpp; /* pointer to pointer to the table */
845 char name[5]; /* table name */
846 char optional; /* flag: table may be missing */
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 */
861 if (stat(fname, &statbuf) == -1) {
862 fprintf(stderr, "**** Cannot access %s ****\n", fname);
865 if ((filebuffer = malloc(statbuf.st_size)) == NULL) {
866 fprintf(stderr, "**** Cannot malloc space for file ****\n");
870 filebuffer_end = filebuffer + statbuf.st_size;
872 if ((ttf_file = fopen(fname, "rb")) == NULL) {
873 fprintf(stderr, "**** Cannot open file '%s'\n", fname);
876 WARNING_2 fprintf(stderr, "Processing file %s\n", fname);
879 if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) {
880 fprintf(stderr, "**** Could not read whole file \n");
885 directory = (TTF_DIRECTORY *) filebuffer;
887 if (ntohl(directory->sfntVersion) != 0x00010000) {
889 "**** Unknown File Version number [%x], or not a TrueType file\n",
890 directory->sfntVersion);
894 /* clear the tables */
895 for(j=0; tables[j].tbpp != NULL; j++)
896 *(tables[j].tbpp) = NULL;
898 dir_entry = &(directory->list);
900 for (i = 0; i < ntohs(directory->numTables); i++) {
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));
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");
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);
926 ttf_nglyphs = ntohs(maxp_table->numGlyphs);
928 enc_found_ms = enc_found_mac = 0;
941 return; /* empty operation */
945 * Get the number of glyphs in font.
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.
967 int i, len, n, npost;
971 char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *));
975 format = ntohl(post_table->formatType);
977 if (format == 0x00010000) {
978 for (i = 0; i < 258 && i < ttf_nglyphs; i++) {
979 glyph_list[i].name = mac_glyph_names[i];
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",
989 name_index = &(post_table->glyphNameIndex);
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;
999 ptr = (char *) post_table + 34 + (ttf_nglyphs << 1);
1001 while (*ptr > 0 && i < n_ps_names) {
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 */
1007 if ((p = malloc(len+1)) == NULL) {
1008 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1013 strncpy(p, ptr+1, len);
1019 if (i != n_ps_names)
1021 WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n",
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]); }
1031 for (i = 0; i < npost; i++) {
1032 n = ntohs(name_index[i]);
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];
1038 glyph_list[i].name = malloc(10);
1039 sprintf(glyph_list[i].name, "_%d", n);
1040 WARNING_2 fprintf(stderr,
1041 "**** Glyph No. %d has no postscript name, becomes %s ****\n",
1042 i, glyph_list[i].name);
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(10)) == NULL)
1050 fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__);
1053 sprintf(glyph_list[i].name, "_%d", i);
1054 WARNING_2 fprintf(stderr,
1055 "** Glyph No. %d has no postscript name, becomes %s **\n",
1056 i, glyph_list[i].name);
1059 } else if (format == 0x00030000) {
1060 WARNING_3 fputs("No postscript table, using default\n", stderr);
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]];
1069 "**** Postscript table in wrong format %x ****\n",
1078 * Get the metrics of the glyphs.
1087 int n_hmetrics = ntohs(hhea_table->numberOfHMetrics);
1089 LONGHORMETRIC *hmtx_entry = hmtx_table;
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);
1099 lsblist = (FWORD *) hmtx_entry;
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]);
1108 for (i = 0; i < ttf_nglyphs; i++) {
1109 g = &(glyph_list[i]);
1110 get_glyf_table(i, &glyf_table, &g->ttf_pathlen);
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);
1128 int j, k, kk, set_ok;
1129 USHORT start, end, ro;
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]);
1138 for (k = start; k <= end; k++) {
1142 n = ntohs(*((ro >> 1) + (k - start) +
1143 &(cmap_idRangeOffset[j])));
1146 /* Not exactly sure how to deal with this circumstance,
1147 I suspect it never occurs */
1150 "rangeoffset and delta both non-zero - %d/%d",
1154 if(n<0 || n>=ttf_nglyphs) {
1155 WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n");
1158 if (glyph_list[n].orig_code != -1) {
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",
1164 glyph_list[n].orig_code,
1172 if (enc_type==1 || forcemap) {
1173 kk = unicode_rev_lookup(k);
1175 fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k);
1177 glyph_list[n].orig_code = k;
1178 /* glyph_list[n].char_no = kk; */
1180 if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1)
1183 if ((k & 0xff00) == 0xf000) {
1184 if( encoding[k & 0x00ff] == -1 ) {
1185 encoding[k & 0x00ff] = n;
1187 /* glyph_list[n].char_no = k & 0x00ff; */
1188 glyph_list[n].orig_code = k;
1193 /* glyph_list[n].char_no = k; */
1194 glyph_list[n].orig_code = k;
1196 WARNING_2 fprintf(stderr,
1197 "Glyph %s has non-symbol encoding %4.4x\n",
1204 if ((k & ~0xff) == 0 && encoding[k] == -1 )
1213 handle_mac_encoding(
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",
1229 glyph_list[n].char_no,
1233 if(encoding[j] == -1) {
1234 glyph_list[n].char_no = j;
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.
1255 int num_tables = ntohs(cmap_table->numberOfEncodingTables);
1257 int i, format, offset, seg_c2, found;
1258 int platform, encoding_id;
1259 TTF_CMAP_ENTRY *table_entry;
1260 TTF_CMAP_FMT4 *encoding4;
1263 handle_ms_encoding(glyph_list, encoding, unimap);
1265 } else if(enc_found_mac) {
1266 handle_mac_encoding(glyph_list, encoding, unimap);
1270 if(force_pid != -1 && force_pid != 3) {
1271 fputs("*** Only platform ID == 3 is supported\n", stderr);
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);
1286 if (platform == 3 && format == 4) {
1287 if(force_pid == 3) {
1288 if(encoding_id != force_eid)
1290 WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n",
1291 force_pid, force_eid);
1294 switch (encoding_id) {
1296 WARNING_1 fputs("Found Symbol Encoding\n", stderr);
1299 WARNING_1 fputs("Found Unicode Encoding\n", stderr);
1305 "****MS Encoding ID %d not supported****\n",
1307 fputs("Treating it like Symbol encoding\n", stderr);
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);
1323 handle_ms_encoding(glyph_list, encoding, unimap);
1328 if(force_pid != -1) {
1329 fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n",
1330 force_pid, force_eid);
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);
1347 handle_mac_encoding(glyph_list, encoding, unimap);
1352 fprintf(stderr, "**** No Recognised Encoding Table ****\n");
1360 * Get the font metrics
1364 struct font_metrics *fm
1368 static int fieldstocheck[]= {2,4,6};
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);
1377 fm->ascender = (short)ntohs(hhea_table->ascender);
1378 fm->descender = (short)ntohs(hhea_table->descender);
1380 fm->units_per_em = ntohs(head_table->unitsPerEm);
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);
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];
1394 /* guess the boldness from the font names */
1397 for(i=0; !fm->force_bold && i<sizeof fieldstocheck /sizeof(int); i++) {
1398 str=name_fields[fieldstocheck[i]];
1399 for(i=0; str[i]!=0; i++) {
1402 && ( i==0 || !isalpha(str[i-1]) )
1404 && !strncmp("old",&str[i+1],3)
1405 && !islower(str[i+4])
1415 * Get the path of contrours for a glyph.
1427 g = &glyph_list[glyphno];
1429 matrix[0] = matrix[3] = 1.0;
1430 matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0;
1431 draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/);
1435 * Get the kerning data.
1443 TTF_KERN_SUB *subtable;
1444 TTF_KERN_ENTRY *kern_entry;
1450 if(kern_table == NULL) {
1451 WARNING_1 fputs("No Kerning data\n", stderr);
1454 if(badpointer(kern_table)) {
1455 fputs("**** Defective Kerning table, ignored\n", stderr);
1459 ntables = ntohs(kern_table->nTables);
1460 ptr = (char *) kern_table + 4;
1462 for (i = 0; i < ntables; i++) {
1463 subtable = (TTF_KERN_SUB *) ptr;
1464 if ((ntohs(subtable->coverage) & 0xff00) == 0) {
1465 npairs = (short) ntohs(subtable->nPairs);
1466 kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
1468 kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB));
1469 for (j = 0; j < npairs; j++) {
1470 if( kern_entry->value != 0)
1471 addkernpair(ntohs(kern_entry->left),
1472 ntohs(kern_entry->right), (short)ntohs(kern_entry->value));
1476 ptr += subtable->length;