gen.sh: the arguments can specify FP and TP
[neatmkfn.git] / otf.c
blob404abadae99bc5953ac81b4f4af687afd86d31b5
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 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
355 valuerecord_print(vfmt, sub + 6);
356 printf("\n");
359 if (fmt == 2) {
360 nvals = U16(sub, 6);
361 for (i = 0; i < nvals; i++) {
362 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
363 valuerecord_print(vfmt, sub + 8 + i * vlen);
364 printf("\n");
369 /* pair adjustment positioning */
370 static void otf_gpostype2(void *otf, void *sub, char *feat)
372 int fmt = U16(sub, 0);
373 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
374 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
375 int fmtoff1, fmtoff2;
376 int vrlen; /* the length of vfmt1 and vfmt2 */
377 int i, j;
378 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
379 if (fmt == 1) {
380 int cov[NGLYPHS];
381 int nc1 = U16(sub, 8);
382 coverage(sub + U16(sub, 2), cov);
383 for (i = 0; i < nc1; i++) {
384 void *c2 = sub + U16(sub, 10 + 2 * i);
385 int nc2 = U16(c2, 0);
386 for (j = 0; j < nc2; j++) {
387 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
388 fmtoff1 = 2 + (2 + vrlen) * j + 2;
389 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
390 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
391 valuerecord_small(vfmt2, c2 + fmtoff2))
392 continue;
393 printf("gpos %s 2", feat);
394 printf(" %s", glyph_name[cov[i]]);
395 valuerecord_print(vfmt1, c2 + fmtoff1);
396 printf(" %s", glyph_name[second]);
397 valuerecord_print(vfmt2, c2 + fmtoff2);
398 printf("\n");
402 if (fmt == 2) {
403 int gl1[NGLYPHS], gl2[NGLYPHS];
404 int cls1[NGLYPHS], cls2[NGLYPHS];
405 int grp1[NGLYPHS], grp2[NGLYPHS];
406 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
407 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
408 int ncls1 = U16(sub, 12);
409 int ncls2 = U16(sub, 14);
410 for (i = 0; i < ncls1; i++)
411 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
412 for (i = 0; i < ncls2; i++)
413 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
414 for (i = 0; i < ncls1; i++) {
415 for (j = 0; j < ncls2; j++) {
416 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
417 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
418 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
419 valuerecord_small(vfmt2, sub + fmtoff2))
420 continue;
421 printf("gpos %s %d", feat, 2);
422 printf(" @%d", grp1[i]);
423 valuerecord_print(vfmt1, sub + fmtoff1);
424 printf(" @%d", grp2[j]);
425 valuerecord_print(vfmt2, sub + fmtoff2);
426 printf("\n");
432 /* cursive attachment positioning */
433 static void otf_gpostype3(void *otf, void *sub, char *feat)
435 int fmt = U16(sub, 0);
436 int cov[NGLYPHS];
437 int i, n;
438 coverage(sub + U16(sub, 2), cov);
439 if (fmt != 1)
440 return;
441 n = U16(sub, 4);
442 for (i = 0; i < n; i++) {
443 int prev = U16(sub, 6 + 4 * i);
444 int next = U16(sub, 6 + 4 * i + 2);
445 printf("gcur %s %s", feat, glyph_name[cov[i]]);
446 if (prev)
447 printf(" %d %d", uwid(S16(sub, prev + 2)),
448 uwid(S16(sub, prev + 4)));
449 else
450 printf(" - -");
451 if (next)
452 printf(" %d %d", uwid(S16(sub, next + 2)),
453 uwid(S16(sub, next + 4)));
454 else
455 printf(" - -");
456 printf("\n");
460 /* gsub context */
461 struct gctx {
462 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
463 int igrp[GCTXLEN]; /* input coverage arrays */
464 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
465 int bn, in, ln; /* size of b[], i[], l[] */
466 int seqidx; /* sequence index */
469 static int gctx_len(struct gctx *ctx, int patlen)
471 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
474 static void gctx_backtrack(struct gctx *ctx)
476 int i;
477 if (!ctx)
478 return;
479 for (i = 0; i < ctx->bn; i++)
480 printf(" =@%d", ctx->bgrp[i]);
481 for (i = 0; i < ctx->seqidx; i++)
482 printf(" =@%d", ctx->igrp[i]);
485 static void gctx_lookahead(struct gctx *ctx, int patlen)
487 int i;
488 if (!ctx)
489 return;
490 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
491 printf(" =@%d", ctx->igrp[i]);
492 for (i = 0; i < ctx->ln; i++)
493 printf(" =@%d", ctx->lgrp[i]);
496 /* single substitution */
497 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
499 int cov[NGLYPHS];
500 int fmt = U16(sub, 0);
501 int ncov;
502 int i;
503 ncov = coverage(sub + U16(sub, 2), cov);
504 if (fmt == 1) {
505 for (i = 0; i < ncov; i++) {
506 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
507 gctx_backtrack(ctx);
508 printf(" -%s +%s", glyph_name[cov[i]],
509 glyph_name[cov[i] + S16(sub, 4)]);
510 gctx_lookahead(ctx, 1);
511 printf("\n");
514 if (fmt == 2) {
515 int n = U16(sub, 4);
516 for (i = 0; i < n; i++) {
517 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
518 gctx_backtrack(ctx);
519 printf(" -%s +%s", glyph_name[cov[i]],
520 glyph_name[U16(sub, 6 + 2 * i)]);
521 gctx_lookahead(ctx, 1);
522 printf("\n");
527 /* alternate substitution */
528 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
530 int cov[NGLYPHS];
531 int fmt = U16(sub, 0);
532 int n, i, j;
533 if (fmt != 1)
534 return;
535 coverage(sub + U16(sub, 2), cov);
536 n = U16(sub, 4);
537 for (i = 0; i < n; i++) {
538 void *alt = sub + U16(sub, 6 + 2 * i);
539 int nalt = U16(alt, 0);
540 for (j = 0; j < nalt; j++) {
541 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
542 gctx_backtrack(ctx);
543 printf(" -%s +%s", glyph_name[cov[i]],
544 glyph_name[U16(alt, 2 + 2 * j)]);
545 gctx_lookahead(ctx, 1);
546 printf("\n");
551 /* ligature substitution */
552 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
554 int fmt = U16(sub, 0);
555 int cov[NGLYPHS];
556 int n, i, j, k;
557 if (fmt != 1)
558 return;
559 coverage(sub + U16(sub, 2), cov);
560 n = U16(sub, 4);
561 for (i = 0; i < n; i++) {
562 void *set = sub + U16(sub, 6 + 2 * i);
563 int nset = U16(set, 0);
564 for (j = 0; j < nset; j++) {
565 void *lig = set + U16(set, 2 + 2 * j);
566 int nlig = U16(lig, 2);
567 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
568 gctx_backtrack(ctx);
569 printf(" -%s", glyph_name[cov[i]]);
570 for (k = 0; k < nlig - 1; k++)
571 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
572 printf(" +%s", glyph_name[U16(lig, 0)]);
573 gctx_lookahead(ctx, nlig);
574 printf("\n");
579 /* chaining contextual substitution */
580 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
582 struct gctx ctx = {{0}};
583 void *lookups = gsub + U16(gsub, 8);
584 int fmt = U16(sub, 0);
585 int cov[NGLYPHS];
586 int i, j, nsub, ncov;
587 int off = 2;
588 if (fmt != 3) {
589 otf_unsupported("GSUB", 6, fmt);
590 return;
592 ctx.bn = U16(sub, off);
593 for (i = 0; i < ctx.bn; i++) {
594 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
595 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
597 off += 2 + 2 * ctx.bn;
598 ctx.in = U16(sub, off);
599 for (i = 0; i < ctx.in; i++) {
600 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
601 ctx.igrp[i] = ggrp_coverage(cov, ncov);
603 off += 2 + 2 * ctx.in;
604 ctx.ln = U16(sub, off);
605 for (i = 0; i < ctx.ln; i ++) {
606 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
607 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
609 off += 2 + 2 * ctx.ln;
610 nsub = U16(sub, off); /* nsub > 1 is not supported */
611 for (i = 0; i < nsub && i < 1; i++) {
612 int lidx = U16(sub, off + 2 + 4 * i + 2);
613 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
614 int ltype = U16(lookup, 0);
615 int ntabs = U16(lookup, 4);
616 ctx.seqidx = U16(sub, off + 2 + 4 * i);
617 for (j = 0; j < ntabs; j++) {
618 void *tab = lookup + U16(lookup, 6 + 2 * j);
619 int type = ltype;
620 if (type == 7) { /* extension substitution */
621 type = U16(tab, 2);
622 tab = tab + U32(tab, 4);
624 if (type == 1)
625 otf_gsubtype1(otf, tab, feat, &ctx);
626 if (type == 3)
627 otf_gsubtype3(otf, tab, feat, &ctx);
628 if (type == 4)
629 otf_gsubtype4(otf, tab, feat, &ctx);
634 /* an otf gsub/gpos lookup */
635 struct otflookup {
636 char feat[8]; /* feature name */
637 int lookup; /* index into the lookup table */
640 /* parse the given gsub/gpos feature table */
641 static int otf_featrec(void *otf, void *gtab, void *featrec, struct otflookup *lookups)
643 void *feats = gtab + U16(gtab, 6);
644 void *feat = feats + U16(featrec, 4);
645 int nlookups = U16(feat, 2);
646 int i;
647 for (i = 0; i < nlookups; i++) {
648 memcpy(lookups[i].feat, featrec, 4);
649 lookups[i].feat[4] = '\0';
650 lookups[i].lookup = U16(feat, 4 + 2 * i);
652 return nlookups;
655 /* parse the given language table and its feature tables */
656 static int otf_lang(void *otf, void *gtab, void *lang, struct otflookup *lookups)
658 void *feats = gtab + U16(gtab, 6);
659 int featidx = U16(lang, 2);
660 int nfeat = U16(lang, 4);
661 int n = 0;
662 int i;
663 if (featidx != 0xffff)
664 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, lookups + n);
665 for (i = 0; i < nfeat; i++)
666 n += otf_featrec(otf, gtab,
667 feats + 2 + 6 * U16(lang, 6 + 2 * i), lookups + n);
668 return n;
671 static int lookupcmp(void *v1, void *v2)
673 struct otflookup *l1 = v1;
674 struct otflookup *l2 = v2;
675 if (trfn_featrank(l1->feat) != trfn_featrank(l2->feat))
676 return trfn_featrank(l1->feat) - trfn_featrank(l2->feat);
677 return l1->lookup - l2->lookup;
680 /* extract lookup tables for all features of the given gsub/gpos table */
681 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
683 void *scripts = gpos + U16(gpos, 4);
684 int nscripts, nlangs;
685 void *script;
686 char tag[8];
687 int i, j;
688 int n = 0;
689 nscripts = U16(scripts, 0);
690 for (i = 0; i < nscripts; i++) {
691 void *grec = scripts + 2 + 6 * i;
692 memcpy(tag, grec, 4);
693 tag[4] = '\0';
694 if (!trfn_script(tag, nscripts))
695 continue;
696 script = scripts + U16(grec, 4);
697 nlangs = U16(script, 2);
698 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
699 n += otf_lang(otf, gpos, script + U16(script, 0), lookups + n);
700 for (j = 0; j < nlangs; j++) {
701 void *lrec = script + 4 + 6 * j;
702 memcpy(tag, lrec, 4);
703 tag[4] = '\0';
704 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
705 n += otf_lang(otf, gpos, script + U16(lrec, 4), lookups + n);
708 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
709 return n;
712 static void otf_gpos(void *otf, void *gpos)
714 struct otflookup lookups[NLOOKUPS];
715 void *lookuplist = gpos + U16(gpos, 8);
716 int nlookups = otf_gtab(otf, gpos, lookups);
717 int i, j;
718 for (i = 0; i < nlookups; i++) {
719 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
720 char *tag = lookups[i].feat;
721 int ltype = U16(lookup, 0);
722 int ntabs = U16(lookup, 4);
723 for (j = 0; j < ntabs; j++) {
724 void *tab = lookup + U16(lookup, 6 + 2 * j);
725 int type = ltype;
726 if (type == 9) { /* extension positioning */
727 type = U16(tab, 2);
728 tab = tab + U32(tab, 4);
730 switch (type) {
731 case 1:
732 otf_gpostype1(otf, tab, tag);
733 break;
734 case 2:
735 otf_gpostype2(otf, tab, tag);
736 break;
737 case 3:
738 otf_gpostype3(otf, tab, tag);
739 break;
740 default:
741 otf_unsupported("GPOS", type, 0);
747 static void otf_gsub(void *otf, void *gsub)
749 struct otflookup lookups[NLOOKUPS];
750 void *lookuplist = gsub + U16(gsub, 8);
751 int nlookups = otf_gtab(otf, gsub, lookups);
752 int i, j;
753 for (i = 0; i < nlookups; i++) {
754 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
755 char *tag = lookups[i].feat;
756 int ltype = U16(lookup, 0);
757 int ntabs = U16(lookup, 4);
758 for (j = 0; j < ntabs; j++) {
759 void *tab = lookup + U16(lookup, 6 + 2 * j);
760 int type = ltype;
761 if (type == 7) { /* extension substitution */
762 type = U16(tab, 2);
763 tab = tab + U32(tab, 4);
765 switch (type) {
766 case 1:
767 otf_gsubtype1(otf, tab, tag, NULL);
768 break;
769 case 3:
770 otf_gsubtype3(otf, tab, tag, NULL);
771 break;
772 case 4:
773 otf_gsubtype4(otf, tab, tag, NULL);
774 break;
775 case 6:
776 otf_gsubtype6(otf, tab, tag, gsub);
777 break;
778 default:
779 otf_unsupported("GSUB", type, 0);
785 static int xread(int fd, char *buf, int len)
787 int nr = 0;
788 while (nr < len) {
789 int ret = read(fd, buf + nr, len - nr);
790 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
791 continue;
792 if (ret <= 0)
793 break;
794 nr += ret;
796 return nr;
799 static char buf[BUFLEN];
801 int otf_read(void)
803 int i;
804 if (xread(0, buf, sizeof(buf)) <= 0)
805 return 1;
806 upm = U16(otf_table(buf, "head"), 18);
807 otf_name(buf, otf_table(buf, "name"));
808 otf_cmap(buf, otf_table(buf, "cmap"));
809 otf_post(buf, otf_table(buf, "post"));
810 if (otf_table(buf, "glyf"))
811 otf_glyf(buf, otf_table(buf, "glyf"));
812 otf_hmtx(buf, otf_table(buf, "hmtx"));
813 for (i = 0; i < glyph_n; i++) {
814 trfn_char(glyph_name[i], -1,
815 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
816 owid(glyph_wid[i]),
817 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
818 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
820 if (otf_table(buf, "kern"))
821 otf_kern(buf, otf_table(buf, "kern"));
822 return 0;
825 void otf_feat(int r, int k, int w)
827 res = r;
828 kmin = k;
829 warn = w;
830 if (otf_table(buf, "GSUB"))
831 otf_gsub(buf, otf_table(buf, "GSUB"));
832 if (otf_table(buf, "GPOS"))
833 otf_gpos(buf, otf_table(buf, "GPOS"));
836 /* glyph groups */
837 static int *ggrp_g[NGRPS];
838 static int ggrp_len[NGRPS];
839 static int ggrp_n;
841 static int ggrp_find(int *src, int n)
843 int i, j;
844 for (i = 0; i < ggrp_n; i++) {
845 if (ggrp_len[i] == n) {
846 for (j = 0; j < n; j++)
847 if (src[j] != ggrp_g[i][j])
848 break;
849 if (j == n)
850 return i;
853 return -1;
856 int ggrp_make(int *src, int n)
858 int id = ggrp_find(src, n);
859 int i;
860 if (id >= 0)
861 return id;
862 id = ggrp_n++;
863 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
864 ggrp_len[id] = n;
865 for (i = 0; i < n; i++)
866 ggrp_g[id][i] = src[i];
867 printf("ggrp %d %d", id, n);
868 for (i = 0; i < n; i++)
869 printf(" %s", glyph_name[src[i]]);
870 printf("\n");
871 return id;
874 static char *macset[] = {
875 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
876 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
877 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
878 "comma", "hyphen", "period", "slash", "zero",
879 "one", "two", "three", "four", "five",
880 "six", "seven", "eight", "nine", "colon",
881 "semicolon", "less", "equal", "greater", "question",
882 "at", "A", "B", "C", "D",
883 "E", "F", "G", "H", "I",
884 "J", "K", "L", "M", "N",
885 "O", "P", "Q", "R", "S",
886 "T", "U", "V", "W", "X",
887 "Y", "Z", "bracketleft", "backslash", "bracketright",
888 "asciicircum", "underscore", "grave", "a", "b",
889 "c", "d", "e", "f", "g",
890 "h", "i", "j", "k", "l",
891 "m", "n", "o", "p", "q",
892 "r", "s", "t", "u", "v",
893 "w", "x", "y", "z", "braceleft",
894 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
895 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
896 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
897 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
898 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
899 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
900 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
901 "dagger", "degree", "cent", "sterling", "section",
902 "bullet", "paragraph", "germandbls", "registered", "copyright",
903 "trademark", "acute", "dieresis", "notequal", "AE",
904 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
905 "yen", "mu", "partialdiff", "summation", "product",
906 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
907 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
908 "radical", "florin", "approxequal", "Delta", "guillemotleft",
909 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
910 "Otilde", "OE", "oe", "endash", "emdash",
911 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
912 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
913 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
914 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
915 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
916 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
917 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
918 "dotlessi", "circumflex", "tilde", "macron", "breve",
919 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
920 "caron", "Lslash", "lslash", "Scaron", "scaron",
921 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
922 "Yacute", "yacute", "Thorn", "thorn", "minus",
923 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
924 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
925 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
926 "Ccaron", "ccaron", "dcroat",