trfn: be more strict about uXYZW and uniXYZW glyph names
[neatmkfn.git] / otf.c
blob3584a30309197798d9a92e4efe9535509d0cde67
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 "trfn.h"
9 #define NGLYPHS (1 << 14)
10 #define NLOOKUPS (1 << 12)
11 #define GNLEN (64)
12 #define BUFLEN (1 << 23)
13 #define NGRPS 2048
14 #define MAX(a, b) ((a) < (b) ? (b) : (a))
16 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
17 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
18 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
19 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
20 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
22 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
24 typedef unsigned int u32;
25 typedef unsigned short u16;
26 typedef unsigned char u8;
27 typedef int s32;
28 typedef short s16;
30 static char glyph_name[NGLYPHS][GNLEN];
31 static int glyph_code[NGLYPHS];
32 static int glyph_bbox[NGLYPHS][4];
33 static int glyph_wid[NGLYPHS];
34 static int glyph_n;
35 static int upm; /* units per em */
36 static int res; /* device resolution */
37 static int kmin; /* minimum kerning value */
38 static int warn;
40 static char *macset[];
42 static int owid(int w)
44 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
47 static int uwid(int w)
49 int d = 7200 / res;
50 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
53 /* report unsupported otf tables */
54 static void otf_unsupported(char *sub, int type, int fmt)
56 if (warn) {
57 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
58 if (fmt > 0)
59 fprintf(stderr, " format %d", fmt);
60 fprintf(stderr, "\n");
64 /* find the otf table with the given name */
65 static void *otf_table(void *otf, char *name)
67 int nrecs = U16(otf, 4);
68 int i;
69 for (i = 0; i < nrecs; i++) {
70 void *rec = otf + 12 + i * 16; /* an otf table record */
71 if (!strncmp(rec, name, 4))
72 return otf + U32(rec, 8);
74 return NULL;
77 /* obtain postscript font name from name table */
78 static void otf_name(void *otf, void *tab)
80 char name[256];
81 void *str = tab + U16(tab, 4); /* storage area */
82 int n = U16(tab, 2); /* number of name records */
83 int i;
84 for (i = 0; i < n; i++) {
85 void *rec = tab + 6 + 12 * i;
86 int pid = U16(rec, 0); /* platform id */
87 int eid = U16(rec, 2); /* encoding id */
88 int lid = U16(rec, 4); /* language id */
89 int nid = U16(rec, 6); /* name id */
90 int len = U16(rec, 8); /* string length */
91 int off = U16(rec, 10); /* string offset */
92 if (pid == 1 && eid == 0 && lid == 0 && nid == 6) {
93 memcpy(name, str + off, len);
94 name[len] = '\0';
95 trfn_psfont(name);
100 /* parse otf cmap format 4 subtable */
101 static void otf_cmap4(void *otf, void *cmap4)
103 int nsegs;
104 void *ends, *begs, *deltas, *offsets;
105 int beg, end, delta, offset;
106 int i, j;
107 nsegs = U16(cmap4, 6) / 2;
108 ends = cmap4 + 14;
109 begs = ends + 2 * nsegs + 2;
110 deltas = begs + 2 * nsegs;
111 offsets = deltas + 2 * nsegs;
112 for (i = 0; i < nsegs; i++) {
113 beg = U16(begs, 2 * i);
114 end = U16(ends, 2 * i);
115 delta = U16(deltas, 2 * i);
116 offset = U16(offsets, 2 * i);
117 if (offset) {
118 for (j = beg; j <= end; j++)
119 glyph_code[(U16(offsets + 2 * i,
120 offset + (j - beg) * 2) + delta) & 0xffff] = j;
121 } else {
122 for (j = beg; j <= end; j++)
123 glyph_code[(j + delta) & 0xffff] = j;
128 /* parse otf cmap header */
129 static void otf_cmap(void *otf, void *cmap)
131 int nrecs = U16(cmap, 2);
132 int i;
133 for (i = 0; i < nrecs; i++) {
134 void *rec = cmap + 4 + i * 8; /* a cmap record */
135 int plat = U16(rec, 0);
136 int enc = U16(rec, 2);
137 void *tab = cmap + U32(rec, 4); /* a cmap subtable */
138 int fmt = U16(tab, 0);
139 if (plat == 3 && enc == 1 && fmt == 4)
140 otf_cmap4(otf, tab);
144 static void otf_post(void *otf, void *post)
146 void *post2; /* version 2.0 header */
147 void *index; /* glyph name indices */
148 void *names; /* glyph names */
149 int cname = 0;
150 int i;
151 if (U32(post, 0) != 0x00020000)
152 return;
153 post2 = post + 32;
154 glyph_n = U16(post2, 0);
155 index = post2 + 2;
156 names = index + 2 * glyph_n;
157 for (i = 0; i < glyph_n; i++) {
158 int idx = U16(index, 2 * i);
159 if (idx <= 257) {
160 strcpy(glyph_name[i], macset[idx]);
161 } else {
162 memcpy(glyph_name[i], names + cname + 1,
163 U8(names, cname));
164 glyph_name[i][U8(names, cname)] = '\0';
165 cname += U8(names, cname) + 1;
170 static void otf_glyf(void *otf, void *glyf)
172 void *maxp = otf_table(otf, "maxp");
173 void *head = otf_table(otf, "head");
174 void *loca = otf_table(otf, "loca");
175 void *gdat;
176 void *gdat_next;
177 int n = U16(maxp, 4);
178 int fmt = U16(head, 50);
179 int i, j;
180 for (i = 0; i < n; i++) {
181 if (fmt) {
182 gdat = glyf + U32(loca, 4 * i);
183 gdat_next = glyf + U32(loca, 4 * (i + 1));
184 } else {
185 gdat = glyf + U16(loca, 2 * i) * 2;
186 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
188 if (gdat < gdat_next)
189 for (j = 0; j < 4; j++)
190 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
194 static void otf_hmtx(void *otf, void *hmtx)
196 void *hhea = otf_table(otf, "hhea");
197 int n;
198 int i;
199 n = U16(hhea, 34);
200 for (i = 0; i < n; i++)
201 glyph_wid[i] = U16(hmtx, i * 4);
202 for (i = n; i < glyph_n; i++)
203 glyph_wid[i] = glyph_wid[n - 1];
206 static void otf_kern(void *otf, void *kern)
208 int off = 4;
209 int i, j;
210 int n = U16(kern, 2); /* number of kern subtables */
211 for (i = 0; i < n; i++) {
212 void *tab = kern + off; /* a kern subtable */
213 int cov = U16(tab, 4);
214 off += U16(tab, 2);
215 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
216 int npairs = U16(tab, 6);
217 for (j = 0; j < npairs; j++) {
218 int c1 = U16(tab, 14 + 6 * j);
219 int c2 = U16(tab, 14 + 6 * j + 2);
220 int val = S16(tab, 14 + 6 * j + 4);
221 trfn_kern(glyph_name[c1], glyph_name[c2],
222 owid(val));
228 static int coverage(void *cov, int *out)
230 int fmt = U16(cov, 0);
231 int n = U16(cov, 2);
232 int beg, end;
233 int ncov = 0;
234 int i, j;
235 if (fmt == 1) {
236 for (i = 0; i < n; i++)
237 out[ncov++] = U16(cov, 4 + 2 * i);
239 if (fmt == 2) {
240 for (i = 0; i < n; i++) {
241 beg = U16(cov, 4 + 6 * i);
242 end = U16(cov, 4 + 6 * i + 2);
243 for (j = beg; j <= end; j++)
244 out[ncov++] = j;
247 return ncov;
250 static int classdef(void *tab, int *gl, int *cls)
252 int fmt = U16(tab, 0);
253 int ngl = 0;
254 int i, j;
255 if (fmt == 1) {
256 int beg = U16(tab, 2);
257 ngl = U16(tab, 4);
258 for (i = 0; i < ngl; i++) {
259 gl[i] = beg + i;
260 cls[i] = U16(tab, 6 + 2 * i);
263 if (fmt == 2) {
264 int n = U16(tab, 2);
265 for (i = 0; i < n; i++) {
266 int beg = U16(tab, 4 + 6 * i);
267 int end = U16(tab, 4 + 6 * i + 2);
268 for (j = beg; j <= end; j++) {
269 gl[ngl] = j;
270 cls[ngl] = U16(tab, 4 + 6 * i + 4);
271 ngl++;
275 return ngl;
278 static int intcmp(void *v1, void *v2)
280 return *(int *) v1 - *(int *) v2;
283 int ggrp_make(int *src, int n);
285 static int ggrp_class(int *src, int *cls, int nsrc, int id)
287 int g[NGLYPHS];
288 int n = 0;
289 int i;
290 for (i = 0; i < nsrc; i++)
291 if (cls[i] == id)
292 g[n++] = src[i];
293 qsort(g, n, sizeof(g[0]), (void *) intcmp);
294 return ggrp_make(g, n);
297 static int ggrp_coverage(int *g, int n)
299 qsort(g, n, sizeof(g[0]), (void *) intcmp);
300 return ggrp_make(g, n);
303 static int valuerecord_len(int fmt)
305 int off = 0;
306 int i;
307 for (i = 0; i < 8; i++)
308 if (fmt & (1 << i))
309 off += 2;
310 return off;
313 static void valuerecord_print(int fmt, void *rec)
315 int vals[8] = {0};
316 int off = 0;
317 int i;
318 for (i = 0; i < 8; i++) {
319 if (fmt & (1 << i)) {
320 vals[i] = uwid(S16(rec, off));
321 off += 2;
324 if (fmt)
325 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
328 static int valuerecord_small(int fmt, void *rec)
330 int off = 0;
331 int i;
332 for (i = 0; i < 8; i++) {
333 if (fmt & (1 << i)) {
334 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
335 return 0;
336 off += 2;
339 return 1;
342 /* single adjustment positioning */
343 static void otf_gpostype1(void *otf, void *sub, char *feat)
345 int fmt = U16(sub, 0);
346 int vfmt = U16(sub, 4);
347 int cov[NGLYPHS];
348 int ncov, nvals;
349 int vlen = valuerecord_len(vfmt);
350 int i;
351 ncov = coverage(sub + U16(sub, 2), cov);
352 if (fmt == 1) {
353 for (i = 0; i < ncov; i++) {
354 if (valuerecord_small(vfmt, sub + 6))
355 continue;
356 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
357 valuerecord_print(vfmt, sub + 6);
358 printf("\n");
361 if (fmt == 2) {
362 nvals = U16(sub, 6);
363 for (i = 0; i < nvals; 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 + 8 + i * vlen);
368 printf("\n");
373 /* pair adjustment positioning */
374 static void otf_gpostype2(void *otf, void *sub, char *feat)
376 int fmt = U16(sub, 0);
377 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
378 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
379 int fmtoff1, fmtoff2;
380 int vrlen; /* the length of vfmt1 and vfmt2 */
381 int i, j;
382 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
383 if (fmt == 1) {
384 int cov[NGLYPHS];
385 int nc1 = U16(sub, 8);
386 coverage(sub + U16(sub, 2), cov);
387 for (i = 0; i < nc1; i++) {
388 void *c2 = sub + U16(sub, 10 + 2 * i);
389 int nc2 = U16(c2, 0);
390 for (j = 0; j < nc2; j++) {
391 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
392 fmtoff1 = 2 + (2 + vrlen) * j + 2;
393 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
394 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
395 valuerecord_small(vfmt2, c2 + fmtoff2))
396 continue;
397 printf("gpos %s 2", feat);
398 printf(" %s", glyph_name[cov[i]]);
399 valuerecord_print(vfmt1, c2 + fmtoff1);
400 printf(" %s", glyph_name[second]);
401 valuerecord_print(vfmt2, c2 + fmtoff2);
402 printf("\n");
406 if (fmt == 2) {
407 int gl1[NGLYPHS], gl2[NGLYPHS];
408 int cls1[NGLYPHS], cls2[NGLYPHS];
409 int grp1[NGLYPHS], grp2[NGLYPHS];
410 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
411 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
412 int ncls1 = U16(sub, 12);
413 int ncls2 = U16(sub, 14);
414 for (i = 0; i < ncls1; i++)
415 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
416 for (i = 0; i < ncls2; i++)
417 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
418 for (i = 0; i < ncls1; i++) {
419 for (j = 0; j < ncls2; j++) {
420 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
421 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
422 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
423 valuerecord_small(vfmt2, sub + fmtoff2))
424 continue;
425 printf("gpos %s %d", feat, 2);
426 printf(" @%d", grp1[i]);
427 valuerecord_print(vfmt1, sub + fmtoff1);
428 printf(" @%d", grp2[j]);
429 valuerecord_print(vfmt2, sub + fmtoff2);
430 printf("\n");
436 /* cursive attachment positioning */
437 static void otf_gpostype3(void *otf, void *sub, char *feat)
439 int fmt = U16(sub, 0);
440 int cov[NGLYPHS];
441 int i, n;
442 coverage(sub + U16(sub, 2), cov);
443 if (fmt != 1)
444 return;
445 n = U16(sub, 4);
446 for (i = 0; i < n; i++) {
447 int prev = U16(sub, 6 + 4 * i);
448 int next = U16(sub, 6 + 4 * i + 2);
449 printf("gcur %s %s", feat, glyph_name[cov[i]]);
450 if (prev)
451 printf(" %d %d", uwid(S16(sub, prev + 2)),
452 uwid(S16(sub, prev + 4)));
453 else
454 printf(" - -");
455 if (next)
456 printf(" %d %d", uwid(S16(sub, next + 2)),
457 uwid(S16(sub, next + 4)));
458 else
459 printf(" - -");
460 printf("\n");
464 /* gsub context */
465 struct gctx {
466 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
467 int igrp[GCTXLEN]; /* input coverage arrays */
468 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
469 int bn, in, ln; /* size of b[], i[], l[] */
470 int seqidx; /* sequence index */
473 static int gctx_len(struct gctx *ctx, int patlen)
475 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
478 static void gctx_backtrack(struct gctx *ctx)
480 int i;
481 if (!ctx)
482 return;
483 for (i = 0; i < ctx->bn; i++)
484 printf(" =@%d", ctx->bgrp[i]);
485 for (i = 0; i < ctx->seqidx; i++)
486 printf(" =@%d", ctx->igrp[i]);
489 static void gctx_lookahead(struct gctx *ctx, int patlen)
491 int i;
492 if (!ctx)
493 return;
494 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
495 printf(" =@%d", ctx->igrp[i]);
496 for (i = 0; i < ctx->ln; i++)
497 printf(" =@%d", ctx->lgrp[i]);
500 /* single substitution */
501 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
503 int cov[NGLYPHS];
504 int fmt = U16(sub, 0);
505 int ncov;
506 int i;
507 ncov = coverage(sub + U16(sub, 2), cov);
508 if (fmt == 1) {
509 for (i = 0; i < ncov; i++) {
510 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
511 gctx_backtrack(ctx);
512 printf(" -%s +%s", glyph_name[cov[i]],
513 glyph_name[cov[i] + S16(sub, 4)]);
514 gctx_lookahead(ctx, 1);
515 printf("\n");
518 if (fmt == 2) {
519 int n = U16(sub, 4);
520 for (i = 0; i < n; i++) {
521 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
522 gctx_backtrack(ctx);
523 printf(" -%s +%s", glyph_name[cov[i]],
524 glyph_name[U16(sub, 6 + 2 * i)]);
525 gctx_lookahead(ctx, 1);
526 printf("\n");
531 /* alternate substitution */
532 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
534 int cov[NGLYPHS];
535 int fmt = U16(sub, 0);
536 int n, i, j;
537 if (fmt != 1)
538 return;
539 coverage(sub + U16(sub, 2), cov);
540 n = U16(sub, 4);
541 for (i = 0; i < n; i++) {
542 void *alt = sub + U16(sub, 6 + 2 * i);
543 int nalt = U16(alt, 0);
544 for (j = 0; j < nalt; j++) {
545 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
546 gctx_backtrack(ctx);
547 printf(" -%s +%s", glyph_name[cov[i]],
548 glyph_name[U16(alt, 2 + 2 * j)]);
549 gctx_lookahead(ctx, 1);
550 printf("\n");
555 /* ligature substitution */
556 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
558 int fmt = U16(sub, 0);
559 int cov[NGLYPHS];
560 int n, i, j, k;
561 if (fmt != 1)
562 return;
563 coverage(sub + U16(sub, 2), cov);
564 n = U16(sub, 4);
565 for (i = 0; i < n; i++) {
566 void *set = sub + U16(sub, 6 + 2 * i);
567 int nset = U16(set, 0);
568 for (j = 0; j < nset; j++) {
569 void *lig = set + U16(set, 2 + 2 * j);
570 int nlig = U16(lig, 2);
571 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
572 gctx_backtrack(ctx);
573 printf(" -%s", glyph_name[cov[i]]);
574 for (k = 0; k < nlig - 1; k++)
575 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
576 printf(" +%s", glyph_name[U16(lig, 0)]);
577 gctx_lookahead(ctx, nlig);
578 printf("\n");
583 /* chaining contextual substitution */
584 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
586 struct gctx ctx = {{0}};
587 void *lookups = gsub + U16(gsub, 8);
588 int fmt = U16(sub, 0);
589 int cov[NGLYPHS];
590 int i, j, nsub, ncov;
591 int off = 2;
592 if (fmt != 3) {
593 otf_unsupported("GSUB", 6, fmt);
594 return;
596 ctx.bn = U16(sub, off);
597 for (i = 0; i < ctx.bn; i++) {
598 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
599 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
601 off += 2 + 2 * ctx.bn;
602 ctx.in = U16(sub, off);
603 for (i = 0; i < ctx.in; i++) {
604 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
605 ctx.igrp[i] = ggrp_coverage(cov, ncov);
607 off += 2 + 2 * ctx.in;
608 ctx.ln = U16(sub, off);
609 for (i = 0; i < ctx.ln; i ++) {
610 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
611 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
613 off += 2 + 2 * ctx.ln;
614 nsub = U16(sub, off); /* nsub > 1 is not supported */
615 for (i = 0; i < nsub && i < 1; i++) {
616 int lidx = U16(sub, off + 2 + 4 * i + 2);
617 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
618 int ltype = U16(lookup, 0);
619 int ntabs = U16(lookup, 4);
620 ctx.seqidx = U16(sub, off + 2 + 4 * i);
621 for (j = 0; j < ntabs; j++) {
622 void *tab = lookup + U16(lookup, 6 + 2 * j);
623 int type = ltype;
624 if (type == 7) { /* extension substitution */
625 type = U16(tab, 2);
626 tab = tab + U32(tab, 4);
628 if (type == 1)
629 otf_gsubtype1(otf, tab, feat, &ctx);
630 if (type == 3)
631 otf_gsubtype3(otf, tab, feat, &ctx);
632 if (type == 4)
633 otf_gsubtype4(otf, tab, feat, &ctx);
638 /* an otf gsub/gpos lookup */
639 struct otflookup {
640 char feat[8]; /* feature name */
641 int lookup; /* index into the lookup table */
644 /* parse the given gsub/gpos feature table */
645 static int otf_featrec(void *otf, void *gtab, void *featrec, struct otflookup *lookups)
647 void *feats = gtab + U16(gtab, 6);
648 void *feat = feats + U16(featrec, 4);
649 int nlookups = U16(feat, 2);
650 int i;
651 for (i = 0; i < nlookups; i++) {
652 memcpy(lookups[i].feat, featrec, 4);
653 lookups[i].feat[4] = '\0';
654 lookups[i].lookup = U16(feat, 4 + 2 * i);
656 return nlookups;
659 /* parse the given language table and its feature tables */
660 static int otf_lang(void *otf, void *gtab, void *lang, struct otflookup *lookups)
662 void *feats = gtab + U16(gtab, 6);
663 int featidx = U16(lang, 2);
664 int nfeat = U16(lang, 4);
665 int n = 0;
666 int i;
667 if (featidx != 0xffff)
668 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, lookups + n);
669 for (i = 0; i < nfeat; i++)
670 n += otf_featrec(otf, gtab,
671 feats + 2 + 6 * U16(lang, 6 + 2 * i), lookups + n);
672 return n;
675 static int lookupcmp(void *v1, void *v2)
677 struct otflookup *l1 = v1;
678 struct otflookup *l2 = v2;
679 if (trfn_featrank(l1->feat) != trfn_featrank(l2->feat))
680 return trfn_featrank(l1->feat) - trfn_featrank(l2->feat);
681 return l1->lookup - l2->lookup;
684 /* extract lookup tables for all features of the given gsub/gpos table */
685 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
687 void *scripts = gpos + U16(gpos, 4);
688 int nscripts, nlangs;
689 void *script;
690 char tag[8];
691 int i, j;
692 int n = 0;
693 nscripts = U16(scripts, 0);
694 for (i = 0; i < nscripts; i++) {
695 void *grec = scripts + 2 + 6 * i;
696 memcpy(tag, grec, 4);
697 tag[4] = '\0';
698 if (!trfn_script(tag, nscripts))
699 continue;
700 script = scripts + U16(grec, 4);
701 nlangs = U16(script, 2);
702 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
703 n += otf_lang(otf, gpos, script + U16(script, 0), lookups + n);
704 for (j = 0; j < nlangs; j++) {
705 void *lrec = script + 4 + 6 * j;
706 memcpy(tag, lrec, 4);
707 tag[4] = '\0';
708 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
709 n += otf_lang(otf, gpos, script + U16(lrec, 4), lookups + n);
712 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
713 return n;
716 static void otf_gpos(void *otf, void *gpos)
718 struct otflookup lookups[NLOOKUPS];
719 void *lookuplist = gpos + U16(gpos, 8);
720 int nlookups = otf_gtab(otf, gpos, lookups);
721 int i, j;
722 for (i = 0; i < nlookups; i++) {
723 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
724 char *tag = lookups[i].feat;
725 int ltype = U16(lookup, 0);
726 int ntabs = U16(lookup, 4);
727 for (j = 0; j < ntabs; j++) {
728 void *tab = lookup + U16(lookup, 6 + 2 * j);
729 int type = ltype;
730 if (type == 9) { /* extension positioning */
731 type = U16(tab, 2);
732 tab = tab + U32(tab, 4);
734 switch (type) {
735 case 1:
736 otf_gpostype1(otf, tab, tag);
737 break;
738 case 2:
739 otf_gpostype2(otf, tab, tag);
740 break;
741 case 3:
742 otf_gpostype3(otf, tab, tag);
743 break;
744 default:
745 otf_unsupported("GPOS", type, 0);
751 static void otf_gsub(void *otf, void *gsub)
753 struct otflookup lookups[NLOOKUPS];
754 void *lookuplist = gsub + U16(gsub, 8);
755 int nlookups = otf_gtab(otf, gsub, lookups);
756 int i, j;
757 for (i = 0; i < nlookups; i++) {
758 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
759 char *tag = lookups[i].feat;
760 int ltype = U16(lookup, 0);
761 int ntabs = U16(lookup, 4);
762 for (j = 0; j < ntabs; j++) {
763 void *tab = lookup + U16(lookup, 6 + 2 * j);
764 int type = ltype;
765 if (type == 7) { /* extension substitution */
766 type = U16(tab, 2);
767 tab = tab + U32(tab, 4);
769 switch (type) {
770 case 1:
771 otf_gsubtype1(otf, tab, tag, NULL);
772 break;
773 case 3:
774 otf_gsubtype3(otf, tab, tag, NULL);
775 break;
776 case 4:
777 otf_gsubtype4(otf, tab, tag, NULL);
778 break;
779 case 6:
780 otf_gsubtype6(otf, tab, tag, gsub);
781 break;
782 default:
783 otf_unsupported("GSUB", type, 0);
789 static int xread(int fd, char *buf, int len)
791 int nr = 0;
792 while (nr < len) {
793 int ret = read(fd, buf + nr, len - nr);
794 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
795 continue;
796 if (ret <= 0)
797 break;
798 nr += ret;
800 return nr;
803 static char buf[BUFLEN];
805 int otf_read(void)
807 int i;
808 if (xread(0, buf, sizeof(buf)) <= 0)
809 return 1;
810 upm = U16(otf_table(buf, "head"), 18);
811 otf_name(buf, otf_table(buf, "name"));
812 otf_cmap(buf, otf_table(buf, "cmap"));
813 otf_post(buf, otf_table(buf, "post"));
814 if (otf_table(buf, "glyf"))
815 otf_glyf(buf, otf_table(buf, "glyf"));
816 otf_hmtx(buf, otf_table(buf, "hmtx"));
817 for (i = 0; i < glyph_n; i++) {
818 trfn_char(glyph_name[i], -1,
819 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
820 owid(glyph_wid[i]),
821 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
822 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
824 if (otf_table(buf, "kern"))
825 otf_kern(buf, otf_table(buf, "kern"));
826 return 0;
829 void otf_feat(int r, int k, int w)
831 res = r;
832 kmin = k;
833 warn = w;
834 if (otf_table(buf, "GSUB"))
835 otf_gsub(buf, otf_table(buf, "GSUB"));
836 if (otf_table(buf, "GPOS"))
837 otf_gpos(buf, otf_table(buf, "GPOS"));
840 /* glyph groups */
841 static int *ggrp_g[NGRPS];
842 static int ggrp_len[NGRPS];
843 static int ggrp_n;
845 static int ggrp_find(int *src, int n)
847 int i, j;
848 for (i = 0; i < ggrp_n; i++) {
849 if (ggrp_len[i] == n) {
850 for (j = 0; j < n; j++)
851 if (src[j] != ggrp_g[i][j])
852 break;
853 if (j == n)
854 return i;
857 return -1;
860 int ggrp_make(int *src, int n)
862 int id = ggrp_find(src, n);
863 int i;
864 if (id >= 0)
865 return id;
866 id = ggrp_n++;
867 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
868 ggrp_len[id] = n;
869 for (i = 0; i < n; i++)
870 ggrp_g[id][i] = src[i];
871 printf("ggrp %d %d", id, n);
872 for (i = 0; i < n; i++)
873 printf(" %s", glyph_name[src[i]]);
874 printf("\n");
875 return id;
878 static char *macset[] = {
879 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
880 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
881 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
882 "comma", "hyphen", "period", "slash", "zero",
883 "one", "two", "three", "four", "five",
884 "six", "seven", "eight", "nine", "colon",
885 "semicolon", "less", "equal", "greater", "question",
886 "at", "A", "B", "C", "D",
887 "E", "F", "G", "H", "I",
888 "J", "K", "L", "M", "N",
889 "O", "P", "Q", "R", "S",
890 "T", "U", "V", "W", "X",
891 "Y", "Z", "bracketleft", "backslash", "bracketright",
892 "asciicircum", "underscore", "grave", "a", "b",
893 "c", "d", "e", "f", "g",
894 "h", "i", "j", "k", "l",
895 "m", "n", "o", "p", "q",
896 "r", "s", "t", "u", "v",
897 "w", "x", "y", "z", "braceleft",
898 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
899 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
900 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
901 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
902 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
903 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
904 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
905 "dagger", "degree", "cent", "sterling", "section",
906 "bullet", "paragraph", "germandbls", "registered", "copyright",
907 "trademark", "acute", "dieresis", "notequal", "AE",
908 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
909 "yen", "mu", "partialdiff", "summation", "product",
910 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
911 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
912 "radical", "florin", "approxequal", "Delta", "guillemotleft",
913 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
914 "Otilde", "OE", "oe", "endash", "emdash",
915 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
916 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
917 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
918 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
919 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
920 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
921 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
922 "dotlessi", "circumflex", "tilde", "macron", "breve",
923 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
924 "caron", "Lslash", "lslash", "Scaron", "scaron",
925 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
926 "Yacute", "yacute", "Thorn", "thorn", "minus",
927 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
928 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
929 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
930 "Ccaron", "ccaron", "dcroat",