trfn: declare trfn_pspath() in trfn.h
[neatmkfn.git] / otf.c
blobf7fbcdfe5a41016cb228cd4082a0b3266b5e9239
1 #include <arpa/inet.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include "sbuf.h"
8 #include "trfn.h"
10 #define MAX(a, b) ((a) < (b) ? (b) : (a))
11 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
13 #define NGLYPHS (1 << 14)
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 res; /* device resolution */
39 static int kmin; /* minimum kerning value */
40 static int warn; /* report unsupported tables */
42 static char *macset[];
43 static char *stdset[];
45 static int owid(int w)
47 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
50 static int uwid(int w)
52 int d = 72000 / res;
53 return (w < 0 ? owid(w) - d / 20 : owid(w) + d / 20) * 10 / d;
56 /* weather the script is right-to-left */
57 static int otf_r2l(char *feat)
59 char *scrp = strchr(feat, ':') + 1;
60 return !strcmp("arab", scrp) || !strcmp("hebr", scrp);
63 /* report unsupported otf tables */
64 static void otf_unsupported(char *sub, int type, int fmt)
66 if (warn) {
67 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
68 if (fmt > 0)
69 fprintf(stderr, " format %d", fmt);
70 fprintf(stderr, "\n");
74 /* find the otf table with the given name */
75 static void *otf_table(void *otf, char *name)
77 int nrecs = U16(otf, 4);
78 int i;
79 for (i = 0; i < nrecs; i++) {
80 void *rec = otf + 12 + i * 16; /* an otf table record */
81 if (!strncmp(rec, name, 4))
82 return otf + U32(rec, 8);
84 return NULL;
87 /* obtain postscript font name from name table */
88 static void otf_name(void *otf, void *tab)
90 char name[256];
91 void *str = tab + U16(tab, 4); /* storage area */
92 int n = U16(tab, 2); /* number of name records */
93 int i;
94 for (i = 0; i < n; i++) {
95 void *rec = tab + 6 + 12 * i;
96 int pid = U16(rec, 0); /* platform id */
97 int eid = U16(rec, 2); /* encoding id */
98 int lid = U16(rec, 4); /* language id */
99 int nid = U16(rec, 6); /* name id */
100 int len = U16(rec, 8); /* string length */
101 int off = U16(rec, 10); /* string offset */
102 if (pid == 1 && eid == 0 && lid == 0 && nid == 6) {
103 memcpy(name, str + off, len);
104 name[len] = '\0';
105 trfn_psfont(name);
110 /* parse otf cmap format 4 subtable */
111 static void otf_cmap4(void *otf, void *cmap4)
113 int nsegs;
114 void *ends, *begs, *deltas, *offsets;
115 int beg, end, delta, offset;
116 int i, j;
117 nsegs = U16(cmap4, 6) / 2;
118 ends = cmap4 + 14;
119 begs = ends + 2 * nsegs + 2;
120 deltas = begs + 2 * nsegs;
121 offsets = deltas + 2 * nsegs;
122 for (i = 0; i < nsegs; i++) {
123 beg = U16(begs, 2 * i);
124 end = U16(ends, 2 * i);
125 delta = U16(deltas, 2 * i);
126 offset = U16(offsets, 2 * i);
127 if (offset) {
128 for (j = beg; j <= end; j++)
129 glyph_code[(U16(offsets + 2 * i,
130 offset + (j - beg) * 2) + delta) & 0xffff] = j;
131 } else {
132 for (j = beg; j <= end; j++)
133 glyph_code[(j + delta) & 0xffff] = j;
138 /* parse otf cmap header */
139 static void otf_cmap(void *otf, void *cmap)
141 int nrecs = U16(cmap, 2);
142 int i;
143 for (i = 0; i < nrecs; i++) {
144 void *rec = cmap + 4 + i * 8; /* a cmap record */
145 int plat = U16(rec, 0);
146 int enc = U16(rec, 2);
147 void *tab = cmap + U32(rec, 4); /* a cmap subtable */
148 int fmt = U16(tab, 0);
149 if (plat == 3 && enc == 1 && fmt == 4)
150 otf_cmap4(otf, tab);
154 static void otf_post(void *otf, void *post)
156 void *post2; /* version 2.0 header */
157 void *index; /* glyph name indices */
158 void *names; /* glyph names */
159 int cname = 0;
160 int i;
161 post2 = post + 32;
162 glyph_n = U16(post2, 0);
163 if (U32(post, 0) != 0x20000)
164 return;
165 index = post2 + 2;
166 names = index + 2 * glyph_n;
167 for (i = 0; i < glyph_n; i++) {
168 int idx = U16(index, 2 * i);
169 if (idx < 258) {
170 strcpy(glyph_name[i], macset[idx]);
171 } else {
172 memcpy(glyph_name[i], names + cname + 1,
173 U8(names, cname));
174 glyph_name[i][U8(names, cname)] = '\0';
175 cname += U8(names, cname) + 1;
180 static void otf_glyf(void *otf, void *glyf)
182 void *maxp = otf_table(otf, "maxp");
183 void *head = otf_table(otf, "head");
184 void *loca = otf_table(otf, "loca");
185 void *gdat;
186 void *gdat_next;
187 int n = U16(maxp, 4);
188 int fmt = U16(head, 50);
189 int i, j;
190 for (i = 0; i < n; i++) {
191 if (fmt) {
192 gdat = glyf + U32(loca, 4 * i);
193 gdat_next = glyf + U32(loca, 4 * (i + 1));
194 } else {
195 gdat = glyf + U16(loca, 2 * i) * 2;
196 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
198 if (gdat < gdat_next)
199 for (j = 0; j < 4; j++)
200 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
204 static void otf_hmtx(void *otf, void *hmtx)
206 void *hhea = otf_table(otf, "hhea");
207 int n;
208 int i;
209 n = U16(hhea, 34);
210 for (i = 0; i < n; i++)
211 glyph_wid[i] = U16(hmtx, i * 4);
212 for (i = n; i < glyph_n; i++)
213 glyph_wid[i] = glyph_wid[n - 1];
216 static void otf_kern(void *otf, void *kern)
218 int off = 4;
219 int i, j;
220 int n = U16(kern, 2); /* number of kern subtables */
221 for (i = 0; i < n; i++) {
222 void *tab = kern + off; /* a kern subtable */
223 int cov = U16(tab, 4);
224 off += U16(tab, 2);
225 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
226 int npairs = U16(tab, 6);
227 for (j = 0; j < npairs; j++) {
228 int c1 = U16(tab, 14 + 6 * j);
229 int c2 = U16(tab, 14 + 6 * j + 2);
230 int val = S16(tab, 14 + 6 * j + 4);
231 trfn_kern(glyph_name[c1], glyph_name[c2],
232 owid(val));
238 static int coverage(void *cov, int *out)
240 int fmt = U16(cov, 0);
241 int n = U16(cov, 2);
242 int beg, end;
243 int ncov = 0;
244 int i, j;
245 if (fmt == 1) {
246 for (i = 0; i < n; i++)
247 out[ncov++] = U16(cov, 4 + 2 * i);
249 if (fmt == 2) {
250 for (i = 0; i < n; i++) {
251 beg = U16(cov, 4 + 6 * i);
252 end = U16(cov, 4 + 6 * i + 2);
253 for (j = beg; j <= end; j++)
254 out[ncov++] = j;
257 return ncov;
260 static int classdef(void *tab, int *gl, int *cls)
262 int fmt = U16(tab, 0);
263 int ngl = 0;
264 int i, j;
265 if (fmt == 1) {
266 int beg = U16(tab, 2);
267 ngl = U16(tab, 4);
268 for (i = 0; i < ngl; i++) {
269 gl[i] = beg + i;
270 cls[i] = U16(tab, 6 + 2 * i);
273 if (fmt == 2) {
274 int n = U16(tab, 2);
275 for (i = 0; i < n; i++) {
276 int beg = U16(tab, 4 + 6 * i);
277 int end = U16(tab, 4 + 6 * i + 2);
278 for (j = beg; j <= end; j++) {
279 gl[ngl] = j;
280 cls[ngl] = U16(tab, 4 + 6 * i + 4);
281 ngl++;
285 return ngl;
288 static int intcmp(void *v1, void *v2)
290 return *(int *) v1 - *(int *) v2;
293 static int ggrp_make(int *src, int n);
295 static int ggrp_class(int *src, int *cls, int nsrc, int id)
297 int g[NGLYPHS];
298 int n = 0;
299 int i;
300 for (i = 0; i < nsrc; i++)
301 if (cls[i] == id)
302 g[n++] = src[i];
303 qsort(g, n, sizeof(g[0]), (void *) intcmp);
304 return ggrp_make(g, n);
307 static int ggrp_coverage(int *g, int n)
309 qsort(g, n, sizeof(g[0]), (void *) intcmp);
310 return ggrp_make(g, n);
313 static int valuerecord_len(int fmt)
315 int off = 0;
316 int i;
317 for (i = 0; i < 8; i++)
318 if (fmt & (1 << i))
319 off += 2;
320 return off;
323 static void valuerecord_print(int fmt, void *rec)
325 int vals[8] = {0};
326 int off = 0;
327 int i;
328 for (i = 0; i < 8; i++) {
329 if (fmt & (1 << i)) {
330 vals[i] = uwid(S16(rec, off));
331 off += 2;
334 if (fmt)
335 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
338 static int valuerecord_small(int fmt, void *rec)
340 int off = 0;
341 int i;
342 for (i = 0; i < 8; i++) {
343 if (fmt & (1 << i)) {
344 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
345 return 0;
346 off += 2;
349 return 1;
352 /* single adjustment positioning */
353 static void otf_gpostype1(void *otf, void *sub, char *feat)
355 int fmt = U16(sub, 0);
356 int vfmt = U16(sub, 4);
357 int cov[NGLYPHS];
358 int ncov, nvals;
359 int vlen = valuerecord_len(vfmt);
360 int i;
361 ncov = coverage(sub + U16(sub, 2), cov);
362 if (fmt == 1) {
363 for (i = 0; i < ncov; i++) {
364 if (valuerecord_small(vfmt, sub + 6))
365 continue;
366 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
367 valuerecord_print(vfmt, sub + 6);
368 printf("\n");
371 if (fmt == 2) {
372 nvals = U16(sub, 6);
373 for (i = 0; i < nvals; i++) {
374 if (valuerecord_small(vfmt, sub + 6))
375 continue;
376 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
377 valuerecord_print(vfmt, sub + 8 + i * vlen);
378 printf("\n");
383 /* pair adjustment positioning */
384 static void otf_gpostype2(void *otf, void *sub, char *feat)
386 int fmt = U16(sub, 0);
387 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
388 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
389 int fmtoff1, fmtoff2;
390 int vrlen; /* the length of vfmt1 and vfmt2 */
391 int i, j;
392 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
393 if (fmt == 1) {
394 int cov[NGLYPHS];
395 int nc1 = U16(sub, 8);
396 coverage(sub + U16(sub, 2), cov);
397 for (i = 0; i < nc1; i++) {
398 void *c2 = sub + U16(sub, 10 + 2 * i);
399 int nc2 = U16(c2, 0);
400 for (j = 0; j < nc2; j++) {
401 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
402 fmtoff1 = 2 + (2 + vrlen) * j + 2;
403 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
404 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
405 valuerecord_small(vfmt2, c2 + fmtoff2))
406 continue;
407 printf("gpos %s 2", feat);
408 printf(" %s", glyph_name[cov[i]]);
409 valuerecord_print(vfmt1, c2 + fmtoff1);
410 printf(" %s", glyph_name[second]);
411 valuerecord_print(vfmt2, c2 + fmtoff2);
412 printf("\n");
416 if (fmt == 2) {
417 int gl1[NGLYPHS], gl2[NGLYPHS];
418 int cls1[NGLYPHS], cls2[NGLYPHS];
419 int grp1[NGLYPHS], grp2[NGLYPHS];
420 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
421 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
422 int ncls1 = U16(sub, 12);
423 int ncls2 = U16(sub, 14);
424 for (i = 0; i < ncls1; i++)
425 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
426 for (i = 0; i < ncls2; i++)
427 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
428 for (i = 0; i < ncls1; i++) {
429 for (j = 0; j < ncls2; j++) {
430 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
431 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
432 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
433 valuerecord_small(vfmt2, sub + fmtoff2))
434 continue;
435 printf("gpos %s %d", feat, 2);
436 printf(" @%d", grp1[i]);
437 valuerecord_print(vfmt1, sub + fmtoff1);
438 printf(" @%d", grp2[j]);
439 valuerecord_print(vfmt2, sub + fmtoff2);
440 printf("\n");
446 /* cursive attachment positioning */
447 static void otf_gpostype3(void *otf, void *sub, char *feat)
449 int fmt = U16(sub, 0);
450 int cov[NGLYPHS];
451 int icov[NGLYPHS];
452 int ocov[NGLYPHS];
453 int i, n;
454 int icnt = 0;
455 int ocnt = 0;
456 int igrp, ogrp;
457 coverage(sub + U16(sub, 2), cov);
458 if (fmt != 1)
459 return;
460 n = U16(sub, 4);
461 for (i = 0; i < n; i++)
462 if (U16(sub, 6 + 4 * i))
463 ocov[ocnt++] = cov[i];
464 for (i = 0; i < n; i++)
465 if (U16(sub, 6 + 4 * i + 2))
466 icov[icnt++] = cov[i];
467 igrp = ggrp_coverage(icov, icnt);
468 ogrp = ggrp_coverage(ocov, ocnt);
469 for (i = 0; i < n; i++) {
470 int prev = U16(sub, 6 + 4 * i);
471 int next = U16(sub, 6 + 4 * i + 2);
472 if (prev) {
473 int dx = -uwid(S16(sub, prev + 2));
474 int dy = -uwid(S16(sub, prev + 4));
475 if (otf_r2l(feat)) {
476 dx += uwid(glyph_wid[cov[i]]);
478 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
479 feat, igrp, glyph_name[cov[i]],
480 0, 0, dx, dy);
482 if (next) {
483 int dx = uwid(S16(sub, next + 2)) - uwid(glyph_wid[cov[i]]);
484 int dy = uwid(S16(sub, next + 4));
485 if (otf_r2l(feat)) {
486 dx += uwid(glyph_wid[cov[i]]);
488 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
489 feat, glyph_name[cov[i]], ogrp,
490 0, 0, dx, dy);
495 /* mark-to-base attachment positioning */
496 static void otf_gpostype4(void *otf, void *sub, char *feat)
498 int fmt = U16(sub, 0);
499 int mcov[NGLYPHS]; /* mark coverage */
500 int bcov[NGLYPHS]; /* base coverage */
501 int cgrp[1024]; /* glyph groups assigned to classes */
502 int bgrp; /* the group assigned to base glyphs */
503 int mcnt; /* mark coverage size */
504 int bcnt; /* base coverage size */
505 int ccnt; /* class count */
506 void *marks; /* mark array table */
507 void *bases; /* base array table */
508 int i, j;
509 if (fmt != 1)
510 return;
511 mcnt = coverage(sub + U16(sub, 2), mcov);
512 bcnt = coverage(sub + U16(sub, 4), bcov);
513 ccnt = U16(sub, 6);
514 marks = sub + U16(sub, 8);
515 bases = sub + U16(sub, 10);
516 bgrp = ggrp_coverage(bcov, bcnt);
517 for (i = 0; i < ccnt; i++) {
518 int grp[NGLYPHS];
519 int cnt = 0;
520 for (j = 0; j < mcnt; j++)
521 if (U16(marks, 2 + 4 * j) == i)
522 grp[cnt++] = mcov[j];
523 cgrp[i] = ggrp_coverage(grp, cnt);
525 for (i = 0; i < mcnt; i++) {
526 void *mark = marks + U16(marks, 2 + 4 * i + 2); /* mark anchor */
527 int dx = -uwid(S16(mark, 2));
528 int dy = -uwid(S16(mark, 4));
529 if (otf_r2l(feat)) {
530 dx += uwid(glyph_wid[mcov[i]]);
531 dy = -dy;
533 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
534 feat, bgrp, glyph_name[mcov[i]], dx, dy, 0, 0);
536 for (i = 0; i < bcnt; i++) {
537 for (j = 0; j < ccnt; j++) {
538 void *base = bases + U16(bases, 2 + ccnt * 2 * i + 2 * j);
539 int dx = uwid(S16(base, 2)) - uwid(glyph_wid[bcov[i]]);
540 int dy = uwid(S16(base, 4));
541 if (otf_r2l(feat)) {
542 dx += uwid(glyph_wid[bcov[i]]);
543 dy = -dy;
545 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
546 feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
551 /* gsub context */
552 struct gctx {
553 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
554 int igrp[GCTXLEN]; /* input coverage arrays */
555 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
556 int bn, in, ln; /* size of b[], i[], l[] */
557 int seqidx; /* sequence index */
560 static int gctx_len(struct gctx *ctx, int patlen)
562 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
565 static void gctx_backtrack(struct gctx *ctx)
567 int i;
568 if (!ctx)
569 return;
570 for (i = 0; i < ctx->bn; i++)
571 printf(" =@%d", ctx->bgrp[i]);
572 for (i = 0; i < ctx->seqidx; i++)
573 printf(" =@%d", ctx->igrp[i]);
576 static void gctx_lookahead(struct gctx *ctx, int patlen)
578 int i;
579 if (!ctx)
580 return;
581 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
582 printf(" =@%d", ctx->igrp[i]);
583 for (i = 0; i < ctx->ln; i++)
584 printf(" =@%d", ctx->lgrp[i]);
587 /* single substitution */
588 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
590 int cov[NGLYPHS];
591 int fmt = U16(sub, 0);
592 int ncov;
593 int i;
594 ncov = coverage(sub + U16(sub, 2), cov);
595 if (fmt == 1) {
596 for (i = 0; i < ncov; i++) {
597 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
598 gctx_backtrack(ctx);
599 printf(" -%s +%s", glyph_name[cov[i]],
600 glyph_name[cov[i] + S16(sub, 4)]);
601 gctx_lookahead(ctx, 1);
602 printf("\n");
605 if (fmt == 2) {
606 int n = U16(sub, 4);
607 for (i = 0; i < n; i++) {
608 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
609 gctx_backtrack(ctx);
610 printf(" -%s +%s", glyph_name[cov[i]],
611 glyph_name[U16(sub, 6 + 2 * i)]);
612 gctx_lookahead(ctx, 1);
613 printf("\n");
618 /* alternate substitution */
619 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
621 int cov[NGLYPHS];
622 int fmt = U16(sub, 0);
623 int n, i, j;
624 if (fmt != 1)
625 return;
626 coverage(sub + U16(sub, 2), cov);
627 n = U16(sub, 4);
628 for (i = 0; i < n; i++) {
629 void *alt = sub + U16(sub, 6 + 2 * i);
630 int nalt = U16(alt, 0);
631 for (j = 0; j < nalt; j++) {
632 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
633 gctx_backtrack(ctx);
634 printf(" -%s +%s", glyph_name[cov[i]],
635 glyph_name[U16(alt, 2 + 2 * j)]);
636 gctx_lookahead(ctx, 1);
637 printf("\n");
642 /* ligature substitution */
643 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
645 int fmt = U16(sub, 0);
646 int cov[NGLYPHS];
647 int n, i, j, k;
648 if (fmt != 1)
649 return;
650 coverage(sub + U16(sub, 2), cov);
651 n = U16(sub, 4);
652 for (i = 0; i < n; i++) {
653 void *set = sub + U16(sub, 6 + 2 * i);
654 int nset = U16(set, 0);
655 for (j = 0; j < nset; j++) {
656 void *lig = set + U16(set, 2 + 2 * j);
657 int nlig = U16(lig, 2);
658 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
659 gctx_backtrack(ctx);
660 printf(" -%s", glyph_name[cov[i]]);
661 for (k = 0; k < nlig - 1; k++)
662 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
663 printf(" +%s", glyph_name[U16(lig, 0)]);
664 gctx_lookahead(ctx, nlig);
665 printf("\n");
670 /* chaining contextual substitution */
671 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
673 struct gctx ctx = {{0}};
674 void *lookups = gsub + U16(gsub, 8);
675 int fmt = U16(sub, 0);
676 int cov[NGLYPHS];
677 int i, j, nsub, ncov;
678 int off = 2;
679 if (fmt != 3) {
680 otf_unsupported("GSUB", 6, fmt);
681 return;
683 ctx.bn = U16(sub, off);
684 for (i = 0; i < ctx.bn; i++) {
685 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
686 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
688 off += 2 + 2 * ctx.bn;
689 ctx.in = U16(sub, off);
690 for (i = 0; i < ctx.in; i++) {
691 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
692 ctx.igrp[i] = ggrp_coverage(cov, ncov);
694 off += 2 + 2 * ctx.in;
695 ctx.ln = U16(sub, off);
696 for (i = 0; i < ctx.ln; i ++) {
697 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
698 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
700 off += 2 + 2 * ctx.ln;
701 nsub = U16(sub, off); /* nsub > 1 is not supported */
702 for (i = 0; i < nsub && i < 1; i++) {
703 int lidx = U16(sub, off + 2 + 4 * i + 2);
704 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
705 int ltype = U16(lookup, 0);
706 int ntabs = U16(lookup, 4);
707 ctx.seqidx = U16(sub, off + 2 + 4 * i);
708 for (j = 0; j < ntabs; j++) {
709 void *tab = lookup + U16(lookup, 6 + 2 * j);
710 int type = ltype;
711 if (type == 7) { /* extension substitution */
712 type = U16(tab, 2);
713 tab = tab + U32(tab, 4);
715 if (type == 1)
716 otf_gsubtype1(otf, tab, feat, &ctx);
717 if (type == 3)
718 otf_gsubtype3(otf, tab, feat, &ctx);
719 if (type == 4)
720 otf_gsubtype4(otf, tab, feat, &ctx);
725 /* an otf gsub/gpos lookup */
726 struct otflookup {
727 char scrp[8]; /* script name */
728 char lang[8]; /* language name */
729 char feat[8]; /* feature name */
730 int lookup; /* index into the lookup table */
733 /* parse the given gsub/gpos feature table */
734 static int otf_featrec(void *otf, void *gtab, void *featrec,
735 char *stag, char *ltag,
736 struct otflookup *lookups, int lookups_n)
738 void *feats = gtab + U16(gtab, 6);
739 void *feat = feats + U16(featrec, 4);
740 int n = U16(feat, 2);
741 int i, j;
742 for (i = 0; i < n; i++) {
743 int lookup = U16(feat, 4 + 2 * i); /* lookup index */
744 /* do not store features common to all languages in a script */
745 for (j = 0; j < lookups_n; j++)
746 if (lookups[j].lookup == lookup && !lookups[j].lang[0])
747 if (!strcmp(lookups[j].scrp, stag))
748 break;
749 if (j == lookups_n) {
750 memcpy(lookups[j].feat, featrec, 4);
751 lookups[j].feat[4] = '\0';
752 strcpy(lookups[j].scrp, stag);
753 strcpy(lookups[j].lang, ltag);
754 lookups[j].lookup = U16(feat, 4 + 2 * i);
755 lookups_n++;
758 return lookups_n;
761 /* parse the given language table and its feature tables */
762 static int otf_lang(void *otf, void *gtab, void *lang, char *stag, char *ltag,
763 struct otflookup *lookups, int lookups_n)
765 void *feats = gtab + U16(gtab, 6);
766 int featidx = U16(lang, 2);
767 int nfeat = U16(lang, 4);
768 int i;
769 if (featidx != 0xffff)
770 lookups_n = otf_featrec(otf, gtab, feats + 2 + 6 * featidx,
771 stag, ltag, lookups, lookups_n);
772 for (i = 0; i < nfeat; i++)
773 lookups_n = otf_featrec(otf, gtab, feats + 2 + 6 * U16(lang, 6 + 2 * i),
774 stag, ltag, lookups, lookups_n);
775 return lookups_n;
778 /* return lookup table tag (i.e. liga:latn:ENG); returns a static buffer */
779 static char *lookuptag(struct otflookup *lu)
781 static char tag[16];
782 sprintf(tag, "%s:%s", lu->feat, lu->scrp[0] ? lu->scrp : "DFLT");
783 if (lu->lang[0])
784 sprintf(strchr(tag, '\0'), ":%s", lu->lang);
785 return tag;
788 static int lookupcmp(void *v1, void *v2)
790 struct otflookup *l1 = v1;
791 struct otflookup *l2 = v2;
792 if (strcmp(l1->scrp, l2->scrp))
793 return strcmp(l1->scrp, l2->scrp);
794 if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
795 return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
796 return l1->lookup - l2->lookup;
799 /* extract lookup tables for all features of the given gsub/gpos table */
800 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
802 void *scripts = gpos + U16(gpos, 4);
803 int nscripts, nlangs;
804 void *script;
805 char stag[8], ltag[8]; /* script and language tags */
806 int i, j;
807 int n = 0;
808 nscripts = U16(scripts, 0);
809 for (i = 0; i < nscripts; i++) {
810 void *grec = scripts + 2 + 6 * i;
811 memcpy(stag, grec, 4);
812 stag[4] = '\0';
813 if (!trfn_script(stag, nscripts))
814 continue;
815 script = scripts + U16(grec, 4);
816 nlangs = U16(script, 2);
817 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
818 n = otf_lang(otf, gpos, script + U16(script, 0),
819 stag, "", lookups, n);
820 for (j = 0; j < nlangs; j++) {
821 void *lrec = script + 4 + 6 * j;
822 memcpy(ltag, lrec, 4);
823 ltag[4] = '\0';
824 if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
825 n = otf_lang(otf, gpos, script + U16(lrec, 4),
826 stag, ltag, lookups, n);
829 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
830 return n;
833 static void otf_gpos(void *otf, void *gpos)
835 struct otflookup lookups[NLOOKUPS];
836 void *lookuplist = gpos + U16(gpos, 8);
837 int nlookups = otf_gtab(otf, gpos, lookups);
838 int i, j;
839 for (i = 0; i < nlookups; i++) {
840 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
841 int ltype = U16(lookup, 0);
842 int ntabs = U16(lookup, 4);
843 char *tag = lookuptag(&lookups[i]);
844 for (j = 0; j < ntabs; j++) {
845 void *tab = lookup + U16(lookup, 6 + 2 * j);
846 int type = ltype;
847 if (type == 9) { /* extension positioning */
848 type = U16(tab, 2);
849 tab = tab + U32(tab, 4);
851 switch (type) {
852 case 1:
853 otf_gpostype1(otf, tab, tag);
854 break;
855 case 2:
856 otf_gpostype2(otf, tab, tag);
857 break;
858 case 3:
859 otf_gpostype3(otf, tab, tag);
860 break;
861 case 4:
862 otf_gpostype4(otf, tab, tag);
863 break;
864 default:
865 otf_unsupported("GPOS", type, 0);
871 static void otf_gsub(void *otf, void *gsub)
873 struct otflookup lookups[NLOOKUPS];
874 void *lookuplist = gsub + U16(gsub, 8);
875 int nlookups = otf_gtab(otf, gsub, lookups);
876 int i, j;
877 for (i = 0; i < nlookups; i++) {
878 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
879 int ltype = U16(lookup, 0);
880 int ntabs = U16(lookup, 4);
881 char *tag = lookuptag(&lookups[i]);
882 for (j = 0; j < ntabs; j++) {
883 void *tab = lookup + U16(lookup, 6 + 2 * j);
884 int type = ltype;
885 if (type == 7) { /* extension substitution */
886 type = U16(tab, 2);
887 tab = tab + U32(tab, 4);
889 switch (type) {
890 case 1:
891 otf_gsubtype1(otf, tab, tag, NULL);
892 break;
893 case 3:
894 otf_gsubtype3(otf, tab, tag, NULL);
895 break;
896 case 4:
897 otf_gsubtype4(otf, tab, tag, NULL);
898 break;
899 case 6:
900 otf_gsubtype6(otf, tab, tag, gsub);
901 break;
902 default:
903 otf_unsupported("GSUB", type, 0);
909 /* read a cff offset, which has sz bytes */
910 static int cff_int(void *tab, int off, int sz)
912 int i;
913 int n = 0;
914 for (i = 0; i < sz; i++)
915 n = n * 256 + U8(tab, off + i);
916 return n;
919 /* cff dict operand/operator */
920 static int cff_op(void *tab, int off, int *val)
922 int b0 = U8(tab, off);
923 int i;
924 if (b0 >= 32 && b0 <= 246) {
925 *val = b0 - 139;
926 return 1;
928 if (b0 >= 247 && b0 <= 250) {
929 *val = (b0 - 247) * 256 + U8(tab, off + 1) + 108;
930 return 2;
932 if (b0 >= 251 && b0 <= 254) {
933 *val = -(b0 - 251) * 256 - U8(tab, off + 1) - 108;
934 return 2;
936 if (b0 == 28) {
937 *val = (U8(tab, off + 1) << 8) | U8(tab, off + 2);
938 return 3;
940 if (b0 == 29) {
941 *val = (U8(tab, off + 1) << 24) | (U8(tab, off + 2) << 16) |
942 (U8(tab, off + 3) << 8) | U8(tab, off + 4);
943 return 5;
945 if (b0 == 30) {
946 for (i = 1; i < 32; i++) {
947 int nib = U8(tab, off + i);
948 if ((nib & 0x0f) == 0x0f || (nib & 0xf0) == 0xf0)
949 break;
951 *val = 0;
952 return i + 1;
954 *val = b0;
955 return 1;
958 static int cffidx_cnt(void *idx)
960 return U16(idx, 0);
963 static void *cffidx_get(void *idx, int i)
965 int cnt = U16(idx, 0);
966 int sz = U8(idx, 2);
967 return idx + 3 + (cnt + 1) * sz - 1 + cff_int(idx, 3 + i * sz, sz);
970 static int cffidx_len(void *idx, int i)
972 return cffidx_get(idx, i + 1) - cffidx_get(idx, i);
975 static void *cffidx_end(void *idx)
977 return cffidx_get(idx, cffidx_cnt(idx));
980 /* obtain the value of the given key from a cff dict */
981 static int cffdict_get(void *dict, int len, int key, int *args)
983 int off = 0;
984 int op = 0;
985 int val = 0;
986 /* operators: keys (one or two bytes); operands: values */
987 while (off < len) {
988 val = op;
989 if (args) {
990 memmove(args + 1, args + 0, 3 * sizeof(args[0]));
991 args[0] = val;
993 off += cff_op(dict, off, &op);
994 if (op == 12) { /* two-byte operator */
995 off += cff_op(dict, off, &op);
996 op += 1200;
998 if (op == key)
999 return val;
1001 return 0;
1004 static void cff_char(void *stridx, int id, char *dst)
1006 int len;
1007 if (id < 391) {
1008 strcpy(dst, stdset[id]);
1009 return;
1011 id -= 391;
1012 len = cffidx_len(stridx, id);
1013 memcpy(dst, cffidx_get(stridx, id), len);
1014 dst[len] = '\0';
1017 static void otf_cff(void *otf, void *cff)
1019 void *nameidx; /* name index */
1020 void *topidx; /* top dict index */
1021 void *stridx; /* string idx */
1022 void *chridx; /* charstrings index */
1023 void *charset; /* charset offset of top dict table */
1024 int bbox[4] = {0};
1025 int i, j;
1026 if (U8(cff, 0) != 1)
1027 return;
1028 nameidx = cff + U8(cff, 2);
1029 topidx = cffidx_end(nameidx);
1030 if (cffidx_cnt(nameidx) < 1)
1031 return;
1032 stridx = cffidx_end(topidx);
1033 chridx = cff + cffdict_get(cffidx_get(topidx, 0),
1034 cffidx_len(topidx, 0), 17, NULL);
1035 charset = cff + cffdict_get(cffidx_get(topidx, 0),
1036 cffidx_len(topidx, 0), 15, NULL);
1037 glyph_n = cffidx_cnt(chridx);
1038 strcpy(glyph_name[0], ".notdef");
1039 if (U8(charset, 0) == 0) {
1040 for (i = 0; i < glyph_n; i++)
1041 cff_char(stridx, U16(charset, 1 + i * 2),
1042 glyph_name[i + 1]);
1044 if (U8(charset, 0) == 1 || U8(charset, 0) == 2) {
1045 int g = 1;
1046 int sz = U8(charset, 0) == 1 ? 3 : 4;
1047 for (i = 0; g < glyph_n; i++) {
1048 int sid = U16(charset, 1 + i * sz);
1049 int cnt = cff_int(charset, 1 + i * sz + 2, sz - 2);
1050 for (j = 0; j <= cnt && g < glyph_n; j++) {
1051 cff_char(stridx, sid + j, glyph_name[g]);
1052 g++;
1056 /* use font bbox for all glyphs */
1057 cffdict_get(cffidx_get(topidx, 0), cffidx_len(topidx, 0), 5, bbox);
1058 for (i = 1; i < glyph_n; i++)
1059 for (j = 0; j < 4; j++)
1060 glyph_bbox[i][j] = bbox[3 - j];
1063 static void *otf_input(int fd)
1065 struct sbuf *sb = sbuf_make();
1066 char buf[1 << 12];
1067 int nr = 0;
1068 while ((nr = read(fd, buf, sizeof(buf))) > 0)
1069 sbuf_mem(sb, buf, nr);
1070 return sbuf_done(sb);
1073 static char *otf_buf;
1075 int otf_read(void)
1077 int i;
1078 otf_buf = otf_input(0);
1079 upm = U16(otf_table(otf_buf, "head"), 18);
1080 otf_name(otf_buf, otf_table(otf_buf, "name"));
1081 otf_cmap(otf_buf, otf_table(otf_buf, "cmap"));
1082 otf_post(otf_buf, otf_table(otf_buf, "post"));
1083 if (otf_table(otf_buf, "glyf"))
1084 otf_glyf(otf_buf, otf_table(otf_buf, "glyf"));
1085 if (otf_table(otf_buf, "CFF "))
1086 otf_cff(otf_buf, otf_table(otf_buf, "CFF "));
1087 otf_hmtx(otf_buf, otf_table(otf_buf, "hmtx"));
1088 for (i = 0; i < glyph_n; i++) {
1089 trfn_char(glyph_name[i], -1,
1090 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
1091 owid(glyph_wid[i]),
1092 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
1093 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
1095 if (otf_table(otf_buf, "kern"))
1096 otf_kern(otf_buf, otf_table(otf_buf, "kern"));
1097 return 0;
1100 void otf_feat(int r, int k, int w)
1102 res = r;
1103 kmin = k;
1104 warn = w;
1105 if (otf_table(otf_buf, "GSUB"))
1106 otf_gsub(otf_buf, otf_table(otf_buf, "GSUB"));
1107 if (otf_table(otf_buf, "GPOS"))
1108 otf_gpos(otf_buf, otf_table(otf_buf, "GPOS"));
1111 /* glyph groups */
1112 static int *ggrp_g[NGRPS];
1113 static int ggrp_len[NGRPS];
1114 static int ggrp_n;
1116 static int ggrp_find(int *src, int n)
1118 int i, j;
1119 for (i = 0; i < ggrp_n; i++) {
1120 if (ggrp_len[i] == n) {
1121 for (j = 0; j < n; j++)
1122 if (src[j] != ggrp_g[i][j])
1123 break;
1124 if (j == n)
1125 return i;
1128 return -1;
1131 static int ggrp_make(int *src, int n)
1133 int id = ggrp_find(src, n);
1134 int i;
1135 if (id >= 0)
1136 return id;
1137 id = ggrp_n++;
1138 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
1139 ggrp_len[id] = n;
1140 for (i = 0; i < n; i++)
1141 ggrp_g[id][i] = src[i];
1142 printf("ggrp %d %d", id, n);
1143 for (i = 0; i < n; i++)
1144 printf(" %s", glyph_name[src[i]]);
1145 printf("\n");
1146 return id;
1149 static char *macset[] = {
1150 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
1151 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
1152 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
1153 "comma", "hyphen", "period", "slash", "zero",
1154 "one", "two", "three", "four", "five",
1155 "six", "seven", "eight", "nine", "colon",
1156 "semicolon", "less", "equal", "greater", "question",
1157 "at", "A", "B", "C", "D",
1158 "E", "F", "G", "H", "I",
1159 "J", "K", "L", "M", "N",
1160 "O", "P", "Q", "R", "S",
1161 "T", "U", "V", "W", "X",
1162 "Y", "Z", "bracketleft", "backslash", "bracketright",
1163 "asciicircum", "underscore", "grave", "a", "b",
1164 "c", "d", "e", "f", "g",
1165 "h", "i", "j", "k", "l",
1166 "m", "n", "o", "p", "q",
1167 "r", "s", "t", "u", "v",
1168 "w", "x", "y", "z", "braceleft",
1169 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
1170 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
1171 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
1172 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
1173 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
1174 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
1175 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
1176 "dagger", "degree", "cent", "sterling", "section",
1177 "bullet", "paragraph", "germandbls", "registered", "copyright",
1178 "trademark", "acute", "dieresis", "notequal", "AE",
1179 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1180 "yen", "mu", "partialdiff", "summation", "product",
1181 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1182 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1183 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1184 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1185 "Otilde", "OE", "oe", "endash", "emdash",
1186 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1187 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1188 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1189 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1190 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1191 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1192 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1193 "dotlessi", "circumflex", "tilde", "macron", "breve",
1194 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1195 "caron", "Lslash", "lslash", "Scaron", "scaron",
1196 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1197 "Yacute", "yacute", "Thorn", "thorn", "minus",
1198 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1199 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1200 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1201 "Ccaron", "ccaron", "dcroat",
1204 static char *stdset[] = {
1205 ".notdef", "space", "exclam", "quotedbl", "numbersign",
1206 "dollar", "percent", "ampersand", "quoteright", "parenleft",
1207 "parenright", "asterisk", "plus", "comma", "hyphen",
1208 "period", "slash", "zero", "one", "two",
1209 "three", "four", "five", "six", "seven",
1210 "eight", "nine", "colon", "semicolon", "less",
1211 "equal", "greater", "question", "at", "A",
1212 "B", "C", "D", "E", "F",
1213 "G", "H", "I", "J", "K",
1214 "L", "M", "N", "O", "P",
1215 "Q", "R", "S", "T", "U",
1216 "V", "W", "X", "Y", "Z",
1217 "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
1218 "quoteleft", "a", "b", "c", "d",
1219 "e", "f", "g", "h", "i",
1220 "j", "k", "l", "m", "n",
1221 "o", "p", "q", "r", "s",
1222 "t", "u", "v", "w", "x",
1223 "y", "z", "braceleft", "bar", "braceright",
1224 "asciitilde", "exclamdown", "cent", "sterling", "fraction",
1225 "yen", "florin", "section", "currency", "quotesingle",
1226 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
1227 "fl", "endash", "dagger", "daggerdbl", "periodcentered",
1228 "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
1229 "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
1230 "acute", "circumflex", "tilde", "macron", "breve",
1231 "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
1232 "ogonek", "caron", "emdash", "AE", "ordfeminine",
1233 "Lslash", "Oslash", "OE", "ordmasculine", "ae",
1234 "dotlessi", "lslash", "oslash", "oe", "germandbls",
1235 "onesuperior", "logicalnot", "mu", "trademark", "Eth",
1236 "onehalf", "plusminus", "Thorn", "onequarter", "divide",
1237 "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
1238 "registered", "minus", "eth", "multiply", "threesuperior",
1239 "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
1240 "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
1241 "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
1242 "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
1243 "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
1244 "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
1245 "aacute", "acircumflex", "adieresis", "agrave", "aring",
1246 "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
1247 "egrave", "iacute", "icircumflex", "idieresis", "igrave",
1248 "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
1249 "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
1250 "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
1251 "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
1252 "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
1253 "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
1254 "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
1255 "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
1256 "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
1257 "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
1258 "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
1259 "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
1260 "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
1261 "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
1262 "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
1263 "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
1264 "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
1265 "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
1266 "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
1267 "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
1268 "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
1269 "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
1270 "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
1271 "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
1272 "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
1273 "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
1274 "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
1275 "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
1276 "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
1277 "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
1278 "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
1279 "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
1280 "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000",
1281 "001.001", "001.002", "001.003", "Black", "Bold",
1282 "Book", "Light", "Medium", "Regular", "Roman",
1283 "Semibold",