trfn_ch.h: fix ws digraph mapping
[neatmkfn.git] / otf.c
blobe348c5635bc149e089887d0fffd6c4323b74d64a
1 /* OpenType and TrueType fonts */
2 #include <arpa/inet.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include "mkfn.h"
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)
15 #define GNLEN (64)
16 #define NGRPS 2048
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;
29 typedef int s32;
30 typedef short s16;
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];
36 static int glyph_n;
37 static int upm; /* units per em */
38 static int sec; /* current font section (lookup index * 10) */
40 struct otf {
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)
70 if (mkfn_warn) {
71 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
72 if (fmt > 0)
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);
82 int i;
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);
88 return NULL;
91 /* obtain postscript font name from name table */
92 static void otf_name(struct otf *otf, void *tab)
94 char name[256];
95 void *str = tab + U16(tab, 4); /* storage area */
96 int n = U16(tab, 2); /* number of name records */
97 int i;
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);
108 name[len] = '\0';
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)
117 int nsegs;
118 void *ends, *begs, *deltas, *offsets;
119 int beg, end, delta, offset;
120 int i, j;
121 nsegs = U16(cmap4, 6) / 2;
122 ends = cmap4 + 14;
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);
131 if (offset) {
132 for (j = beg; j <= end; j++)
133 glyph_code[(U16(offsets + 2 * i,
134 offset + (j - beg) * 2) + delta) & 0xffff] = j;
135 } else {
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);
146 int i;
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)
154 otf_cmap4(otf, tab);
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 */
163 int cname = 0;
164 int i;
165 if (U32(post, 0) != 0x20000)
166 return;
167 post2 = post + 32;
168 glyph_n = U16(post2, 0);
169 index = post2 + 2;
170 names = index + 2 * glyph_n;
171 for (i = 0; i < glyph_n; i++) {
172 int idx = U16(index, 2 * i);
173 if (idx < 258) {
174 strcpy(glyph_name[i], macset[idx]);
175 } else {
176 memcpy(glyph_name[i], names + cname + 1,
177 U8(names, cname));
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");
189 void *gdat;
190 void *gdat_next;
191 int n = U16(maxp, 4);
192 int fmt = U16(head, 50);
193 int i, j;
194 if (!glyph_n)
195 glyph_n = n;
196 for (i = 0; i < n; i++) {
197 if (fmt) {
198 gdat = glyf + U32(loca, 4 * i);
199 gdat_next = glyf + U32(loca, 4 * (i + 1));
200 } else {
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");
213 int n;
214 int i;
215 n = U16(hhea, 34);
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)
224 int off = 4;
225 int i, j;
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);
230 off += U16(tab, 2);
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],
238 uwid(val));
244 static int *coverage(void *cov, int *ncov)
246 int fmt = U16(cov, 0);
247 int n = U16(cov, 2);
248 int beg, end;
249 int i, j;
250 int *out = malloc(glyph_n * sizeof(*out));
251 int cnt = 0;
252 if (fmt == 1) {
253 for (i = 0; i < n; i++)
254 out[cnt++] = U16(cov, 4 + 2 * i);
256 if (fmt == 2) {
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++)
261 out[cnt++] = j;
264 if (ncov)
265 *ncov = cnt;
266 return out;
269 static int classdef(void *tab, int *gl, int *cls)
271 int fmt = U16(tab, 0);
272 int ngl = 0;
273 int i, j;
274 if (fmt == 1) {
275 int beg = U16(tab, 2);
276 ngl = U16(tab, 4);
277 for (i = 0; i < ngl; i++) {
278 gl[i] = beg + i;
279 cls[i] = U16(tab, 6 + 2 * i);
282 if (fmt == 2) {
283 int n = U16(tab, 2);
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++) {
288 gl[ngl] = j;
289 cls[ngl] = U16(tab, 4 + 6 * i + 4);
290 ngl++;
294 return ngl;
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]));
307 int n = 0;
308 int i;
309 int grp;
310 for (i = 0; i < nsrc; i++)
311 if (cls[i] == id)
312 g[n++] = src[i];
313 qsort(g, n, sizeof(g[0]), (void *) intcmp);
314 grp = ggrp_make(g, n);
315 free(g);
316 return grp;
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)
327 int off = 0;
328 int i;
329 for (i = 0; i < 8; i++)
330 if (fmt & (1 << i))
331 off += 2;
332 return off;
335 static void valuerecord_print(int fmt, void *rec)
337 int vals[8] = {0};
338 int off = 0;
339 int i;
340 for (i = 0; i < 8; i++) {
341 if (fmt & (1 << i)) {
342 vals[i] = uwid(S16(rec, off));
343 off += 2;
346 if (fmt)
347 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
350 static int valuerecord_small(int fmt, void *rec)
352 int off = 0;
353 int i;
354 for (i = 0; i < 8; i++) {
355 if (fmt & (1 << i)) {
356 if (abs(uwid(S16(rec, off))) >= MAX(1, mkfn_kmin))
357 return 0;
358 off += 2;
361 return 1;
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);
369 int *cov;
370 int ncov, nvals;
371 int vlen = valuerecord_len(vfmt);
372 int i;
373 cov = coverage(sub + U16(sub, 2), &ncov);
374 if (fmt == 1) {
375 for (i = 0; i < ncov; i++) {
376 if (valuerecord_small(vfmt, sub + 6))
377 continue;
378 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
379 valuerecord_print(vfmt, sub + 6);
380 printf("\n");
383 if (fmt == 2) {
384 nvals = U16(sub, 6);
385 for (i = 0; i < nvals; i++) {
386 if (valuerecord_small(vfmt, sub + 6))
387 continue;
388 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
389 valuerecord_print(vfmt, sub + 8 + i * vlen);
390 printf("\n");
393 free(cov);
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 */
404 int i, j;
405 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
406 if (fmt == 1) {
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))
418 continue;
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);
424 printf("\n");
427 free(cov);
429 if (fmt == 2) {
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))
447 continue;
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);
453 printf("\n");
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;
464 int i, n;
465 int icnt = 0;
466 int ocnt = 0;
467 int igrp, ogrp;
468 if (fmt != 1)
469 return;
470 cov = coverage(sub + U16(sub, 2), NULL);
471 n = U16(sub, 4);
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);
482 free(icov);
483 free(ocov);
484 for (i = 0; i < n; i++) {
485 int prev = U16(sub, 6 + 4 * i);
486 int next = U16(sub, 6 + 4 * i + 2);
487 if (prev) {
488 int dx = -uwid(S16(sub, prev + 2));
489 int dy = -uwid(S16(sub, prev + 4));
490 if (otf_r2l(feat))
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]],
494 0, 0, dx, dy);
496 if (next) {
497 int dx = uwid(S16(sub, next + 2)) - uwid(glyph_wid[cov[i]]);
498 int dy = uwid(S16(sub, next + 4));
499 if (otf_r2l(feat)) {
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,
504 0, 0, dx, dy);
507 free(cov);
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 */
523 int i, j;
524 if (fmt != 1)
525 return;
526 mcov = coverage(sub + U16(sub, 2), &mcnt);
527 bcov = coverage(sub + U16(sub, 4), &bcnt);
528 ccnt = U16(sub, 6);
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]));
536 int cnt = 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);
541 free(grp);
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));
549 if (otf_r2l(feat)) {
550 dx += uwid(glyph_wid[mcov[i]]);
551 dy = -dy;
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));
563 if (otf_r2l(feat)) {
564 dx += uwid(glyph_wid[bcov[i]]);
565 dy = -dy;
567 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
568 feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
571 free(mcov);
572 free(bcov);
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 */
588 int i, j, k;
589 /* only marks at the end of ligatures are supported */
590 if (fmt != 1)
591 return;
592 mcov = coverage(sub + U16(sub, 2), &mcnt);
593 lcov = coverage(sub + U16(sub, 4), &lcnt);
594 ccnt = U16(sub, 6);
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]));
602 int cnt = 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);
607 free(grp);
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));
615 if (otf_r2l(feat)) {
616 dx += uwid(glyph_wid[mcov[i]]);
617 dy = -dy;
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 */
628 k = comcnt - 1;
629 if (comcnt == 0)
630 continue;
631 if (!U16(ligattach, 2 + 2 * ccnt * k))
632 continue;
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));
637 if (otf_r2l(feat)) {
638 dx += uwid(glyph_wid[lcov[i]]);
639 dy = -dy;
641 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
642 feat, glyph_name[lcov[i]], cgrp[j], dx, dy, 0, 0);
645 free(mcov);
646 free(lcov);
649 /* gsub context */
650 struct gctx {
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)
665 int i;
666 if (!ctx)
667 return;
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)
676 int i;
677 if (!ctx)
678 return;
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)
688 int *cov;
689 int fmt = U16(sub, 0);
690 int ncov;
691 int i;
692 cov = coverage(sub + U16(sub, 2), &ncov);
693 if (fmt == 1) {
694 for (i = 0; i < ncov; i++) {
695 int dst = cov[i] + S16(sub, 4);
696 if (dst >= glyph_n || dst < 0)
697 continue;
698 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
699 gctx_backtrack(ctx);
700 printf(" -%s +%s", glyph_name[cov[i]], glyph_name[dst]);
701 gctx_lookahead(ctx, 1);
702 printf("\n");
705 if (fmt == 2) {
706 int n = U16(sub, 4);
707 for (i = 0; i < n; i++) {
708 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
709 gctx_backtrack(ctx);
710 printf(" -%s +%s", glyph_name[cov[i]],
711 glyph_name[U16(sub, 6 + 2 * i)]);
712 gctx_lookahead(ctx, 1);
713 printf("\n");
716 free(cov);
719 /* alternate substitution */
720 static void otf_gsubtype3(struct otf *otf, void *sub, char *feat, struct gctx *ctx)
722 int *cov;
723 int fmt = U16(sub, 0);
724 int n, i, j;
725 if (fmt != 1)
726 return;
727 cov = coverage(sub + U16(sub, 2), NULL);
728 n = U16(sub, 4);
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));
734 gctx_backtrack(ctx);
735 printf(" -%s +%s", glyph_name[cov[i]],
736 glyph_name[U16(alt, 2 + 2 * j)]);
737 gctx_lookahead(ctx, 1);
738 printf("\n");
741 free(cov);
744 /* ligature substitution */
745 static void otf_gsubtype4(struct otf *otf, void *sub, char *feat, struct gctx *ctx)
747 int fmt = U16(sub, 0);
748 int *cov;
749 int n, i, j, k;
750 if (fmt != 1)
751 return;
752 cov = coverage(sub + U16(sub, 2), NULL);
753 n = U16(sub, 4);
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));
761 gctx_backtrack(ctx);
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);
767 printf("\n");
770 free(cov);
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);
779 int *cov;
780 int i, j, nsub, ncov;
781 int off = 2;
782 if (fmt != 3) {
783 otf_unsupported("GSUB", 6, fmt);
784 return;
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);
790 free(cov);
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);
797 free(cov);
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);
804 free(cov);
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);
816 int type = ltype;
817 if (type == 7) { /* extension substitution */
818 type = U16(tab, 2);
819 tab = tab + U32(tab, 4);
821 if (type == 1)
822 otf_gsubtype1(otf, tab, feat, &ctx);
823 if (type == 3)
824 otf_gsubtype3(otf, tab, feat, &ctx);
825 if (type == 4)
826 otf_gsubtype4(otf, tab, feat, &ctx);
831 /* an otf gsub/gpos lookup */
832 struct otflookup {
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);
846 char ftag[8] = "";
847 int n = U16(feat, 2);
848 int i, j;
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))
857 break;
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);
863 lookups_n++;
866 return lookups_n;
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);
876 int i;
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);
883 return lookups_n;
886 /* return lookup table tag (i.e. liga:latn:ENG); returns a static buffer */
887 static char *lookuptag(struct otflookup *lu)
889 static char tag[16];
890 sprintf(tag, "%s:%s", lu->feat, lu->scrp[0] ? lu->scrp : "DFLT");
891 if (lu->lang[0])
892 sprintf(strchr(tag, '\0'), ":%s", lu->lang);
893 return tag;
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;
912 void *script;
913 char stag[8], ltag[8]; /* script and language tags */
914 int i, j;
915 int n = 0;
916 nscripts = U16(scripts, 0);
917 for (i = 0; i < nscripts; i++) {
918 void *grec = scripts + 2 + 6 * i;
919 memcpy(stag, grec, 4);
920 stag[4] = '\0';
921 if (!mkfn_script(stag, nscripts))
922 continue;
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);
931 ltag[4] = '\0';
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);
938 return n;
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);
946 int i, j;
947 if (mkfn_dry)
948 return;
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]);
954 sec = (i + 1) * 10;
955 printf("gsec %d %s\n", sec, tag);
956 for (j = 0; j < ntabs; j++) {
957 void *tab = lookup + U16(lookup, 6 + 2 * j);
958 int type = ltype;
959 if (type == 9) { /* extension positioning */
960 type = U16(tab, 2);
961 tab = tab + U32(tab, 4);
963 switch (type) {
964 case 1:
965 otf_gpostype1(otf, tab, tag);
966 break;
967 case 2:
968 otf_gpostype2(otf, tab, tag);
969 break;
970 case 3:
971 otf_gpostype3(otf, tab, tag);
972 break;
973 case 4:
974 otf_gpostype4(otf, tab, tag);
975 break;
976 case 5:
977 otf_gpostype5(otf, tab, tag);
978 break;
979 default:
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);
991 int i, j;
992 if (mkfn_dry)
993 return;
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]);
999 sec = (i + 1) * 10;
1000 printf("gsec %d %s\n", sec, tag);
1001 for (j = 0; j < ntabs; j++) {
1002 void *tab = lookup + U16(lookup, 6 + 2 * j);
1003 int type = ltype;
1004 if (type == 7) { /* extension substitution */
1005 type = U16(tab, 2);
1006 tab = tab + U32(tab, 4);
1008 switch (type) {
1009 case 1:
1010 otf_gsubtype1(otf, tab, tag, NULL);
1011 break;
1012 case 3:
1013 otf_gsubtype3(otf, tab, tag, NULL);
1014 break;
1015 case 4:
1016 otf_gsubtype4(otf, tab, tag, NULL);
1017 break;
1018 case 6:
1019 otf_gsubtype6(otf, tab, tag, gsub);
1020 break;
1021 default:
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)
1031 int i;
1032 int n = 0;
1033 for (i = 0; i < sz; i++)
1034 n = n * 256 + U8(tab, off + i);
1035 return n;
1038 /* cff dict operand/operator */
1039 static int cff_op(void *tab, int off, int *val)
1041 int b0 = U8(tab, off);
1042 int i;
1043 if (b0 >= 32 && b0 <= 246) {
1044 *val = b0 - 139;
1045 return 1;
1047 if (b0 >= 247 && b0 <= 250) {
1048 *val = (b0 - 247) * 256 + U8(tab, off + 1) + 108;
1049 return 2;
1051 if (b0 >= 251 && b0 <= 254) {
1052 *val = -(b0 - 251) * 256 - U8(tab, off + 1) - 108;
1053 return 2;
1055 if (b0 == 28) {
1056 *val = (U8(tab, off + 1) << 8) | U8(tab, off + 2);
1057 return 3;
1059 if (b0 == 29) {
1060 *val = (U8(tab, off + 1) << 24) | (U8(tab, off + 2) << 16) |
1061 (U8(tab, off + 3) << 8) | U8(tab, off + 4);
1062 return 5;
1064 if (b0 == 30) {
1065 for (i = 1; i < 32; i++) {
1066 int nib = U8(tab, off + i);
1067 if ((nib & 0x0f) == 0x0f || (nib & 0xf0) == 0xf0)
1068 break;
1070 *val = 0;
1071 return i + 1;
1073 *val = b0;
1074 return 1;
1077 static int cffidx_cnt(void *idx)
1079 return U16(idx, 0);
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)
1102 int off = 0;
1103 int op = 0;
1104 int val = 0;
1105 /* operators: keys (one or two bytes); operands: values */
1106 while (off < len) {
1107 val = op;
1108 if (args) {
1109 memmove(args + 1, args + 0, 3 * sizeof(args[0]));
1110 args[0] = val;
1112 off += cff_op(dict, off, &op);
1113 if (op == 12) { /* two-byte operator */
1114 off += cff_op(dict, off, &op);
1115 op += 1200;
1117 if (op == key)
1118 return val;
1120 return 0;
1123 static void cff_char(void *stridx, int id, char *dst)
1125 int len;
1126 if (id < 391) {
1127 strcpy(dst, stdset[id]);
1128 return;
1130 id -= 391;
1131 len = cffidx_len(stridx, id);
1132 if (mkfn_warn && len >= GNLEN)
1133 fprintf(stderr, "neatmkfn: truncating glyph names (GNLEN is too small)\n");
1134 if (len >= GNLEN)
1135 len = GNLEN - 1;
1136 memcpy(dst, cffidx_get(stridx, id), len);
1137 dst[len] = '\0';
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 */
1148 int i, j;
1149 if (U8(cff, 0) != 1)
1150 return;
1151 nameidx = cff + U8(cff, 2);
1152 topidx = cffidx_end(nameidx);
1153 if (cffidx_cnt(nameidx) < 1)
1154 return;
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),
1174 glyph_name[i + 1]);
1176 if (!badcff && (U8(charset, 0) == 1 || U8(charset, 0) == 2)) {
1177 int g = 1;
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]);
1184 g++;
1190 static void *otf_input(int fd)
1192 struct sbuf *sb = sbuf_make();
1193 char buf[1 << 12];
1194 int nr = 0;
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)
1210 int i;
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)
1215 return 1;
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]) {
1226 if (glyph_code[i])
1227 sprintf(glyph_name[i], "uni%04X", glyph_code[i]);
1228 else
1229 sprintf(glyph_name[i], "gl%05X", i);
1232 otf_hmtx(otf, otf_table(otf, "hmtx"));
1233 if (!mkfn_font(otf->name))
1234 return 0;
1235 for (i = 0; i < glyph_n; i++) {
1236 mkfn_char(glyph_name[i], -1,
1237 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
1238 uwid(glyph_wid[i]),
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"));
1245 otf_feat(otf);
1246 return 0;
1249 int otf_read(void)
1251 char *otf_buf = otf_input(0);
1252 unsigned tag = U32(otf_buf, 0);
1253 int n, i;
1254 if (tag == 0x00010000 || tag == 0x4F54544F)
1255 return otf_offsettable(otf_buf, otf_buf);
1256 if (tag != 0x74746366)
1257 return 1;
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);
1264 return 0;
1267 /* glyph groups */
1268 static int *ggrp_g[NGRPS];
1269 static int ggrp_len[NGRPS];
1270 static int ggrp_n;
1272 static int ggrp_find(int *src, int n)
1274 int i, j;
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])
1279 break;
1280 if (j == n)
1281 return i;
1284 return -1;
1287 static int ggrp_make(int *src, int n)
1289 int id = ggrp_find(src, n);
1290 int i;
1291 if (id >= 0)
1292 return id;
1293 id = ggrp_n++;
1294 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
1295 ggrp_len[id] = n;
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]]);
1301 printf("\n");
1302 return id;
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",
1439 "Semibold",