otf: otf file support
[neatmkfn.git] / otf.c
blobf93242b6000c3aef742403b3156b4512061709e3
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 = 7200 / res;
53 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / 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 feat[8]; /* feature name */
729 int lookup; /* index into the lookup table */
732 /* parse the given gsub/gpos feature table */
733 static int otf_featrec(void *otf, void *gtab, void *featrec, char *script, struct otflookup *lookups)
735 void *feats = gtab + U16(gtab, 6);
736 void *feat = feats + U16(featrec, 4);
737 int nlookups = U16(feat, 2);
738 int i;
739 for (i = 0; i < nlookups; i++) {
740 memcpy(lookups[i].feat, featrec, 4);
741 lookups[i].feat[4] = '\0';
742 strcpy(lookups[i].scrp, script);
743 lookups[i].lookup = U16(feat, 4 + 2 * i);
745 return nlookups;
748 /* parse the given language table and its feature tables */
749 static int otf_lang(void *otf, void *gtab, void *lang, char *script, struct otflookup *lookups)
751 void *feats = gtab + U16(gtab, 6);
752 int featidx = U16(lang, 2);
753 int nfeat = U16(lang, 4);
754 int n = 0;
755 int i;
756 if (featidx != 0xffff)
757 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, script, lookups + n);
758 for (i = 0; i < nfeat; i++)
759 n += otf_featrec(otf, gtab,
760 feats + 2 + 6 * U16(lang, 6 + 2 * i), script, lookups + n);
761 return n;
764 static int lookupcmp(void *v1, void *v2)
766 struct otflookup *l1 = v1;
767 struct otflookup *l2 = v2;
768 if (strcmp(l1->scrp, l2->scrp))
769 return strcmp(l1->scrp, l2->scrp);
770 if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
771 return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
772 return l1->lookup - l2->lookup;
775 /* extract lookup tables for all features of the given gsub/gpos table */
776 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
778 void *scripts = gpos + U16(gpos, 4);
779 int nscripts, nlangs;
780 void *script;
781 char stag[8], ltag[8]; /* script and language tags */
782 int i, j;
783 int n = 0;
784 nscripts = U16(scripts, 0);
785 for (i = 0; i < nscripts; i++) {
786 void *grec = scripts + 2 + 6 * i;
787 memcpy(stag, grec, 4);
788 stag[4] = '\0';
789 if (!trfn_script(stag, nscripts))
790 continue;
791 script = scripts + U16(grec, 4);
792 nlangs = U16(script, 2);
793 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
794 n += otf_lang(otf, gpos, script + U16(script, 0),
795 stag, lookups + n);
796 for (j = 0; j < nlangs; j++) {
797 void *lrec = script + 4 + 6 * j;
798 memcpy(ltag, lrec, 4);
799 ltag[4] = '\0';
800 if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
801 n += otf_lang(otf, gpos, script + U16(lrec, 4),
802 stag, lookups + n);
805 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
806 return n;
809 static void otf_gpos(void *otf, void *gpos)
811 struct otflookup lookups[NLOOKUPS];
812 void *lookuplist = gpos + U16(gpos, 8);
813 int nlookups = otf_gtab(otf, gpos, lookups);
814 char tag[16];
815 int i, j;
816 for (i = 0; i < nlookups; i++) {
817 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
818 int ltype = U16(lookup, 0);
819 int ntabs = U16(lookup, 4);
820 sprintf(tag, "%s:%s", lookups[i].feat,
821 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
822 for (j = 0; j < ntabs; j++) {
823 void *tab = lookup + U16(lookup, 6 + 2 * j);
824 int type = ltype;
825 if (type == 9) { /* extension positioning */
826 type = U16(tab, 2);
827 tab = tab + U32(tab, 4);
829 switch (type) {
830 case 1:
831 otf_gpostype1(otf, tab, tag);
832 break;
833 case 2:
834 otf_gpostype2(otf, tab, tag);
835 break;
836 case 3:
837 otf_gpostype3(otf, tab, tag);
838 break;
839 case 4:
840 otf_gpostype4(otf, tab, tag);
841 break;
842 default:
843 otf_unsupported("GPOS", type, 0);
849 static void otf_gsub(void *otf, void *gsub)
851 struct otflookup lookups[NLOOKUPS];
852 void *lookuplist = gsub + U16(gsub, 8);
853 int nlookups = otf_gtab(otf, gsub, lookups);
854 char tag[16];
855 int i, j;
856 for (i = 0; i < nlookups; i++) {
857 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
858 int ltype = U16(lookup, 0);
859 int ntabs = U16(lookup, 4);
860 sprintf(tag, "%s:%s", lookups[i].feat,
861 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
862 for (j = 0; j < ntabs; j++) {
863 void *tab = lookup + U16(lookup, 6 + 2 * j);
864 int type = ltype;
865 if (type == 7) { /* extension substitution */
866 type = U16(tab, 2);
867 tab = tab + U32(tab, 4);
869 switch (type) {
870 case 1:
871 otf_gsubtype1(otf, tab, tag, NULL);
872 break;
873 case 3:
874 otf_gsubtype3(otf, tab, tag, NULL);
875 break;
876 case 4:
877 otf_gsubtype4(otf, tab, tag, NULL);
878 break;
879 case 6:
880 otf_gsubtype6(otf, tab, tag, gsub);
881 break;
882 default:
883 otf_unsupported("GSUB", type, 0);
889 /* read a cff offset, which has sz bytes */
890 static int cff_int(void *tab, int off, int sz)
892 int i;
893 int n = 0;
894 for (i = 0; i < sz; i++)
895 n = n * 256 + U8(tab, off + i);
896 return n;
899 /* cff dict operand/operator */
900 static int cff_op(void *tab, int off, int *val)
902 int b0 = U8(tab, off);
903 int i;
904 if (b0 >= 32 && b0 <= 246) {
905 *val = b0 - 139;
906 return 1;
908 if (b0 >= 247 && b0 <= 250) {
909 *val = (b0 - 247) * 256 + U8(tab, off + 1) + 108;
910 return 2;
912 if (b0 >= 251 && b0 <= 254) {
913 *val = -(b0 - 251) * 256 - U8(tab, off + 1) - 108;
914 return 2;
916 if (b0 == 28) {
917 *val = (U8(tab, off + 1) << 8) | U8(tab, off + 2);
918 return 3;
920 if (b0 == 29) {
921 *val = (U8(tab, off + 1) << 24) | (U8(tab, off + 2) << 16) |
922 (U8(tab, off + 3) << 8) | U8(tab, off + 4);
923 return 5;
925 if (b0 == 30) {
926 for (i = 1; i < 32; i++) {
927 int nib = U8(tab, off + i);
928 if ((nib & 0x0f) == 0x0f || (nib & 0xf0) == 0xf0)
929 break;
931 *val = 0;
932 return i + 1;
934 *val = b0;
935 return 1;
938 static int cffidx_cnt(void *idx)
940 return U16(idx, 0);
943 static void *cffidx_get(void *idx, int i)
945 int cnt = U16(idx, 0);
946 int sz = U8(idx, 2);
947 return idx + 3 + (cnt + 1) * sz - 1 + cff_int(idx, 3 + i * sz, sz);
950 static int cffidx_len(void *idx, int i)
952 return cffidx_get(idx, i + 1) - cffidx_get(idx, i);
955 static void *cffidx_end(void *idx)
957 return cffidx_get(idx, cffidx_cnt(idx));
960 static int cffdict_get(void *dict, int len, int key)
962 int off = 0;
963 int op = 0;
964 int val = 0;
965 /* operators: keys (one or two bytes); operands: values */
966 while (off < len) {
967 val = op;
968 off += cff_op(dict, off, &op);
969 if (op == 12) { /* two-byte operator */
970 off += cff_op(dict, off, &op);
971 op += 1200;
973 if (op == key)
974 return val;
976 return 0;
979 static void cff_char(void *stridx, int id, char *dst)
981 int len;
982 if (id < 391) {
983 strcpy(dst, stdset[id]);
984 return;
986 id -= 391;
987 len = cffidx_len(stridx, id);
988 memcpy(dst, cffidx_get(stridx, id), len);
989 dst[len] = '\0';
992 static void otf_cff(void *otf, void *cff)
994 void *nameidx; /* name index */
995 void *topidx; /* top dict index */
996 void *stridx; /* string idx */
997 void *chridx; /* charstrings index */
998 void *charset; /* charset offset of top dict table */
999 int i, j;
1000 if (U8(cff, 0) != 1)
1001 return;
1002 nameidx = cff + U8(cff, 2);
1003 topidx = cffidx_end(nameidx);
1004 if (cffidx_cnt(nameidx) < 1)
1005 return;
1006 stridx = cffidx_end(topidx);
1007 chridx = cff + cffdict_get(cffidx_get(topidx, 0), cffidx_len(topidx, 0), 17);
1008 charset = cff + cffdict_get(cffidx_get(topidx, 0), cffidx_len(topidx, 0), 15);
1009 glyph_n = cffidx_cnt(chridx);
1010 strcpy(glyph_name[0], ".notdef");
1011 if (U8(charset, 0) == 0) {
1012 for (i = 0; i < glyph_n; i++)
1013 cff_char(stridx, i, glyph_name[i]);
1015 if (U8(charset, 0) == 1) {
1016 int g = 1;
1017 for (i = 0; g < glyph_n; i++) {
1018 int sid = U16(charset, 1 + i * 3);
1019 int cnt = U8(charset, 1 + i * 3 + 2);
1020 for (j = 0; j <= cnt && g < glyph_n; j++) {
1021 cff_char(stridx, sid + j, glyph_name[g]);
1022 g++;
1026 if (U8(charset, 0) == 2) {
1027 int g = 1;
1028 for (i = 0; g < glyph_n; i++) {
1029 int sid = U16(charset, 1 + i * 4);
1030 int cnt = U16(charset, 1 + i * 4 + 2);
1031 for (j = 0; j <= cnt && g < glyph_n; j++) {
1032 cff_char(stridx, sid + j, glyph_name[g]);
1033 g++;
1039 static void *otf_input(int fd)
1041 struct sbuf *sb = sbuf_make();
1042 char buf[1 << 12];
1043 int nr = 0;
1044 while ((nr = read(fd, buf, sizeof(buf))) > 0)
1045 sbuf_mem(sb, buf, nr);
1046 return sbuf_done(sb);
1049 static char *otf_buf;
1051 int otf_read(void)
1053 int i;
1054 otf_buf = otf_input(0);
1055 upm = U16(otf_table(otf_buf, "head"), 18);
1056 otf_name(otf_buf, otf_table(otf_buf, "name"));
1057 otf_cmap(otf_buf, otf_table(otf_buf, "cmap"));
1058 otf_post(otf_buf, otf_table(otf_buf, "post"));
1059 if (otf_table(otf_buf, "glyf"))
1060 otf_glyf(otf_buf, otf_table(otf_buf, "glyf"));
1061 if (otf_table(otf_buf, "CFF "))
1062 otf_cff(otf_buf, otf_table(otf_buf, "CFF "));
1063 otf_hmtx(otf_buf, otf_table(otf_buf, "hmtx"));
1064 for (i = 0; i < glyph_n; i++) {
1065 trfn_char(glyph_name[i], -1,
1066 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
1067 owid(glyph_wid[i]),
1068 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
1069 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
1071 if (otf_table(otf_buf, "kern"))
1072 otf_kern(otf_buf, otf_table(otf_buf, "kern"));
1073 return 0;
1076 void otf_feat(int r, int k, int w)
1078 res = r;
1079 kmin = k;
1080 warn = w;
1081 if (otf_table(otf_buf, "GSUB"))
1082 otf_gsub(otf_buf, otf_table(otf_buf, "GSUB"));
1083 if (otf_table(otf_buf, "GPOS"))
1084 otf_gpos(otf_buf, otf_table(otf_buf, "GPOS"));
1087 /* glyph groups */
1088 static int *ggrp_g[NGRPS];
1089 static int ggrp_len[NGRPS];
1090 static int ggrp_n;
1092 static int ggrp_find(int *src, int n)
1094 int i, j;
1095 for (i = 0; i < ggrp_n; i++) {
1096 if (ggrp_len[i] == n) {
1097 for (j = 0; j < n; j++)
1098 if (src[j] != ggrp_g[i][j])
1099 break;
1100 if (j == n)
1101 return i;
1104 return -1;
1107 static int ggrp_make(int *src, int n)
1109 int id = ggrp_find(src, n);
1110 int i;
1111 if (id >= 0)
1112 return id;
1113 id = ggrp_n++;
1114 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
1115 ggrp_len[id] = n;
1116 for (i = 0; i < n; i++)
1117 ggrp_g[id][i] = src[i];
1118 printf("ggrp %d %d", id, n);
1119 for (i = 0; i < n; i++)
1120 printf(" %s", glyph_name[src[i]]);
1121 printf("\n");
1122 return id;
1125 static char *macset[] = {
1126 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
1127 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
1128 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
1129 "comma", "hyphen", "period", "slash", "zero",
1130 "one", "two", "three", "four", "five",
1131 "six", "seven", "eight", "nine", "colon",
1132 "semicolon", "less", "equal", "greater", "question",
1133 "at", "A", "B", "C", "D",
1134 "E", "F", "G", "H", "I",
1135 "J", "K", "L", "M", "N",
1136 "O", "P", "Q", "R", "S",
1137 "T", "U", "V", "W", "X",
1138 "Y", "Z", "bracketleft", "backslash", "bracketright",
1139 "asciicircum", "underscore", "grave", "a", "b",
1140 "c", "d", "e", "f", "g",
1141 "h", "i", "j", "k", "l",
1142 "m", "n", "o", "p", "q",
1143 "r", "s", "t", "u", "v",
1144 "w", "x", "y", "z", "braceleft",
1145 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
1146 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
1147 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
1148 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
1149 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
1150 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
1151 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
1152 "dagger", "degree", "cent", "sterling", "section",
1153 "bullet", "paragraph", "germandbls", "registered", "copyright",
1154 "trademark", "acute", "dieresis", "notequal", "AE",
1155 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1156 "yen", "mu", "partialdiff", "summation", "product",
1157 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1158 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1159 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1160 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1161 "Otilde", "OE", "oe", "endash", "emdash",
1162 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1163 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1164 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1165 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1166 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1167 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1168 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1169 "dotlessi", "circumflex", "tilde", "macron", "breve",
1170 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1171 "caron", "Lslash", "lslash", "Scaron", "scaron",
1172 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1173 "Yacute", "yacute", "Thorn", "thorn", "minus",
1174 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1175 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1176 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1177 "Ccaron", "ccaron", "dcroat",
1180 static char *stdset[] = {
1181 ".notdef", "space", "exclam", "quotedbl", "numbersign",
1182 "dollar", "percent", "ampersand", "quoteright", "parenleft",
1183 "parenright", "asterisk", "plus", "comma", "hyphen",
1184 "period", "slash", "zero", "one", "two",
1185 "three", "four", "five", "six", "seven",
1186 "eight", "nine", "colon", "semicolon", "less",
1187 "equal", "greater", "question", "at", "A",
1188 "B", "C", "D", "E", "F",
1189 "G", "H", "I", "J", "K",
1190 "L", "M", "N", "O", "P",
1191 "Q", "R", "S", "T", "U",
1192 "V", "W", "X", "Y", "Z",
1193 "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
1194 "quoteleft", "a", "b", "c", "d",
1195 "e", "f", "g", "h", "i",
1196 "j", "k", "l", "m", "n",
1197 "o", "p", "q", "r", "s",
1198 "t", "u", "v", "w", "x",
1199 "y", "z", "braceleft", "bar", "braceright",
1200 "asciitilde", "exclamdown", "cent", "sterling", "fraction",
1201 "yen", "florin", "section", "currency", "quotesingle",
1202 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
1203 "fl", "endash", "dagger", "daggerdbl", "periodcentered",
1204 "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
1205 "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
1206 "acute", "circumflex", "tilde", "macron", "breve",
1207 "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
1208 "ogonek", "caron", "emdash", "AE", "ordfeminine",
1209 "Lslash", "Oslash", "OE", "ordmasculine", "ae",
1210 "dotlessi", "lslash", "oslash", "oe", "germandbls",
1211 "onesuperior", "logicalnot", "mu", "trademark", "Eth",
1212 "onehalf", "plusminus", "Thorn", "onequarter", "divide",
1213 "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
1214 "registered", "minus", "eth", "multiply", "threesuperior",
1215 "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
1216 "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
1217 "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
1218 "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
1219 "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
1220 "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
1221 "aacute", "acircumflex", "adieresis", "agrave", "aring",
1222 "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
1223 "egrave", "iacute", "icircumflex", "idieresis", "igrave",
1224 "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
1225 "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
1226 "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
1227 "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
1228 "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
1229 "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
1230 "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
1231 "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
1232 "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
1233 "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
1234 "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
1235 "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
1236 "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
1237 "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
1238 "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
1239 "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
1240 "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
1241 "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
1242 "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
1243 "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
1244 "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
1245 "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
1246 "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
1247 "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
1248 "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
1249 "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
1250 "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
1251 "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
1252 "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
1253 "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
1254 "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
1255 "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
1256 "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000",
1257 "001.001", "001.002", "001.003", "Black", "Bold",
1258 "Book", "Light", "Medium", "Regular", "Roman",
1259 "Semibold",