gen.sh: include a loop for converting afm files as well
[neatmkfn.git] / otf.c
blobc469b74620a61867ce0f88a57090a8aa2896d2c1
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 GNLEN (64)
11 #define BUFLEN (1 << 23)
12 #define NGRPS 2048
13 #define MAX(a, b) ((a) < (b) ? (b) : (a))
15 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
16 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
17 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
18 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
19 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
21 #define OTFLEN 12 /* otf header length */
22 #define OTFRECLEN 16 /* otf header record length */
23 #define CMAPLEN 4 /* cmap header length */
24 #define CMAPRECLEN 8 /* cmap record length */
25 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
26 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
28 typedef unsigned int u32;
29 typedef unsigned short u16;
30 typedef unsigned char u8;
31 typedef int s32;
32 typedef short s16;
34 static char glyph_name[NGLYPHS][GNLEN];
35 static int glyph_code[NGLYPHS];
36 static int glyph_bbox[NGLYPHS][4];
37 static int glyph_wid[NGLYPHS];
38 static int glyph_n;
39 static int upm; /* units per em */
40 static int res; /* device resolution */
41 static int kmin; /* minimum kerning value */
42 static int warn;
44 static char *macset[];
46 static int owid(int w)
48 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
51 static int uwid(int w)
53 int d = 7200 / res;
54 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
57 /* report unsupported otf tables */
58 static void otf_unsupported(char *sub, int type, int fmt)
60 if (warn) {
61 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
62 if (fmt > 0)
63 fprintf(stderr, " format %d", fmt);
64 fprintf(stderr, "\n");
68 /* find the otf table with the given name */
69 static void *otf_table(void *otf, char *name)
71 void *recs = otf + OTFLEN; /* otf table records */
72 void *rec; /* beginning of a table record */
73 int nrecs = U16(otf, 4);
74 int i;
75 for (i = 0; i < nrecs; i++) {
76 rec = recs + i * OTFRECLEN;
77 if (!strncmp(rec, name, 4))
78 return otf + U32(rec, 8);
80 return NULL;
83 /* parse otf cmap format 4 subtable */
84 static void otf_cmap4(void *otf, void *cmap4)
86 int nsegs;
87 void *ends, *begs, *deltas, *offsets;
88 int beg, end, delta, offset;
89 int i, j;
90 nsegs = U16(cmap4, 6) / 2;
91 ends = cmap4 + 14;
92 begs = ends + 2 * nsegs + 2;
93 deltas = begs + 2 * nsegs;
94 offsets = deltas + 2 * nsegs;
95 for (i = 0; i < nsegs; i++) {
96 beg = U16(begs, 2 * i);
97 end = U16(ends, 2 * i);
98 delta = U16(deltas, 2 * i);
99 offset = U16(offsets, 2 * i);
100 if (offset) {
101 for (j = beg; j <= end; j++)
102 glyph_code[(U16(offsets + 2 * i,
103 offset + (j - beg) * 2) + delta) & 0xffff] = j;
104 } else {
105 for (j = beg; j <= end; j++)
106 glyph_code[(j + delta) & 0xffff] = j;
111 /* parse otf cmap header */
112 static void otf_cmap(void *otf, void *cmap)
114 void *recs = cmap + CMAPLEN; /* cmap records */
115 void *rec; /* a cmap record */
116 void *tab; /* a cmap subtable */
117 int plat, enc;
118 int fmt;
119 int nrecs = U16(cmap, 2);
120 int i;
121 for (i = 0; i < nrecs; i++) {
122 rec = recs + i * CMAPRECLEN;
123 plat = U16(rec, 0);
124 enc = U16(rec, 2);
125 tab = cmap + U32(rec, 4);
126 fmt = U16(tab, 0);
127 if (plat == 3 && enc == 1 && fmt == 4)
128 otf_cmap4(otf, tab);
132 static void otf_post(void *otf, void *post)
134 void *post2; /* version 2.0 header */
135 void *index; /* glyph name indices */
136 void *names; /* glyph names */
137 int i, idx;
138 int cname = 0;
139 if (U32(post, 0) != 0x00020000)
140 return;
141 post2 = post + 32;
142 glyph_n = U16(post2, 0);
143 index = post2 + 2;
144 names = index + 2 * glyph_n;
145 for (i = 0; i < glyph_n; i++) {
146 idx = U16(index, 2 * i);
147 if (idx <= 257) {
148 strcpy(glyph_name[i], macset[idx]);
149 } else {
150 memcpy(glyph_name[i], names + cname + 1,
151 U8(names, cname));
152 glyph_name[i][U8(names, cname)] = '\0';
153 cname += U8(names, cname) + 1;
158 static void otf_glyf(void *otf, void *glyf)
160 void *maxp = otf_table(otf, "maxp");
161 void *head = otf_table(otf, "head");
162 void *loca = otf_table(otf, "loca");
163 void *gdat;
164 void *gdat_next;
165 int n = U16(maxp, 4);
166 int fmt = U16(head, 50);
167 int i, j;
168 for (i = 0; i < n; i++) {
169 if (fmt) {
170 gdat = glyf + U32(loca, 4 * i);
171 gdat_next = glyf + U32(loca, 4 * (i + 1));
172 } else {
173 gdat = glyf + U16(loca, 2 * i) * 2;
174 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
176 if (gdat < gdat_next)
177 for (j = 0; j < 4; j++)
178 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
182 static void otf_hmtx(void *otf, void *hmtx)
184 void *hhea = otf_table(otf, "hhea");
185 int n;
186 int i;
187 n = U16(hhea, 34);
188 for (i = 0; i < n; i++)
189 glyph_wid[i] = U16(hmtx, i * 4);
190 for (i = n; i < glyph_n; i++)
191 glyph_wid[i] = glyph_wid[n - 1];
194 static void otf_kern(void *otf, void *kern)
196 int n; /* number of kern subtables */
197 void *tab; /* a kern subtable */
198 int off = 4;
199 int npairs;
200 int cov;
201 int i, j;
202 int c1, c2, val;
203 n = U16(kern, 2);
204 for (i = 0; i < n; i++) {
205 tab = kern + off;
206 off += U16(tab, 2);
207 cov = U16(tab, 4);
208 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
209 npairs = U16(tab, 6);
210 for (j = 0; j < npairs; j++) {
211 c1 = U16(tab, 14 + 6 * j);
212 c2 = U16(tab, 14 + 6 * j + 2);
213 val = S16(tab, 14 + 6 * j + 4);
214 trfn_kern(glyph_name[c1], glyph_name[c2],
215 owid(val));
221 static int coverage(void *cov, int *out)
223 int fmt = U16(cov, 0);
224 int n = U16(cov, 2);
225 int beg, end;
226 int ncov = 0;
227 int i, j;
228 if (fmt == 1) {
229 for (i = 0; i < n; i++)
230 out[ncov++] = U16(cov, 4 + 2 * i);
232 if (fmt == 2) {
233 for (i = 0; i < n; i++) {
234 beg = U16(cov, 4 + 6 * i);
235 end = U16(cov, 4 + 6 * i + 2);
236 for (j = beg; j <= end; j++)
237 out[ncov++] = j;
240 return ncov;
243 static int classdef(void *tab, int *gl, int *cls)
245 int fmt = U16(tab, 0);
246 int beg, end;
247 int n, ngl = 0;
248 int i, j;
249 if (fmt == 1) {
250 beg = U16(tab, 2);
251 ngl = U16(tab, 4);
252 for (i = 0; i < ngl; i++) {
253 gl[i] = beg + i;
254 cls[i] = U16(tab, 6 + 2 * i);
257 if (fmt == 2) {
258 n = U16(tab, 2);
259 for (i = 0; i < n; i++) {
260 beg = U16(tab, 4 + 6 * i);
261 end = U16(tab, 4 + 6 * i + 2);
262 for (j = beg; j <= end; j++) {
263 gl[ngl] = j;
264 cls[ngl] = U16(tab, 4 + 6 * i + 4);
265 ngl++;
269 return ngl;
272 static int intcmp(void *v1, void *v2)
274 return *(int *) v1 - *(int *) v2;
277 int ggrp_make(int *src, int n);
279 static int ggrp_class(int *src, int *cls, int nsrc, int id)
281 int g[NGLYPHS];
282 int n = 0;
283 int i;
284 for (i = 0; i < nsrc; i++)
285 if (cls[i] == id)
286 g[n++] = src[i];
287 qsort(g, n, sizeof(g[0]), (void *) intcmp);
288 return ggrp_make(g, n);
291 static int ggrp_coverage(int *g, int n)
293 qsort(g, n, sizeof(g[0]), (void *) intcmp);
294 return ggrp_make(g, n);
297 static int valuerecord_len(int fmt)
299 int off = 0;
300 int i;
301 for (i = 0; i < 8; i++)
302 if (fmt & (1 << i))
303 off += 2;
304 return off;
307 static void valuerecord_print(int fmt, void *rec)
309 int vals[8] = {0};
310 int off = 0;
311 int i;
312 for (i = 0; i < 8; i++) {
313 if (fmt & (1 << i)) {
314 vals[i] = uwid(S16(rec, off));
315 off += 2;
318 if (fmt)
319 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
322 static int valuerecord_small(int fmt, void *rec)
324 int off = 0;
325 int i;
326 for (i = 0; i < 8; i++) {
327 if (fmt & (1 << i)) {
328 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
329 return 0;
330 off += 2;
333 return 1;
336 /* single adjustment positioning */
337 static void otf_gpostype1(void *otf, void *sub, char *feat)
339 int fmt = U16(sub, 0);
340 int vfmt = U16(sub, 4);
341 int cov[NGLYPHS];
342 int ncov, nvals;
343 int vlen = valuerecord_len(vfmt);
344 int i;
345 ncov = coverage(sub + U16(sub, 2), cov);
346 if (fmt == 1) {
347 for (i = 0; i < ncov; i++) {
348 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
349 valuerecord_print(vfmt, sub + 6);
350 printf("\n");
353 if (fmt == 2) {
354 nvals = U16(sub, 6);
355 for (i = 0; i < nvals; i++) {
356 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
357 valuerecord_print(vfmt, sub + 8 + i * vlen);
358 printf("\n");
363 /* pair adjustment positioning */
364 static void otf_gpostype2(void *otf, void *sub, char *feat)
366 int fmt = U16(sub, 0);
367 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
368 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
369 int fmtoff1, fmtoff2;
370 int vrlen; /* the length of vfmt1 and vfmt2 */
371 int i, j;
372 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
373 if (fmt == 1) {
374 int cov[NGLYPHS];
375 int nc1 = U16(sub, 8);
376 coverage(sub + U16(sub, 2), cov);
377 for (i = 0; i < nc1; i++) {
378 void *c2 = sub + U16(sub, 10 + 2 * i);
379 int nc2 = U16(c2, 0);
380 for (j = 0; j < nc2; j++) {
381 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
382 fmtoff1 = 2 + (2 + vrlen) * j + 2;
383 fmtoff2 = fmtoff1 + valuerecord_len(vfmt2);
384 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
385 valuerecord_small(vfmt2, c2 + fmtoff2))
386 continue;
387 printf("gpos %s 2", feat);
388 printf(" %s", glyph_name[cov[i]]);
389 valuerecord_print(vfmt1, c2 + fmtoff1);
390 printf(" %s", glyph_name[second]);
391 valuerecord_print(vfmt2, c2 + fmtoff2);
392 printf("\n");
396 if (fmt == 2) {
397 int gl1[NGLYPHS], gl2[NGLYPHS];
398 int cls1[NGLYPHS], cls2[NGLYPHS];
399 int grp1[NGLYPHS], grp2[NGLYPHS];
400 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
401 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
402 int ncls1 = U16(sub, 12);
403 int ncls2 = U16(sub, 14);
404 for (i = 0; i < ncls1; i++)
405 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
406 for (i = 0; i < ncls2; i++)
407 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
408 for (i = 0; i < ncls1; i++) {
409 for (j = 0; j < ncls2; j++) {
410 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
411 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
412 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
413 valuerecord_small(vfmt2, sub + fmtoff2))
414 continue;
415 printf("gpos %s %d", feat, 2);
416 printf(" @%d", grp1[i]);
417 valuerecord_print(vfmt1, sub + fmtoff1);
418 printf(" @%d", grp2[j]);
419 valuerecord_print(vfmt2, sub + fmtoff2);
420 printf("\n");
426 /* cursive attachment positioning */
427 static void otf_gpostype3(void *otf, void *sub, char *feat)
429 int fmt = U16(sub, 0);
430 int cov[NGLYPHS];
431 int i, n;
432 coverage(sub + U16(sub, 2), cov);
433 if (fmt != 1)
434 return;
435 n = U16(sub, 4);
436 for (i = 0; i < n; i++) {
437 int prev = U16(sub, 6 + 4 * i);
438 int next = U16(sub, 6 + 4 * i + 2);
439 printf("gcur %s %s", feat, glyph_name[cov[i]]);
440 if (prev)
441 printf(" %d %d", uwid(S16(sub, prev + 2)),
442 uwid(S16(sub, prev + 4)));
443 else
444 printf(" - -");
445 if (next)
446 printf(" %d %d", uwid(S16(sub, next + 2)),
447 uwid(S16(sub, next + 4)));
448 else
449 printf(" - -");
450 printf("\n");
454 /* parse the given gpos feature table */
455 static void otf_gposfeatrec(void *otf, void *gpos, void *featrec)
457 void *feats = gpos + U16(gpos, 6);
458 void *lookups = gpos + U16(gpos, 8);
459 void *feat;
460 int nlookups;
461 char tag[8] = "";
462 int i, j;
463 memcpy(tag, featrec, 4);
464 feat = feats + U16(featrec, 4);
465 nlookups = U16(feat, 2);
466 for (i = 0; i < nlookups; i++) {
467 void *lookup = lookups + U16(lookups, 2 + 2 * U16(feat, 4 + 2 * i));
468 int ltype = U16(lookup, 0);
469 int ntabs = U16(lookup, 4);
470 for (j = 0; j < ntabs; j++) {
471 void *tab = lookup + U16(lookup, 6 + 2 * j);
472 int type = ltype;
473 if (type == 9) { /* extension positioning */
474 type = U16(tab, 2);
475 tab = tab + U32(tab, 4);
477 switch (type) {
478 case 1:
479 otf_gpostype1(otf, tab, tag);
480 break;
481 case 2:
482 otf_gpostype2(otf, tab, tag);
483 break;
484 case 3:
485 otf_gpostype3(otf, tab, tag);
486 break;
487 default:
488 otf_unsupported("GPOS", type, 0);
494 /* parse the given gpos language table and its feature tables */
495 static void otf_gposlang(void *otf, void *gpos, void *lang)
497 void *feats = gpos + U16(gpos, 6);
498 int featidx = U16(lang, 2);
499 int nfeat = U16(lang, 4);
500 int i;
501 if (featidx != 0xffff)
502 otf_gposfeatrec(otf, gpos, feats + 2 + 6 * featidx);
503 for (i = 0; i < nfeat; i++)
504 otf_gposfeatrec(otf, gpos,
505 feats + 2 + 6 * U16(lang, 6 + 2 * i));
508 static void otf_gpos(void *otf, void *gpos)
510 void *scripts = gpos + U16(gpos, 4);
511 int nscripts, nlangs;
512 void *script;
513 void *grec, *lrec;
514 char tag[8];
515 int i, j;
516 nscripts = U16(scripts, 0);
517 for (i = 0; i < nscripts; i++) {
518 grec = scripts + 2 + 6 * i;
519 memcpy(tag, grec, 4);
520 tag[4] = '\0';
521 if (!trfn_script(tag, nscripts))
522 continue;
523 script = scripts + U16(grec, 4);
524 nlangs = U16(script, 2);
525 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
526 otf_gposlang(otf, gpos, script + U16(script, 0));
527 for (j = 0; j < nlangs; j++) {
528 lrec = script + 4 + 6 * j;
529 memcpy(tag, lrec, 4);
530 tag[4] = '\0';
531 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
532 otf_gposlang(otf, gpos, script + U16(lrec, 4));
537 /* gsub context */
538 struct gctx {
539 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
540 int igrp[GCTXLEN]; /* input coverage arrays */
541 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
542 int bn, in, ln; /* size of b[], i[], l[] */
543 int seqidx; /* sequence index */
546 static int gctx_len(struct gctx *ctx, int patlen)
548 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
551 static void gctx_backtrack(struct gctx *ctx)
553 int i;
554 if (!ctx)
555 return;
556 for (i = 0; i < ctx->bn; i++)
557 printf(" =@%d", ctx->bgrp[i]);
558 for (i = 0; i < ctx->seqidx; i++)
559 printf(" =@%d", ctx->igrp[i]);
562 static void gctx_lookahead(struct gctx *ctx, int patlen)
564 int i;
565 if (!ctx)
566 return;
567 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
568 printf(" =@%d", ctx->igrp[i]);
569 for (i = 0; i < ctx->ln; i++)
570 printf(" =@%d", ctx->lgrp[i]);
573 /* single substitution */
574 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
576 int cov[NGLYPHS];
577 int fmt = U16(sub, 0);
578 int ncov;
579 int n;
580 int i;
581 ncov = coverage(sub + U16(sub, 2), cov);
582 if (fmt == 1) {
583 for (i = 0; i < ncov; i++) {
584 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
585 gctx_backtrack(ctx);
586 printf(" -%s +%s", glyph_name[cov[i]],
587 glyph_name[cov[i] + S16(sub, 4)]);
588 gctx_lookahead(ctx, 1);
589 printf("\n");
592 if (fmt == 2) {
593 n = U16(sub, 4);
594 for (i = 0; i < n; i++) {
595 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
596 gctx_backtrack(ctx);
597 printf(" -%s +%s", glyph_name[cov[i]],
598 glyph_name[U16(sub, 6 + 2 * i)]);
599 gctx_lookahead(ctx, 1);
600 printf("\n");
605 /* alternate substitution */
606 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
608 int cov[NGLYPHS];
609 int fmt = U16(sub, 0);
610 int n, i, j;
611 if (fmt != 1)
612 return;
613 coverage(sub + U16(sub, 2), cov);
614 n = U16(sub, 4);
615 for (i = 0; i < n; i++) {
616 void *alt = sub + U16(sub, 6 + 2 * i);
617 int nalt = U16(alt, 0);
618 for (j = 0; j < nalt; j++) {
619 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
620 gctx_backtrack(ctx);
621 printf(" -%s +%s", glyph_name[cov[i]],
622 glyph_name[U16(alt, 2 + 2 * j)]);
623 gctx_lookahead(ctx, 1);
624 printf("\n");
629 /* ligature substitution */
630 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
632 int fmt = U16(sub, 0);
633 int cov[NGLYPHS];
634 int n, i, j, k;
635 if (fmt != 1)
636 return;
637 coverage(sub + U16(sub, 2), cov);
638 n = U16(sub, 4);
639 for (i = 0; i < n; i++) {
640 void *set = sub + U16(sub, 6 + 2 * i);
641 int nset = U16(set, 0);
642 for (j = 0; j < nset; j++) {
643 void *lig = set + U16(set, 2 + 2 * j);
644 int nlig = U16(lig, 2);
645 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
646 gctx_backtrack(ctx);
647 printf(" -%s", glyph_name[cov[i]]);
648 for (k = 0; k < nlig - 1; k++)
649 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
650 printf(" +%s", glyph_name[U16(lig, 0)]);
651 gctx_lookahead(ctx, nlig);
652 printf("\n");
657 /* chaining contextual substitution */
658 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
660 struct gctx ctx = {{0}};
661 void *lookups = gsub + U16(gsub, 8);
662 int fmt = U16(sub, 0);
663 int cov[NGLYPHS];
664 int i, j, nsub, ncov;
665 int off = 2;
666 if (fmt != 3) {
667 otf_unsupported("GSUB", 6, fmt);
668 return;
670 ctx.bn = U16(sub, off);
671 for (i = 0; i < ctx.bn; i++) {
672 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
673 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
675 off += 2 + 2 * ctx.bn;
676 ctx.in = U16(sub, off);
677 for (i = 0; i < ctx.in; i++) {
678 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
679 ctx.igrp[i] = ggrp_coverage(cov, ncov);
681 off += 2 + 2 * ctx.in;
682 ctx.ln = U16(sub, off);
683 for (i = 0; i < ctx.ln; i ++) {
684 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
685 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
687 off += 2 + 2 * ctx.ln;
688 nsub = U16(sub, off); /* nsub > 1 is not supported */
689 for (i = 0; i < nsub && i < 1; i++) {
690 int lidx = U16(sub, off + 2 + 4 * i + 2);
691 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
692 int ltype = U16(lookup, 0);
693 int ntabs = U16(lookup, 4);
694 ctx.seqidx = U16(sub, off + 2 + 4 * i);
695 for (j = 0; j < ntabs; j++) {
696 void *tab = lookup + U16(lookup, 6 + 2 * j);
697 int type = ltype;
698 if (type == 7) { /* extension substitution */
699 type = U16(tab, 2);
700 tab = tab + U32(tab, 4);
702 if (type == 1)
703 otf_gsubtype1(otf, tab, feat, &ctx);
704 if (type == 3)
705 otf_gsubtype3(otf, tab, feat, &ctx);
706 if (type == 4)
707 otf_gsubtype4(otf, tab, feat, &ctx);
712 /* parse the given gsub feature table */
713 static void otf_gsubfeatrec(void *otf, void *gsub, void *featrec)
715 void *feats = gsub + U16(gsub, 6);
716 void *lookups = gsub + U16(gsub, 8);
717 void *feat;
718 int nlookups;
719 char tag[8] = "";
720 int i, j;
721 memcpy(tag, featrec, 4);
722 feat = feats + U16(featrec, 4);
723 nlookups = U16(feat, 2);
724 for (i = 0; i < nlookups; i++) {
725 void *lookup = lookups + U16(lookups, 2 + 2 * U16(feat, 4 + 2 * i));
726 int ltype = U16(lookup, 0);
727 int ntabs = U16(lookup, 4);
728 for (j = 0; j < ntabs; j++) {
729 void *tab = lookup + U16(lookup, 6 + 2 * j);
730 int type = ltype;
731 if (type == 7) { /* extension substitution */
732 type = U16(tab, 2);
733 tab = tab + U32(tab, 4);
735 switch (type) {
736 case 1:
737 otf_gsubtype1(otf, tab, tag, NULL);
738 break;
739 case 3:
740 otf_gsubtype3(otf, tab, tag, NULL);
741 break;
742 case 4:
743 otf_gsubtype4(otf, tab, tag, NULL);
744 break;
745 case 6:
746 otf_gsubtype6(otf, tab, tag, gsub);
747 break;
748 default:
749 otf_unsupported("GSUB", type, 0);
755 /* parse the given gsub language table and its feature tables */
756 static void otf_gsublang(void *otf, void *gsub, void *lang)
758 void *feats = gsub + U16(gsub, 6);
759 int featidx = U16(lang, 2);
760 int nfeat = U16(lang, 4);
761 int i;
762 if (featidx != 0xffff)
763 otf_gsubfeatrec(otf, gsub, feats + 2 + 6 * featidx);
764 for (i = 0; i < nfeat; i++)
765 otf_gsubfeatrec(otf, gsub,
766 feats + 2 + 6 * U16(lang, 6 + 2 * i));
769 static void otf_gsub(void *otf, void *gsub)
771 void *scripts = gsub + U16(gsub, 4);
772 int nscripts, nlangs;
773 void *script;
774 void *grec, *lrec;
775 char tag[8];
776 int i, j;
777 nscripts = U16(scripts, 0);
778 for (i = 0; i < nscripts; i++) {
779 grec = scripts + 2 + 6 * i;
780 memcpy(tag, grec, 4);
781 tag[4] = '\0';
782 if (!trfn_script(tag, nscripts))
783 continue;
784 script = scripts + U16(scripts + 2 + 6 * i, 4);
785 nlangs = U16(script, 2);
786 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
787 otf_gsublang(otf, gsub, script + U16(script, 0));
788 for (j = 0; j < nlangs; j++) {
789 lrec = script + 4 + 6 * j;
790 memcpy(tag, lrec, 4);
791 tag[4] = '\0';
792 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
793 otf_gsublang(otf, gsub, script + U16(lrec, 4));
798 int xread(int fd, char *buf, int len)
800 int nr = 0;
801 while (nr < len) {
802 int ret = read(fd, buf + nr, len - nr);
803 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
804 continue;
805 if (ret <= 0)
806 break;
807 nr += ret;
809 return nr;
812 static char buf[BUFLEN];
814 int otf_read(void)
816 int i;
817 if (xread(0, buf, sizeof(buf)) <= 0)
818 return 1;
819 upm = U16(otf_table(buf, "head"), 18);
820 otf_cmap(buf, otf_table(buf, "cmap"));
821 otf_post(buf, otf_table(buf, "post"));
822 if (otf_table(buf, "glyf"))
823 otf_glyf(buf, otf_table(buf, "glyf"));
824 otf_hmtx(buf, otf_table(buf, "hmtx"));
825 for (i = 0; i < glyph_n; i++) {
826 trfn_char(glyph_name[i], -1,
827 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
828 owid(glyph_wid[i]),
829 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
830 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
832 if (otf_table(buf, "kern"))
833 otf_kern(buf, otf_table(buf, "kern"));
834 return 0;
837 void otf_feat(int r, int k, int w)
839 res = r;
840 kmin = k;
841 warn = w;
842 if (otf_table(buf, "GSUB"))
843 otf_gsub(buf, otf_table(buf, "GSUB"));
844 if (otf_table(buf, "GPOS"))
845 otf_gpos(buf, otf_table(buf, "GPOS"));
848 /* glyph groups */
849 static int *ggrp_g[NGRPS];
850 static int ggrp_len[NGRPS];
851 static int ggrp_n;
853 static int ggrp_find(int *src, int n)
855 int i, j;
856 for (i = 0; i < ggrp_n; i++) {
857 if (ggrp_len[i] == n) {
858 for (j = 0; j < n; j++)
859 if (src[j] != ggrp_g[i][j])
860 break;
861 if (j == n)
862 return i;
865 return -1;
868 int ggrp_make(int *src, int n)
870 int id = ggrp_find(src, n);
871 int i;
872 if (id >= 0)
873 return id;
874 id = ggrp_n++;
875 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
876 ggrp_len[id] = n;
877 for (i = 0; i < n; i++)
878 ggrp_g[id][i] = src[i];
879 printf("ggrp %d %d", id, n);
880 for (i = 0; i < n; i++)
881 printf(" %s", glyph_name[src[i]]);
882 printf("\n");
883 return id;
886 static char *macset[] = {
887 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
888 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
889 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
890 "comma", "hyphen", "period", "slash", "zero",
891 "one", "two", "three", "four", "five",
892 "six", "seven", "eight", "nine", "colon",
893 "semicolon", "less", "equal", "greater", "question",
894 "at", "A", "B", "C", "D",
895 "E", "F", "G", "H", "I",
896 "J", "K", "L", "M", "N",
897 "O", "P", "Q", "R", "S",
898 "T", "U", "V", "W", "X",
899 "Y", "Z", "bracketleft", "backslash", "bracketright",
900 "asciicircum", "underscore", "grave", "a", "b",
901 "c", "d", "e", "f", "g",
902 "h", "i", "j", "k", "l",
903 "m", "n", "o", "p", "q",
904 "r", "s", "t", "u", "v",
905 "w", "x", "y", "z", "braceleft",
906 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
907 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
908 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
909 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
910 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
911 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
912 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
913 "dagger", "degree", "cent", "sterling", "section",
914 "bullet", "paragraph", "germandbls", "registered", "copyright",
915 "trademark", "acute", "dieresis", "notequal", "AE",
916 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
917 "yen", "mu", "partialdiff", "summation", "product",
918 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
919 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
920 "radical", "florin", "approxequal", "Delta", "guillemotleft",
921 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
922 "Otilde", "OE", "oe", "endash", "emdash",
923 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
924 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
925 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
926 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
927 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
928 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
929 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
930 "dotlessi", "circumflex", "tilde", "macron", "breve",
931 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
932 "caron", "Lslash", "lslash", "Scaron", "scaron",
933 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
934 "Yacute", "yacute", "Thorn", "thorn", "minus",
935 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
936 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
937 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
938 "Ccaron", "ccaron", "dcroat",