1 /* OpenType and TrueType fonts */
10 #define MAX(a, b) ((a) < (b) ? (b) : (a))
11 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
13 #define NGLYPHS (1 << 16)
14 #define NLOOKUPS (1 << 12)
18 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
19 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
20 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
21 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
22 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
24 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
26 typedef unsigned int u32
;
27 typedef unsigned short u16
;
28 typedef unsigned char u8
;
32 static char glyph_name
[NGLYPHS
][GNLEN
];
33 static int glyph_code
[NGLYPHS
];
34 static int glyph_bbox
[NGLYPHS
][4];
35 static int glyph_wid
[NGLYPHS
];
37 static int upm
; /* units per em */
38 static int sec
; /* current font section (lookup index * 10) */
41 void *otf
; /* TTC header or offset table */
42 void *off
; /* offset table */
43 char name
[128]; /* font name */
46 static char *macset
[];
47 static char *stdset
[];
49 static int owid(int w
)
51 return (w
< 0 ? w
* 1000 - upm
/ 2 : w
* 1000 + upm
/ 2) / upm
;
54 static int uwid(int w
)
56 int d
= 72000 / mkfn_res
;
57 return (w
< 0 ? owid(w
) - d
/ 20 : owid(w
) + d
/ 20) * 10 / d
;
60 /* whether the script is right-to-left */
61 static int otf_r2l(char *feat
)
63 char *scrp
= strchr(feat
, ':') + 1;
64 return !strcmp("arab", scrp
) || !strcmp("hebr", scrp
);
67 /* report unsupported otf tables */
68 static void otf_unsupported(char *sub
, int type
, int fmt
)
71 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
73 fprintf(stderr
, " format %d", fmt
);
74 fprintf(stderr
, "\n");
78 /* find the otf table with the given name */
79 static void *otf_table(struct otf
*otf
, char *name
)
81 int nrecs
= U16(otf
->off
, 4);
83 for (i
= 0; i
< nrecs
; i
++) {
84 void *rec
= otf
->off
+ 12 + i
* 16; /* an otf table record */
85 if (!strncmp(rec
, name
, 4))
86 return otf
->otf
+ U32(rec
, 8);
91 /* obtain postscript font name from name table */
92 static void otf_name(struct otf
*otf
, void *tab
)
95 void *str
= tab
+ U16(tab
, 4); /* storage area */
96 int n
= U16(tab
, 2); /* number of name records */
98 for (i
= 0; i
< n
; i
++) {
99 void *rec
= tab
+ 6 + 12 * i
;
100 int pid
= U16(rec
, 0); /* platform id */
101 int eid
= U16(rec
, 2); /* encoding id */
102 int lid
= U16(rec
, 4); /* language id */
103 int nid
= U16(rec
, 6); /* name id */
104 int len
= U16(rec
, 8); /* string length */
105 int off
= U16(rec
, 10); /* string offset */
106 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
107 memcpy(name
, str
+ off
, len
);
109 snprintf(otf
->name
, sizeof(otf
->name
), "%s", name
);
114 /* parse otf cmap format 4 subtable */
115 static void otf_cmap4(struct otf
*otf
, void *cmap4
)
118 void *ends
, *begs
, *deltas
, *offsets
;
119 int beg
, end
, delta
, offset
;
121 nsegs
= U16(cmap4
, 6) / 2;
123 begs
= ends
+ 2 * nsegs
+ 2;
124 deltas
= begs
+ 2 * nsegs
;
125 offsets
= deltas
+ 2 * nsegs
;
126 for (i
= 0; i
< nsegs
; i
++) {
127 beg
= U16(begs
, 2 * i
);
128 end
= U16(ends
, 2 * i
);
129 delta
= U16(deltas
, 2 * i
);
130 offset
= U16(offsets
, 2 * i
);
132 for (j
= beg
; j
<= end
; j
++)
133 glyph_code
[(U16(offsets
+ 2 * i
,
134 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
136 for (j
= beg
; j
<= end
; j
++)
137 glyph_code
[(j
+ delta
) & 0xffff] = j
;
142 /* parse otf cmap header */
143 static void otf_cmap(struct otf
*otf
, void *cmap
)
145 int nrecs
= U16(cmap
, 2);
147 for (i
= 0; i
< nrecs
; i
++) {
148 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
149 int plat
= U16(rec
, 0);
150 int enc
= U16(rec
, 2);
151 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
152 int fmt
= U16(tab
, 0);
153 if (plat
== 3 && enc
== 1 && fmt
== 4)
158 static void otf_post(struct otf
*otf
, void *post
)
160 void *post2
; /* version 2.0 header */
161 void *index
; /* glyph name indices */
162 void *names
; /* glyph names */
165 if (U32(post
, 0) != 0x20000)
168 glyph_n
= U16(post2
, 0);
170 names
= index
+ 2 * glyph_n
;
171 for (i
= 0; i
< glyph_n
; i
++) {
172 int idx
= U16(index
, 2 * i
);
174 strcpy(glyph_name
[i
], macset
[idx
]);
176 memcpy(glyph_name
[i
], names
+ cname
+ 1,
178 glyph_name
[i
][U8(names
, cname
)] = '\0';
179 cname
+= U8(names
, cname
) + 1;
184 static void otf_glyf(struct otf
*otf
, void *glyf
)
186 void *maxp
= otf_table(otf
, "maxp");
187 void *head
= otf_table(otf
, "head");
188 void *loca
= otf_table(otf
, "loca");
191 int n
= U16(maxp
, 4);
192 int fmt
= U16(head
, 50);
196 for (i
= 0; i
< n
; i
++) {
198 gdat
= glyf
+ U32(loca
, 4 * i
);
199 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
201 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
202 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
204 if (gdat
< gdat_next
)
205 for (j
= 0; j
< 4; j
++)
206 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
210 static void otf_hmtx(struct otf
*otf
, void *hmtx
)
212 void *hhea
= otf_table(otf
, "hhea");
216 for (i
= 0; i
< n
; i
++)
217 glyph_wid
[i
] = U16(hmtx
, i
* 4);
218 for (i
= n
; i
< glyph_n
; i
++)
219 glyph_wid
[i
] = glyph_wid
[n
- 1];
222 static void otf_kern(struct otf
*otf
, void *kern
)
226 int n
= U16(kern
, 2); /* number of kern subtables */
227 for (i
= 0; i
< n
; i
++) {
228 void *tab
= kern
+ off
; /* a kern subtable */
229 int cov
= U16(tab
, 4);
231 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
232 int npairs
= U16(tab
, 6);
233 for (j
= 0; j
< npairs
; j
++) {
234 int c1
= U16(tab
, 14 + 6 * j
);
235 int c2
= U16(tab
, 14 + 6 * j
+ 2);
236 int val
= S16(tab
, 14 + 6 * j
+ 4);
237 mkfn_kern(glyph_name
[c1
], glyph_name
[c2
],
244 static int *coverage(void *cov
, int *ncov
)
246 int fmt
= U16(cov
, 0);
250 int *out
= malloc(glyph_n
* sizeof(*out
));
253 for (i
= 0; i
< n
; i
++)
254 out
[cnt
++] = U16(cov
, 4 + 2 * i
);
257 for (i
= 0; i
< n
; i
++) {
258 beg
= U16(cov
, 4 + 6 * i
);
259 end
= U16(cov
, 4 + 6 * i
+ 2);
260 for (j
= beg
; j
<= end
; j
++)
269 static int classdef(void *tab
, int *gl
, int *cls
)
271 int fmt
= U16(tab
, 0);
275 int beg
= U16(tab
, 2);
277 for (i
= 0; i
< ngl
; i
++) {
279 cls
[i
] = U16(tab
, 6 + 2 * i
);
284 for (i
= 0; i
< n
; i
++) {
285 int beg
= U16(tab
, 4 + 6 * i
);
286 int end
= U16(tab
, 4 + 6 * i
+ 2);
287 for (j
= beg
; j
<= end
; j
++) {
289 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
297 static int intcmp(void *v1
, void *v2
)
299 return *(int *) v1
- *(int *) v2
;
302 static int ggrp_make(int *src
, int n
);
304 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
306 int *g
= malloc(nsrc
* sizeof(g
[0]));
310 for (i
= 0; i
< nsrc
; i
++)
313 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
314 grp
= ggrp_make(g
, n
);
319 static int ggrp_coverage(int *g
, int n
)
321 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
322 return ggrp_make(g
, n
);
325 static int valuerecord_len(int fmt
)
329 for (i
= 0; i
< 8; i
++)
335 static void valuerecord_print(int fmt
, void *rec
)
340 for (i
= 0; i
< 8; i
++) {
341 if (fmt
& (1 << i
)) {
342 vals
[i
] = uwid(S16(rec
, off
));
347 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
350 static int valuerecord_small(int fmt
, void *rec
)
354 for (i
= 0; i
< 8; i
++) {
355 if (fmt
& (1 << i
)) {
356 if (abs(uwid(S16(rec
, off
))) >= MAX(1, mkfn_kmin
))
364 /* single adjustment positioning */
365 static void otf_gpostype1(struct otf
*otf
, void *sub
, char *feat
)
367 int fmt
= U16(sub
, 0);
368 int vfmt
= U16(sub
, 4);
371 int vlen
= valuerecord_len(vfmt
);
373 cov
= coverage(sub
+ U16(sub
, 2), &ncov
);
375 for (i
= 0; i
< ncov
; i
++) {
376 if (valuerecord_small(vfmt
, sub
+ 6))
378 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
379 valuerecord_print(vfmt
, sub
+ 6);
385 for (i
= 0; i
< nvals
; i
++) {
386 if (valuerecord_small(vfmt
, sub
+ 6))
388 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
389 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
396 /* pair adjustment positioning */
397 static void otf_gpostype2(struct otf
*otf
, void *sub
, char *feat
)
399 int fmt
= U16(sub
, 0);
400 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
401 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
402 int fmtoff1
, fmtoff2
;
403 int vrlen
; /* the length of vfmt1 and vfmt2 */
405 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
407 int nc1
= U16(sub
, 8);
408 int *cov
= coverage(sub
+ U16(sub
, 2), NULL
);
409 for (i
= 0; i
< nc1
; i
++) {
410 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
411 int nc2
= U16(c2
, 0);
412 for (j
= 0; j
< nc2
; j
++) {
413 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
414 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
415 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
416 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
417 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
419 printf("gpos %s 2", feat
);
420 printf(" %s", glyph_name
[cov
[i
]]);
421 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
422 printf(" %s", glyph_name
[second
]);
423 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
430 static int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
431 static int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
432 static int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
433 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
434 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
435 int ncls1
= U16(sub
, 12);
436 int ncls2
= U16(sub
, 14);
437 for (i
= 0; i
< ncls1
; i
++)
438 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
439 for (i
= 0; i
< ncls2
; i
++)
440 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
441 for (i
= 0; i
< ncls1
; i
++) {
442 for (j
= 0; j
< ncls2
; j
++) {
443 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
444 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
445 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
446 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
448 printf("gpos %s %d", feat
, 2);
449 printf(" @%d", grp1
[i
]);
450 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
451 printf(" @%d", grp2
[j
]);
452 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
459 /* cursive attachment positioning */
460 static void otf_gpostype3(struct otf
*otf
, void *sub
, char *feat
)
462 int fmt
= U16(sub
, 0);
463 int *cov
, *icov
, *ocov
;
470 cov
= coverage(sub
+ U16(sub
, 2), NULL
);
472 icov
= malloc(n
* sizeof(icov
[0]));
473 ocov
= malloc(n
* sizeof(ocov
[0]));
474 for (i
= 0; i
< n
; i
++)
475 if (U16(sub
, 6 + 4 * i
))
476 ocov
[ocnt
++] = cov
[i
];
477 for (i
= 0; i
< n
; i
++)
478 if (U16(sub
, 6 + 4 * i
+ 2))
479 icov
[icnt
++] = cov
[i
];
480 igrp
= ggrp_coverage(icov
, icnt
);
481 ogrp
= ggrp_coverage(ocov
, ocnt
);
484 for (i
= 0; i
< n
; i
++) {
485 int prev
= U16(sub
, 6 + 4 * i
);
486 int next
= U16(sub
, 6 + 4 * i
+ 2);
488 int dx
= -uwid(S16(sub
, prev
+ 2));
489 int dy
= -uwid(S16(sub
, prev
+ 4));
491 dx
+= uwid(glyph_wid
[cov
[i
]]);
492 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
493 feat
, igrp
, glyph_name
[cov
[i
]],
497 int dx
= uwid(S16(sub
, next
+ 2)) - uwid(glyph_wid
[cov
[i
]]);
498 int dy
= uwid(S16(sub
, next
+ 4));
500 dx
+= uwid(glyph_wid
[cov
[i
]]);
502 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
503 feat
, glyph_name
[cov
[i
]], ogrp
,
510 /* mark-to-base attachment positioning */
511 static void otf_gpostype4(struct otf
*otf
, void *sub
, char *feat
)
513 int fmt
= U16(sub
, 0);
514 int *mcov
; /* mark coverage */
515 int *bcov
; /* base coverage */
516 int cgrp
[1024]; /* glyph groups assigned to classes */
517 int bgrp
; /* the group assigned to base glyphs */
518 int mcnt
; /* mark coverage size */
519 int bcnt
; /* base coverage size */
520 int ccnt
; /* class count */
521 void *marks
; /* mark array table */
522 void *bases
; /* base array table */
526 mcov
= coverage(sub
+ U16(sub
, 2), &mcnt
);
527 bcov
= coverage(sub
+ U16(sub
, 4), &bcnt
);
529 marks
= sub
+ U16(sub
, 8);
530 bases
= sub
+ U16(sub
, 10);
531 /* define a group for base glyphs */
532 bgrp
= ggrp_coverage(bcov
, bcnt
);
533 /* define a group for each mark class */
534 for (i
= 0; i
< ccnt
; i
++) {
535 int *grp
= malloc(mcnt
* sizeof(grp
[0]));
537 for (j
= 0; j
< mcnt
; j
++)
538 if (U16(marks
, 2 + 4 * j
) == i
)
539 grp
[cnt
++] = mcov
[j
];
540 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
543 /* GPOS rules for each mark after base glyphs */
544 printf("gsec %d\n", sec
);
545 for (i
= 0; i
< mcnt
; i
++) {
546 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
547 int dx
= -uwid(S16(mark
, 2));
548 int dy
= -uwid(S16(mark
, 4));
550 dx
+= uwid(glyph_wid
[mcov
[i
]]);
553 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
554 feat
, bgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
556 /* GPOS rules for each base glyph before a mark */
557 printf("gsec %d\n", sec
+ 1);
558 for (i
= 0; i
< bcnt
; i
++) {
559 for (j
= 0; j
< ccnt
; j
++) {
560 void *base
= bases
+ U16(bases
, 2 + ccnt
* 2 * i
+ 2 * j
);
561 int dx
= uwid(S16(base
, 2)) - uwid(glyph_wid
[bcov
[i
]]);
562 int dy
= uwid(S16(base
, 4));
564 dx
+= uwid(glyph_wid
[bcov
[i
]]);
567 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
568 feat
, glyph_name
[bcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
575 /* mark-to-ligature attachment positioning */
576 static void otf_gpostype5(struct otf
*otf
, void *sub
, char *feat
)
578 int fmt
= U16(sub
, 0);
579 int *mcov
; /* mark coverage */
580 int *lcov
; /* ligature coverage */
581 int cgrp
[1024]; /* glyph groups assigned to classes */
582 int lgrp
; /* the group assigned to base glyphs */
583 int mcnt
; /* mark coverage size */
584 int lcnt
; /* ligature coverage size */
585 int ccnt
; /* class count */
586 void *marks
; /* mark array table */
587 void *ligas
; /* ligature array table */
589 /* only marks at the end of ligatures are supported */
592 mcov
= coverage(sub
+ U16(sub
, 2), &mcnt
);
593 lcov
= coverage(sub
+ U16(sub
, 4), &lcnt
);
595 marks
= sub
+ U16(sub
, 8);
596 ligas
= sub
+ U16(sub
, 10);
597 /* define a group for ligatures */
598 lgrp
= ggrp_coverage(lcov
, lcnt
);
599 /* define a group for each mark class */
600 for (i
= 0; i
< ccnt
; i
++) {
601 int *grp
= malloc(mcnt
* sizeof(grp
[0]));
603 for (j
= 0; j
< mcnt
; j
++)
604 if (U16(marks
, 2 + 4 * j
) == i
)
605 grp
[cnt
++] = mcov
[j
];
606 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
609 /* GPOS rules for each mark after a ligature */
610 printf("gsec %d\n", sec
);
611 for (i
= 0; i
< mcnt
; i
++) {
612 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
613 int dx
= -uwid(S16(mark
, 2));
614 int dy
= -uwid(S16(mark
, 4));
616 dx
+= uwid(glyph_wid
[mcov
[i
]]);
619 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
620 feat
, lgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
622 printf("gsec %d\n", sec
+ 1);
623 /* GPOS rules for each ligature before a mark */
624 for (i
= 0; i
< lcnt
; i
++) {
625 void *ligattach
= ligas
+ U16(ligas
, 2 + 2 * i
);
626 int comcnt
= U16(ligattach
, 0); /* component count */
627 /* considering only the last component */
631 if (!U16(ligattach
, 2 + 2 * ccnt
* k
))
633 for (j
= 0; j
< ccnt
; j
++) {
634 char *base
= ligattach
+ U16(ligattach
, 2 + 2 * ccnt
* k
+ 2 * j
);
635 int dx
= uwid(S16(base
, 2)) - uwid(glyph_wid
[lcov
[i
]]);
636 int dy
= uwid(S16(base
, 4));
638 dx
+= uwid(glyph_wid
[lcov
[i
]]);
641 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
642 feat
, glyph_name
[lcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
651 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
652 int igrp
[GCTXLEN
]; /* input coverage arrays */
653 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
654 int bn
, in
, ln
; /* size of b[], i[], l[] */
655 int seqidx
; /* sequence index */
658 static int gctx_len(struct gctx
*ctx
, int patlen
)
660 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
663 static void gctx_backtrack(struct gctx
*ctx
)
668 for (i
= 0; i
< ctx
->bn
; i
++)
669 printf(" =@%d", ctx
->bgrp
[i
]);
670 for (i
= 0; i
< ctx
->seqidx
; i
++)
671 printf(" =@%d", ctx
->igrp
[i
]);
674 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
679 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
680 printf(" =@%d", ctx
->igrp
[i
]);
681 for (i
= 0; i
< ctx
->ln
; i
++)
682 printf(" =@%d", ctx
->lgrp
[i
]);
685 /* single substitution */
686 static void otf_gsubtype1(struct otf
*otf
, void *sub
, char *feat
, struct gctx
*ctx
)
689 int fmt
= U16(sub
, 0);
692 cov
= coverage(sub
+ U16(sub
, 2), &ncov
);
694 for (i
= 0; i
< ncov
; i
++) {
695 int dst
= cov
[i
] + S16(sub
, 4);
696 if (dst
>= glyph_n
|| dst
< 0)
698 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
700 printf(" -%s +%s", glyph_name
[cov
[i
]], glyph_name
[dst
]);
701 gctx_lookahead(ctx
, 1);
707 for (i
= 0; i
< n
; i
++) {
708 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
710 printf(" -%s +%s", glyph_name
[cov
[i
]],
711 glyph_name
[U16(sub
, 6 + 2 * i
)]);
712 gctx_lookahead(ctx
, 1);
719 /* alternate substitution */
720 static void otf_gsubtype3(struct otf
*otf
, void *sub
, char *feat
, struct gctx
*ctx
)
723 int fmt
= U16(sub
, 0);
727 cov
= coverage(sub
+ U16(sub
, 2), NULL
);
729 for (i
= 0; i
< n
; i
++) {
730 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
731 int nalt
= U16(alt
, 0);
732 for (j
= 0; j
< nalt
; j
++) {
733 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
735 printf(" -%s +%s", glyph_name
[cov
[i
]],
736 glyph_name
[U16(alt
, 2 + 2 * j
)]);
737 gctx_lookahead(ctx
, 1);
744 /* ligature substitution */
745 static void otf_gsubtype4(struct otf
*otf
, void *sub
, char *feat
, struct gctx
*ctx
)
747 int fmt
= U16(sub
, 0);
752 cov
= coverage(sub
+ U16(sub
, 2), NULL
);
754 for (i
= 0; i
< n
; i
++) {
755 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
756 int nset
= U16(set
, 0);
757 for (j
= 0; j
< nset
; j
++) {
758 void *lig
= set
+ U16(set
, 2 + 2 * j
);
759 int nlig
= U16(lig
, 2);
760 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
762 printf(" -%s", glyph_name
[cov
[i
]]);
763 for (k
= 0; k
< nlig
- 1; k
++)
764 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
765 printf(" +%s", glyph_name
[U16(lig
, 0)]);
766 gctx_lookahead(ctx
, nlig
);
773 /* chaining contextual substitution */
774 static void otf_gsubtype6(struct otf
*otf
, void *sub
, char *feat
, void *gsub
)
776 struct gctx ctx
= {{0}};
777 void *lookups
= gsub
+ U16(gsub
, 8);
778 int fmt
= U16(sub
, 0);
780 int i
, j
, nsub
, ncov
;
783 otf_unsupported("GSUB", 6, fmt
);
786 ctx
.bn
= U16(sub
, off
);
787 for (i
= 0; i
< ctx
.bn
; i
++) {
788 cov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), &ncov
);
789 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
792 off
+= 2 + 2 * ctx
.bn
;
793 ctx
.in
= U16(sub
, off
);
794 for (i
= 0; i
< ctx
.in
; i
++) {
795 cov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), &ncov
);
796 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
799 off
+= 2 + 2 * ctx
.in
;
800 ctx
.ln
= U16(sub
, off
);
801 for (i
= 0; i
< ctx
.ln
; i
++) {
802 cov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), &ncov
);
803 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
806 off
+= 2 + 2 * ctx
.ln
;
807 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
808 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
809 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
810 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
811 int ltype
= U16(lookup
, 0);
812 int ntabs
= U16(lookup
, 4);
813 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
814 for (j
= 0; j
< ntabs
; j
++) {
815 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
817 if (type
== 7) { /* extension substitution */
819 tab
= tab
+ U32(tab
, 4);
822 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
824 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
826 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
831 /* an otf gsub/gpos lookup */
833 char scrp
[8]; /* script name */
834 char lang
[8]; /* language name */
835 char feat
[8]; /* feature name */
836 int lookup
; /* index into the lookup table */
839 /* parse the given gsub/gpos feature table */
840 static int otf_featrec(struct otf
*otf
, void *gtab
, void *featrec
,
841 char *stag
, char *ltag
,
842 struct otflookup
*lookups
, int lookups_n
)
844 void *feats
= gtab
+ U16(gtab
, 6);
845 void *feat
= feats
+ U16(featrec
, 4);
847 int n
= U16(feat
, 2);
849 memcpy(ftag
, featrec
, 4);
850 for (i
= 0; i
< n
; i
++) {
851 int lookup
= U16(feat
, 4 + 2 * i
); /* lookup index */
852 /* do not store features common to all languages in a script */
853 for (j
= 0; j
< lookups_n
; j
++)
854 if (lookups
[j
].lookup
== lookup
&& !lookups
[j
].lang
[0])
855 if (!strcmp(lookups
[j
].scrp
, stag
) &&
856 !strcmp(lookups
[j
].feat
, ftag
))
858 if (j
== lookups_n
) {
859 strcpy(lookups
[j
].feat
, ftag
);
860 strcpy(lookups
[j
].scrp
, stag
);
861 strcpy(lookups
[j
].lang
, ltag
);
862 lookups
[j
].lookup
= U16(feat
, 4 + 2 * i
);
869 /* parse the given language table and its feature tables */
870 static int otf_lang(struct otf
*otf
, void *gtab
, void *lang
, char *stag
, char *ltag
,
871 struct otflookup
*lookups
, int lookups_n
)
873 void *feats
= gtab
+ U16(gtab
, 6);
874 int featidx
= U16(lang
, 2);
875 int nfeat
= U16(lang
, 4);
877 if (featidx
!= 0xffff)
878 lookups_n
= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
,
879 stag
, ltag
, lookups
, lookups_n
);
880 for (i
= 0; i
< nfeat
; i
++)
881 lookups_n
= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
),
882 stag
, ltag
, lookups
, lookups_n
);
886 /* return lookup table tag (i.e. liga:latn:ENG); returns a static buffer */
887 static char *lookuptag(struct otflookup
*lu
)
890 sprintf(tag
, "%s:%s", lu
->feat
, lu
->scrp
[0] ? lu
->scrp
: "DFLT");
892 sprintf(strchr(tag
, '\0'), ":%s", lu
->lang
);
896 static int lookupcmp(void *v1
, void *v2
)
898 struct otflookup
*l1
= v1
;
899 struct otflookup
*l2
= v2
;
900 if (strcmp(l1
->scrp
, l2
->scrp
))
901 return strcmp(l1
->scrp
, l2
->scrp
);
902 if (mkfn_featrank(l1
->scrp
, l1
->feat
) != mkfn_featrank(l1
->scrp
, l2
->feat
))
903 return mkfn_featrank(l1
->scrp
, l1
->feat
) - mkfn_featrank(l1
->scrp
, l2
->feat
);
904 return l1
->lookup
- l2
->lookup
;
907 /* extract lookup tables for all features of the given gsub/gpos table */
908 static int otf_gtab(struct otf
*otf
, void *gpos
, struct otflookup
*lookups
)
910 void *scripts
= gpos
+ U16(gpos
, 4);
911 int nscripts
, nlangs
;
913 char stag
[8], ltag
[8]; /* script and language tags */
916 nscripts
= U16(scripts
, 0);
917 for (i
= 0; i
< nscripts
; i
++) {
918 void *grec
= scripts
+ 2 + 6 * i
;
919 memcpy(stag
, grec
, 4);
921 if (!mkfn_script(stag
, nscripts
))
923 script
= scripts
+ U16(grec
, 4);
924 nlangs
= U16(script
, 2);
925 if (U16(script
, 0) && mkfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
926 n
= otf_lang(otf
, gpos
, script
+ U16(script
, 0),
927 stag
, "", lookups
, n
);
928 for (j
= 0; j
< nlangs
; j
++) {
929 void *lrec
= script
+ 4 + 6 * j
;
930 memcpy(ltag
, lrec
, 4);
932 if (mkfn_lang(ltag
, nlangs
+ (U16(script
, 0) != 0)))
933 n
= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4),
934 stag
, ltag
, lookups
, n
);
937 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
941 static void otf_gpos(struct otf
*otf
, void *gpos
)
943 struct otflookup lookups
[NLOOKUPS
];
944 void *lookuplist
= gpos
+ U16(gpos
, 8);
945 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
949 for (i
= 0; i
< nlookups
; i
++) {
950 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
951 int ltype
= U16(lookup
, 0);
952 int ntabs
= U16(lookup
, 4);
953 char *tag
= lookuptag(&lookups
[i
]);
955 printf("gsec %d %s\n", sec
, tag
);
956 for (j
= 0; j
< ntabs
; j
++) {
957 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
959 if (type
== 9) { /* extension positioning */
961 tab
= tab
+ U32(tab
, 4);
965 otf_gpostype1(otf
, tab
, tag
);
968 otf_gpostype2(otf
, tab
, tag
);
971 otf_gpostype3(otf
, tab
, tag
);
974 otf_gpostype4(otf
, tab
, tag
);
977 otf_gpostype5(otf
, tab
, tag
);
980 otf_unsupported("GPOS", type
, 0);
986 static void otf_gsub(struct otf
*otf
, void *gsub
)
988 struct otflookup lookups
[NLOOKUPS
];
989 void *lookuplist
= gsub
+ U16(gsub
, 8);
990 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
994 for (i
= 0; i
< nlookups
; i
++) {
995 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
996 int ltype
= U16(lookup
, 0);
997 int ntabs
= U16(lookup
, 4);
998 char *tag
= lookuptag(&lookups
[i
]);
1000 printf("gsec %d %s\n", sec
, tag
);
1001 for (j
= 0; j
< ntabs
; j
++) {
1002 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
1004 if (type
== 7) { /* extension substitution */
1006 tab
= tab
+ U32(tab
, 4);
1010 otf_gsubtype1(otf
, tab
, tag
, NULL
);
1013 otf_gsubtype3(otf
, tab
, tag
, NULL
);
1016 otf_gsubtype4(otf
, tab
, tag
, NULL
);
1019 otf_gsubtype6(otf
, tab
, tag
, gsub
);
1022 otf_unsupported("GSUB", type
, 0);
1028 /* read a cff offset, which has sz bytes */
1029 static int cff_int(void *tab
, int off
, int sz
)
1033 for (i
= 0; i
< sz
; i
++)
1034 n
= n
* 256 + U8(tab
, off
+ i
);
1038 /* cff dict operand/operator */
1039 static int cff_op(void *tab
, int off
, int *val
)
1041 int b0
= U8(tab
, off
);
1043 if (b0
>= 32 && b0
<= 246) {
1047 if (b0
>= 247 && b0
<= 250) {
1048 *val
= (b0
- 247) * 256 + U8(tab
, off
+ 1) + 108;
1051 if (b0
>= 251 && b0
<= 254) {
1052 *val
= -(b0
- 251) * 256 - U8(tab
, off
+ 1) - 108;
1056 *val
= (U8(tab
, off
+ 1) << 8) | U8(tab
, off
+ 2);
1060 *val
= (U8(tab
, off
+ 1) << 24) | (U8(tab
, off
+ 2) << 16) |
1061 (U8(tab
, off
+ 3) << 8) | U8(tab
, off
+ 4);
1065 for (i
= 1; i
< 32; i
++) {
1066 int nib
= U8(tab
, off
+ i
);
1067 if ((nib
& 0x0f) == 0x0f || (nib
& 0xf0) == 0xf0)
1077 static int cffidx_cnt(void *idx
)
1082 static void *cffidx_get(void *idx
, int i
)
1084 int cnt
= U16(idx
, 0);
1085 int sz
= U8(idx
, 2);
1086 return idx
+ 3 + (cnt
+ 1) * sz
- 1 + cff_int(idx
, 3 + i
* sz
, sz
);
1089 static int cffidx_len(void *idx
, int i
)
1091 return cffidx_get(idx
, i
+ 1) - cffidx_get(idx
, i
);
1094 static void *cffidx_end(void *idx
)
1096 return cffidx_get(idx
, cffidx_cnt(idx
));
1099 /* obtain the value of the given key from a cff dict */
1100 static int cffdict_get(void *dict
, int len
, int key
, int *args
)
1105 /* operators: keys (one or two bytes); operands: values */
1109 memmove(args
+ 1, args
+ 0, 3 * sizeof(args
[0]));
1112 off
+= cff_op(dict
, off
, &op
);
1113 if (op
== 12) { /* two-byte operator */
1114 off
+= cff_op(dict
, off
, &op
);
1123 static void cff_char(void *stridx
, int id
, char *dst
)
1127 strcpy(dst
, stdset
[id
]);
1131 len
= cffidx_len(stridx
, id
);
1132 if (mkfn_warn
&& len
>= GNLEN
)
1133 fprintf(stderr
, "neatmkfn: truncating glyph names (GNLEN is too small)\n");
1136 memcpy(dst
, cffidx_get(stridx
, id
), len
);
1140 static void otf_cff(struct otf
*otf
, void *cff
)
1142 void *nameidx
; /* name index */
1143 void *topidx
; /* top dict index */
1144 void *stridx
; /* string idx */
1145 void *chridx
; /* charstrings index */
1146 void *charset
; /* charset offset */
1147 int badcff
; /* invalid CFF SIDs */
1149 if (U8(cff
, 0) != 1)
1151 nameidx
= cff
+ U8(cff
, 2);
1152 topidx
= cffidx_end(nameidx
);
1153 if (cffidx_cnt(nameidx
) < 1)
1155 stridx
= cffidx_end(topidx
);
1156 chridx
= cff
+ cffdict_get(cffidx_get(topidx
, 0),
1157 cffidx_len(topidx
, 0), 17, NULL
);
1158 charset
= cff
+ cffdict_get(cffidx_get(topidx
, 0),
1159 cffidx_len(topidx
, 0), 15, NULL
);
1160 glyph_n
= cffidx_cnt(chridx
);
1161 badcff
= cffidx_cnt(chridx
) - 391 > cffidx_cnt(stridx
);
1162 strcpy(glyph_name
[0], ".notdef");
1163 /* read font name from name index */
1164 if (cffidx_cnt(nameidx
) > 0) {
1165 char name
[256] = "";
1166 memcpy(name
, cffidx_get(nameidx
, 0), cffidx_len(nameidx
, 0));
1167 if (name
[0] && !otf
->name
[0])
1168 snprintf(otf
->name
, sizeof(otf
->name
), "%s", name
);
1170 /* read charset: glyph to character name */
1171 if (!badcff
&& U8(charset
, 0) == 0) {
1172 for (i
= 0; i
< glyph_n
; i
++)
1173 cff_char(stridx
, U16(charset
, 1 + i
* 2),
1176 if (!badcff
&& (U8(charset
, 0) == 1 || U8(charset
, 0) == 2)) {
1178 int sz
= U8(charset
, 0) == 1 ? 3 : 4;
1179 for (i
= 0; g
< glyph_n
; i
++) {
1180 int sid
= U16(charset
, 1 + i
* sz
);
1181 int cnt
= cff_int(charset
, 1 + i
* sz
+ 2, sz
- 2);
1182 for (j
= 0; j
<= cnt
&& g
< glyph_n
; j
++) {
1183 cff_char(stridx
, sid
+ j
, glyph_name
[g
]);
1190 static void *otf_input(int fd
)
1192 struct sbuf
*sb
= sbuf_make();
1195 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
1196 sbuf_mem(sb
, buf
, nr
);
1197 return sbuf_done(sb
);
1200 static void otf_feat(struct otf
*otf
)
1202 if (otf_table(otf
, "GSUB"))
1203 otf_gsub(otf
, otf_table(otf
, "GSUB"));
1204 if (otf_table(otf
, "GPOS"))
1205 otf_gpos(otf
, otf_table(otf
, "GPOS"));
1208 int otf_offsettable(void *otf_otf
, void *otf_off
)
1211 unsigned tag
= U32(otf_off
, 0);
1212 struct otf otf_cur
= {otf_otf
, otf_off
};
1213 struct otf
*otf
= &otf_cur
;
1214 if (tag
!= 0x00010000 && tag
!= 0x4F54544F)
1216 upm
= U16(otf_table(otf
, "head"), 18);
1217 otf_name(otf
, otf_table(otf
, "name"));
1218 otf_cmap(otf
, otf_table(otf
, "cmap"));
1219 otf_post(otf
, otf_table(otf
, "post"));
1220 if (otf_table(otf
, "glyf"))
1221 otf_glyf(otf
, otf_table(otf
, "glyf"));
1222 if (otf_table(otf
, "CFF "))
1223 otf_cff(otf
, otf_table(otf
, "CFF "));
1224 for (i
= 0; i
< glyph_n
; i
++) {
1225 if (!glyph_name
[i
][0]) {
1227 sprintf(glyph_name
[i
], "uni%04X", glyph_code
[i
]);
1229 sprintf(glyph_name
[i
], "gl%05X", i
);
1232 otf_hmtx(otf
, otf_table(otf
, "hmtx"));
1233 if (!mkfn_font(otf
->name
))
1235 for (i
= 0; i
< glyph_n
; i
++) {
1236 mkfn_char(glyph_name
[i
], -1,
1237 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
1239 uwid(glyph_bbox
[i
][0]), uwid(glyph_bbox
[i
][1]),
1240 uwid(glyph_bbox
[i
][2]), uwid(glyph_bbox
[i
][3]));
1242 mkfn_header(otf
->name
);
1243 if (otf_table(otf
, "kern"))
1244 otf_kern(otf
, otf_table(otf
, "kern"));
1251 char *otf_buf
= otf_input(0);
1252 unsigned tag
= U32(otf_buf
, 0);
1254 if (tag
== 0x00010000 || tag
== 0x4F54544F)
1255 return otf_offsettable(otf_buf
, otf_buf
);
1256 if (tag
!= 0x74746366)
1258 /* OpenType Collections */
1259 n
= U32(otf_buf
, 8);
1260 for (i
= 0; i
< n
; i
++) {
1261 void *off
= otf_buf
+ U32(otf_buf
, 12 + i
* 4);
1262 otf_offsettable(otf_buf
, off
);
1268 static int *ggrp_g
[NGRPS
];
1269 static int ggrp_len
[NGRPS
];
1272 static int ggrp_find(int *src
, int n
)
1275 for (i
= 0; i
< ggrp_n
; i
++) {
1276 if (ggrp_len
[i
] == n
) {
1277 for (j
= 0; j
< n
; j
++)
1278 if (src
[j
] != ggrp_g
[i
][j
])
1287 static int ggrp_make(int *src
, int n
)
1289 int id
= ggrp_find(src
, n
);
1294 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
1296 for (i
= 0; i
< n
; i
++)
1297 ggrp_g
[id
][i
] = src
[i
];
1298 printf("ggrp %d %d", id
, n
);
1299 for (i
= 0; i
< n
; i
++)
1300 printf(" %s", glyph_name
[src
[i
]]);
1305 static char *macset
[] = {
1306 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
1307 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
1308 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
1309 "comma", "hyphen", "period", "slash", "zero",
1310 "one", "two", "three", "four", "five",
1311 "six", "seven", "eight", "nine", "colon",
1312 "semicolon", "less", "equal", "greater", "question",
1313 "at", "A", "B", "C", "D",
1314 "E", "F", "G", "H", "I",
1315 "J", "K", "L", "M", "N",
1316 "O", "P", "Q", "R", "S",
1317 "T", "U", "V", "W", "X",
1318 "Y", "Z", "bracketleft", "backslash", "bracketright",
1319 "asciicircum", "underscore", "grave", "a", "b",
1320 "c", "d", "e", "f", "g",
1321 "h", "i", "j", "k", "l",
1322 "m", "n", "o", "p", "q",
1323 "r", "s", "t", "u", "v",
1324 "w", "x", "y", "z", "braceleft",
1325 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
1326 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
1327 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
1328 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
1329 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
1330 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
1331 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
1332 "dagger", "degree", "cent", "sterling", "section",
1333 "bullet", "paragraph", "germandbls", "registered", "copyright",
1334 "trademark", "acute", "dieresis", "notequal", "AE",
1335 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1336 "yen", "mu", "partialdiff", "summation", "product",
1337 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1338 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1339 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1340 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1341 "Otilde", "OE", "oe", "endash", "emdash",
1342 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1343 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1344 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1345 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1346 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1347 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1348 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1349 "dotlessi", "circumflex", "tilde", "macron", "breve",
1350 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1351 "caron", "Lslash", "lslash", "Scaron", "scaron",
1352 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1353 "Yacute", "yacute", "Thorn", "thorn", "minus",
1354 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1355 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1356 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1357 "Ccaron", "ccaron", "dcroat",
1360 static char *stdset
[] = {
1361 ".notdef", "space", "exclam", "quotedbl", "numbersign",
1362 "dollar", "percent", "ampersand", "quoteright", "parenleft",
1363 "parenright", "asterisk", "plus", "comma", "hyphen",
1364 "period", "slash", "zero", "one", "two",
1365 "three", "four", "five", "six", "seven",
1366 "eight", "nine", "colon", "semicolon", "less",
1367 "equal", "greater", "question", "at", "A",
1368 "B", "C", "D", "E", "F",
1369 "G", "H", "I", "J", "K",
1370 "L", "M", "N", "O", "P",
1371 "Q", "R", "S", "T", "U",
1372 "V", "W", "X", "Y", "Z",
1373 "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
1374 "quoteleft", "a", "b", "c", "d",
1375 "e", "f", "g", "h", "i",
1376 "j", "k", "l", "m", "n",
1377 "o", "p", "q", "r", "s",
1378 "t", "u", "v", "w", "x",
1379 "y", "z", "braceleft", "bar", "braceright",
1380 "asciitilde", "exclamdown", "cent", "sterling", "fraction",
1381 "yen", "florin", "section", "currency", "quotesingle",
1382 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
1383 "fl", "endash", "dagger", "daggerdbl", "periodcentered",
1384 "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
1385 "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
1386 "acute", "circumflex", "tilde", "macron", "breve",
1387 "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
1388 "ogonek", "caron", "emdash", "AE", "ordfeminine",
1389 "Lslash", "Oslash", "OE", "ordmasculine", "ae",
1390 "dotlessi", "lslash", "oslash", "oe", "germandbls",
1391 "onesuperior", "logicalnot", "mu", "trademark", "Eth",
1392 "onehalf", "plusminus", "Thorn", "onequarter", "divide",
1393 "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
1394 "registered", "minus", "eth", "multiply", "threesuperior",
1395 "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
1396 "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
1397 "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
1398 "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
1399 "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
1400 "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
1401 "aacute", "acircumflex", "adieresis", "agrave", "aring",
1402 "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
1403 "egrave", "iacute", "icircumflex", "idieresis", "igrave",
1404 "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
1405 "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
1406 "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
1407 "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
1408 "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
1409 "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
1410 "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
1411 "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
1412 "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
1413 "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
1414 "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
1415 "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
1416 "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
1417 "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
1418 "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
1419 "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
1420 "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
1421 "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
1422 "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
1423 "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
1424 "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
1425 "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
1426 "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
1427 "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
1428 "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
1429 "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
1430 "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
1431 "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
1432 "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
1433 "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
1434 "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
1435 "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
1436 "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000",
1437 "001.001", "001.002", "001.003", "Black", "Bold",
1438 "Book", "Light", "Medium", "Regular", "Roman",