gen.sh: use urw-core35, if available
[neatmkfn.git] / otf.c
blob8b12a18cf10823d42567a18da6f9b8cb198d5cd6
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))
12 #define NGLYPHS (1 << 14)
13 #define NLOOKUPS (1 << 12)
14 #define GNLEN (64)
15 #define NGRPS 2048
17 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
18 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
19 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
20 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
21 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
23 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
25 typedef unsigned int u32;
26 typedef unsigned short u16;
27 typedef unsigned char u8;
28 typedef int s32;
29 typedef short s16;
31 static char glyph_name[NGLYPHS][GNLEN];
32 static int glyph_code[NGLYPHS];
33 static int glyph_bbox[NGLYPHS][4];
34 static int glyph_wid[NGLYPHS];
35 static int glyph_n;
36 static int upm; /* units per em */
37 static int res; /* device resolution */
38 static int kmin; /* minimum kerning value */
39 static int warn; /* report unsupported tables */
41 static char *macset[];
43 static int owid(int w)
45 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
48 static int uwid(int w)
50 int d = 7200 / res;
51 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
54 /* weather the script is right-to-left */
55 static int otf_r2l(char *feat)
57 char *scrp = strchr(feat, ':') + 1;
58 return !strcmp("arab", scrp) || !strcmp("hebr", scrp);
61 /* report unsupported otf tables */
62 static void otf_unsupported(char *sub, int type, int fmt)
64 if (warn) {
65 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
66 if (fmt > 0)
67 fprintf(stderr, " format %d", fmt);
68 fprintf(stderr, "\n");
72 /* find the otf table with the given name */
73 static void *otf_table(void *otf, char *name)
75 int nrecs = U16(otf, 4);
76 int i;
77 for (i = 0; i < nrecs; i++) {
78 void *rec = otf + 12 + i * 16; /* an otf table record */
79 if (!strncmp(rec, name, 4))
80 return otf + U32(rec, 8);
82 return NULL;
85 /* obtain postscript font name from name table */
86 static void otf_name(void *otf, void *tab)
88 char name[256];
89 void *str = tab + U16(tab, 4); /* storage area */
90 int n = U16(tab, 2); /* number of name records */
91 int i;
92 for (i = 0; i < n; i++) {
93 void *rec = tab + 6 + 12 * i;
94 int pid = U16(rec, 0); /* platform id */
95 int eid = U16(rec, 2); /* encoding id */
96 int lid = U16(rec, 4); /* language id */
97 int nid = U16(rec, 6); /* name id */
98 int len = U16(rec, 8); /* string length */
99 int off = U16(rec, 10); /* string offset */
100 if (pid == 1 && eid == 0 && lid == 0 && nid == 6) {
101 memcpy(name, str + off, len);
102 name[len] = '\0';
103 trfn_psfont(name);
108 /* parse otf cmap format 4 subtable */
109 static void otf_cmap4(void *otf, void *cmap4)
111 int nsegs;
112 void *ends, *begs, *deltas, *offsets;
113 int beg, end, delta, offset;
114 int i, j;
115 nsegs = U16(cmap4, 6) / 2;
116 ends = cmap4 + 14;
117 begs = ends + 2 * nsegs + 2;
118 deltas = begs + 2 * nsegs;
119 offsets = deltas + 2 * nsegs;
120 for (i = 0; i < nsegs; i++) {
121 beg = U16(begs, 2 * i);
122 end = U16(ends, 2 * i);
123 delta = U16(deltas, 2 * i);
124 offset = U16(offsets, 2 * i);
125 if (offset) {
126 for (j = beg; j <= end; j++)
127 glyph_code[(U16(offsets + 2 * i,
128 offset + (j - beg) * 2) + delta) & 0xffff] = j;
129 } else {
130 for (j = beg; j <= end; j++)
131 glyph_code[(j + delta) & 0xffff] = j;
136 /* parse otf cmap header */
137 static void otf_cmap(void *otf, void *cmap)
139 int nrecs = U16(cmap, 2);
140 int i;
141 for (i = 0; i < nrecs; i++) {
142 void *rec = cmap + 4 + i * 8; /* a cmap record */
143 int plat = U16(rec, 0);
144 int enc = U16(rec, 2);
145 void *tab = cmap + U32(rec, 4); /* a cmap subtable */
146 int fmt = U16(tab, 0);
147 if (plat == 3 && enc == 1 && fmt == 4)
148 otf_cmap4(otf, tab);
152 static void otf_post(void *otf, void *post)
154 void *post2; /* version 2.0 header */
155 void *index; /* glyph name indices */
156 void *names; /* glyph names */
157 int cname = 0;
158 int i;
159 if (U32(post, 0) != 0x00020000)
160 return;
161 post2 = post + 32;
162 glyph_n = U16(post2, 0);
163 index = post2 + 2;
164 names = index + 2 * glyph_n;
165 for (i = 0; i < glyph_n; i++) {
166 int idx = U16(index, 2 * i);
167 if (idx <= 257) {
168 strcpy(glyph_name[i], macset[idx]);
169 } else {
170 memcpy(glyph_name[i], names + cname + 1,
171 U8(names, cname));
172 glyph_name[i][U8(names, cname)] = '\0';
173 cname += U8(names, cname) + 1;
178 static void otf_glyf(void *otf, void *glyf)
180 void *maxp = otf_table(otf, "maxp");
181 void *head = otf_table(otf, "head");
182 void *loca = otf_table(otf, "loca");
183 void *gdat;
184 void *gdat_next;
185 int n = U16(maxp, 4);
186 int fmt = U16(head, 50);
187 int i, j;
188 for (i = 0; i < n; i++) {
189 if (fmt) {
190 gdat = glyf + U32(loca, 4 * i);
191 gdat_next = glyf + U32(loca, 4 * (i + 1));
192 } else {
193 gdat = glyf + U16(loca, 2 * i) * 2;
194 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
196 if (gdat < gdat_next)
197 for (j = 0; j < 4; j++)
198 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
202 static void otf_hmtx(void *otf, void *hmtx)
204 void *hhea = otf_table(otf, "hhea");
205 int n;
206 int i;
207 n = U16(hhea, 34);
208 for (i = 0; i < n; i++)
209 glyph_wid[i] = U16(hmtx, i * 4);
210 for (i = n; i < glyph_n; i++)
211 glyph_wid[i] = glyph_wid[n - 1];
214 static void otf_kern(void *otf, void *kern)
216 int off = 4;
217 int i, j;
218 int n = U16(kern, 2); /* number of kern subtables */
219 for (i = 0; i < n; i++) {
220 void *tab = kern + off; /* a kern subtable */
221 int cov = U16(tab, 4);
222 off += U16(tab, 2);
223 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
224 int npairs = U16(tab, 6);
225 for (j = 0; j < npairs; j++) {
226 int c1 = U16(tab, 14 + 6 * j);
227 int c2 = U16(tab, 14 + 6 * j + 2);
228 int val = S16(tab, 14 + 6 * j + 4);
229 trfn_kern(glyph_name[c1], glyph_name[c2],
230 owid(val));
236 static int coverage(void *cov, int *out)
238 int fmt = U16(cov, 0);
239 int n = U16(cov, 2);
240 int beg, end;
241 int ncov = 0;
242 int i, j;
243 if (fmt == 1) {
244 for (i = 0; i < n; i++)
245 out[ncov++] = U16(cov, 4 + 2 * i);
247 if (fmt == 2) {
248 for (i = 0; i < n; i++) {
249 beg = U16(cov, 4 + 6 * i);
250 end = U16(cov, 4 + 6 * i + 2);
251 for (j = beg; j <= end; j++)
252 out[ncov++] = j;
255 return ncov;
258 static int classdef(void *tab, int *gl, int *cls)
260 int fmt = U16(tab, 0);
261 int ngl = 0;
262 int i, j;
263 if (fmt == 1) {
264 int beg = U16(tab, 2);
265 ngl = U16(tab, 4);
266 for (i = 0; i < ngl; i++) {
267 gl[i] = beg + i;
268 cls[i] = U16(tab, 6 + 2 * i);
271 if (fmt == 2) {
272 int n = U16(tab, 2);
273 for (i = 0; i < n; i++) {
274 int beg = U16(tab, 4 + 6 * i);
275 int end = U16(tab, 4 + 6 * i + 2);
276 for (j = beg; j <= end; j++) {
277 gl[ngl] = j;
278 cls[ngl] = U16(tab, 4 + 6 * i + 4);
279 ngl++;
283 return ngl;
286 static int intcmp(void *v1, void *v2)
288 return *(int *) v1 - *(int *) v2;
291 static int ggrp_make(int *src, int n);
293 static int ggrp_class(int *src, int *cls, int nsrc, int id)
295 int g[NGLYPHS];
296 int n = 0;
297 int i;
298 for (i = 0; i < nsrc; i++)
299 if (cls[i] == id)
300 g[n++] = src[i];
301 qsort(g, n, sizeof(g[0]), (void *) intcmp);
302 return ggrp_make(g, n);
305 static int ggrp_coverage(int *g, int n)
307 qsort(g, n, sizeof(g[0]), (void *) intcmp);
308 return ggrp_make(g, n);
311 static int valuerecord_len(int fmt)
313 int off = 0;
314 int i;
315 for (i = 0; i < 8; i++)
316 if (fmt & (1 << i))
317 off += 2;
318 return off;
321 static void valuerecord_print(int fmt, void *rec)
323 int vals[8] = {0};
324 int off = 0;
325 int i;
326 for (i = 0; i < 8; i++) {
327 if (fmt & (1 << i)) {
328 vals[i] = uwid(S16(rec, off));
329 off += 2;
332 if (fmt)
333 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
336 static int valuerecord_small(int fmt, void *rec)
338 int off = 0;
339 int i;
340 for (i = 0; i < 8; i++) {
341 if (fmt & (1 << i)) {
342 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
343 return 0;
344 off += 2;
347 return 1;
350 /* single adjustment positioning */
351 static void otf_gpostype1(void *otf, void *sub, char *feat)
353 int fmt = U16(sub, 0);
354 int vfmt = U16(sub, 4);
355 int cov[NGLYPHS];
356 int ncov, nvals;
357 int vlen = valuerecord_len(vfmt);
358 int i;
359 ncov = coverage(sub + U16(sub, 2), cov);
360 if (fmt == 1) {
361 for (i = 0; i < ncov; i++) {
362 if (valuerecord_small(vfmt, sub + 6))
363 continue;
364 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
365 valuerecord_print(vfmt, sub + 6);
366 printf("\n");
369 if (fmt == 2) {
370 nvals = U16(sub, 6);
371 for (i = 0; i < nvals; i++) {
372 if (valuerecord_small(vfmt, sub + 6))
373 continue;
374 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
375 valuerecord_print(vfmt, sub + 8 + i * vlen);
376 printf("\n");
381 /* pair adjustment positioning */
382 static void otf_gpostype2(void *otf, void *sub, char *feat)
384 int fmt = U16(sub, 0);
385 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
386 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
387 int fmtoff1, fmtoff2;
388 int vrlen; /* the length of vfmt1 and vfmt2 */
389 int i, j;
390 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
391 if (fmt == 1) {
392 int cov[NGLYPHS];
393 int nc1 = U16(sub, 8);
394 coverage(sub + U16(sub, 2), cov);
395 for (i = 0; i < nc1; i++) {
396 void *c2 = sub + U16(sub, 10 + 2 * i);
397 int nc2 = U16(c2, 0);
398 for (j = 0; j < nc2; j++) {
399 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
400 fmtoff1 = 2 + (2 + vrlen) * j + 2;
401 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
402 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
403 valuerecord_small(vfmt2, c2 + fmtoff2))
404 continue;
405 printf("gpos %s 2", feat);
406 printf(" %s", glyph_name[cov[i]]);
407 valuerecord_print(vfmt1, c2 + fmtoff1);
408 printf(" %s", glyph_name[second]);
409 valuerecord_print(vfmt2, c2 + fmtoff2);
410 printf("\n");
414 if (fmt == 2) {
415 int gl1[NGLYPHS], gl2[NGLYPHS];
416 int cls1[NGLYPHS], cls2[NGLYPHS];
417 int grp1[NGLYPHS], grp2[NGLYPHS];
418 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
419 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
420 int ncls1 = U16(sub, 12);
421 int ncls2 = U16(sub, 14);
422 for (i = 0; i < ncls1; i++)
423 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
424 for (i = 0; i < ncls2; i++)
425 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
426 for (i = 0; i < ncls1; i++) {
427 for (j = 0; j < ncls2; j++) {
428 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
429 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
430 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
431 valuerecord_small(vfmt2, sub + fmtoff2))
432 continue;
433 printf("gpos %s %d", feat, 2);
434 printf(" @%d", grp1[i]);
435 valuerecord_print(vfmt1, sub + fmtoff1);
436 printf(" @%d", grp2[j]);
437 valuerecord_print(vfmt2, sub + fmtoff2);
438 printf("\n");
444 /* cursive attachment positioning */
445 static void otf_gpostype3(void *otf, void *sub, char *feat)
447 int fmt = U16(sub, 0);
448 int cov[NGLYPHS];
449 int icov[NGLYPHS];
450 int ocov[NGLYPHS];
451 int i, n;
452 int icnt = 0;
453 int ocnt = 0;
454 int igrp, ogrp;
455 coverage(sub + U16(sub, 2), cov);
456 if (fmt != 1)
457 return;
458 n = U16(sub, 4);
459 for (i = 0; i < n; i++)
460 if (U16(sub, 6 + 4 * i))
461 ocov[ocnt++] = cov[i];
462 for (i = 0; i < n; i++)
463 if (U16(sub, 6 + 4 * i + 2))
464 icov[icnt++] = cov[i];
465 igrp = ggrp_coverage(icov, icnt);
466 ogrp = ggrp_coverage(ocov, ocnt);
467 for (i = 0; i < n; i++) {
468 int prev = U16(sub, 6 + 4 * i);
469 int next = U16(sub, 6 + 4 * i + 2);
470 if (prev) {
471 int dx = -uwid(S16(sub, prev + 2));
472 int dy = -uwid(S16(sub, prev + 4));
473 if (otf_r2l(feat)) {
474 dx += uwid(glyph_wid[cov[i]]);
476 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
477 feat, igrp, glyph_name[cov[i]],
478 0, 0, dx, dy);
480 if (next) {
481 int dx = uwid(S16(sub, next + 2)) - uwid(glyph_wid[cov[i]]);
482 int dy = uwid(S16(sub, next + 4));
483 if (otf_r2l(feat)) {
484 dx += uwid(glyph_wid[cov[i]]);
486 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
487 feat, glyph_name[cov[i]], ogrp,
488 0, 0, dx, dy);
493 /* mark-to-base attachment positioning */
494 static void otf_gpostype4(void *otf, void *sub, char *feat)
496 int fmt = U16(sub, 0);
497 int mcov[NGLYPHS]; /* mark coverage */
498 int bcov[NGLYPHS]; /* base coverage */
499 int cgrp[1024]; /* glyph groups assigned to classes */
500 int bgrp; /* the group assigned to base glyphs */
501 int mcnt; /* mark coverage size */
502 int bcnt; /* base coverage size */
503 int ccnt; /* class count */
504 void *marks; /* mark array table */
505 void *bases; /* base array table */
506 int i, j;
507 if (fmt != 1)
508 return;
509 mcnt = coverage(sub + U16(sub, 2), mcov);
510 bcnt = coverage(sub + U16(sub, 4), bcov);
511 ccnt = U16(sub, 6);
512 marks = sub + U16(sub, 8);
513 bases = sub + U16(sub, 10);
514 bgrp = ggrp_coverage(bcov, bcnt);
515 for (i = 0; i < ccnt; i++) {
516 int grp[NGLYPHS];
517 int cnt = 0;
518 for (j = 0; j < mcnt; j++)
519 if (U16(marks, 2 + 4 * j) == i)
520 grp[cnt++] = mcov[j];
521 cgrp[i] = ggrp_coverage(grp, cnt);
523 for (i = 0; i < mcnt; i++) {
524 void *mark = marks + U16(marks, 2 + 4 * i + 2); /* mark anchor */
525 int dx = -uwid(S16(mark, 2));
526 int dy = -uwid(S16(mark, 4));
527 if (otf_r2l(feat)) {
528 dx += uwid(glyph_wid[mcov[i]]);
529 dy = -dy;
531 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
532 feat, bgrp, glyph_name[mcov[i]], dx, dy, 0, 0);
534 for (i = 0; i < bcnt; i++) {
535 for (j = 0; j < ccnt; j++) {
536 void *base = bases + U16(bases, 2 + ccnt * 2 * i + 2 * j);
537 int dx = uwid(S16(base, 2)) - uwid(glyph_wid[bcov[i]]);
538 int dy = uwid(S16(base, 4));
539 if (otf_r2l(feat)) {
540 dx += uwid(glyph_wid[bcov[i]]);
541 dy = -dy;
543 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
544 feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
549 /* gsub context */
550 struct gctx {
551 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
552 int igrp[GCTXLEN]; /* input coverage arrays */
553 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
554 int bn, in, ln; /* size of b[], i[], l[] */
555 int seqidx; /* sequence index */
558 static int gctx_len(struct gctx *ctx, int patlen)
560 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
563 static void gctx_backtrack(struct gctx *ctx)
565 int i;
566 if (!ctx)
567 return;
568 for (i = 0; i < ctx->bn; i++)
569 printf(" =@%d", ctx->bgrp[i]);
570 for (i = 0; i < ctx->seqidx; i++)
571 printf(" =@%d", ctx->igrp[i]);
574 static void gctx_lookahead(struct gctx *ctx, int patlen)
576 int i;
577 if (!ctx)
578 return;
579 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
580 printf(" =@%d", ctx->igrp[i]);
581 for (i = 0; i < ctx->ln; i++)
582 printf(" =@%d", ctx->lgrp[i]);
585 /* single substitution */
586 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
588 int cov[NGLYPHS];
589 int fmt = U16(sub, 0);
590 int ncov;
591 int i;
592 ncov = coverage(sub + U16(sub, 2), cov);
593 if (fmt == 1) {
594 for (i = 0; i < ncov; 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[cov[i] + S16(sub, 4)]);
599 gctx_lookahead(ctx, 1);
600 printf("\n");
603 if (fmt == 2) {
604 int n = U16(sub, 4);
605 for (i = 0; i < n; i++) {
606 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
607 gctx_backtrack(ctx);
608 printf(" -%s +%s", glyph_name[cov[i]],
609 glyph_name[U16(sub, 6 + 2 * i)]);
610 gctx_lookahead(ctx, 1);
611 printf("\n");
616 /* alternate substitution */
617 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
619 int cov[NGLYPHS];
620 int fmt = U16(sub, 0);
621 int n, i, j;
622 if (fmt != 1)
623 return;
624 coverage(sub + U16(sub, 2), cov);
625 n = U16(sub, 4);
626 for (i = 0; i < n; i++) {
627 void *alt = sub + U16(sub, 6 + 2 * i);
628 int nalt = U16(alt, 0);
629 for (j = 0; j < nalt; j++) {
630 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
631 gctx_backtrack(ctx);
632 printf(" -%s +%s", glyph_name[cov[i]],
633 glyph_name[U16(alt, 2 + 2 * j)]);
634 gctx_lookahead(ctx, 1);
635 printf("\n");
640 /* ligature substitution */
641 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
643 int fmt = U16(sub, 0);
644 int cov[NGLYPHS];
645 int n, i, j, k;
646 if (fmt != 1)
647 return;
648 coverage(sub + U16(sub, 2), cov);
649 n = U16(sub, 4);
650 for (i = 0; i < n; i++) {
651 void *set = sub + U16(sub, 6 + 2 * i);
652 int nset = U16(set, 0);
653 for (j = 0; j < nset; j++) {
654 void *lig = set + U16(set, 2 + 2 * j);
655 int nlig = U16(lig, 2);
656 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
657 gctx_backtrack(ctx);
658 printf(" -%s", glyph_name[cov[i]]);
659 for (k = 0; k < nlig - 1; k++)
660 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
661 printf(" +%s", glyph_name[U16(lig, 0)]);
662 gctx_lookahead(ctx, nlig);
663 printf("\n");
668 /* chaining contextual substitution */
669 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
671 struct gctx ctx = {{0}};
672 void *lookups = gsub + U16(gsub, 8);
673 int fmt = U16(sub, 0);
674 int cov[NGLYPHS];
675 int i, j, nsub, ncov;
676 int off = 2;
677 if (fmt != 3) {
678 otf_unsupported("GSUB", 6, fmt);
679 return;
681 ctx.bn = U16(sub, off);
682 for (i = 0; i < ctx.bn; i++) {
683 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
684 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
686 off += 2 + 2 * ctx.bn;
687 ctx.in = U16(sub, off);
688 for (i = 0; i < ctx.in; i++) {
689 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
690 ctx.igrp[i] = ggrp_coverage(cov, ncov);
692 off += 2 + 2 * ctx.in;
693 ctx.ln = U16(sub, off);
694 for (i = 0; i < ctx.ln; i ++) {
695 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
696 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
698 off += 2 + 2 * ctx.ln;
699 nsub = U16(sub, off); /* nsub > 1 is not supported */
700 for (i = 0; i < nsub && i < 1; i++) {
701 int lidx = U16(sub, off + 2 + 4 * i + 2);
702 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
703 int ltype = U16(lookup, 0);
704 int ntabs = U16(lookup, 4);
705 ctx.seqidx = U16(sub, off + 2 + 4 * i);
706 for (j = 0; j < ntabs; j++) {
707 void *tab = lookup + U16(lookup, 6 + 2 * j);
708 int type = ltype;
709 if (type == 7) { /* extension substitution */
710 type = U16(tab, 2);
711 tab = tab + U32(tab, 4);
713 if (type == 1)
714 otf_gsubtype1(otf, tab, feat, &ctx);
715 if (type == 3)
716 otf_gsubtype3(otf, tab, feat, &ctx);
717 if (type == 4)
718 otf_gsubtype4(otf, tab, feat, &ctx);
723 /* an otf gsub/gpos lookup */
724 struct otflookup {
725 char scrp[8]; /* script name */
726 char feat[8]; /* feature name */
727 int lookup; /* index into the lookup table */
730 /* parse the given gsub/gpos feature table */
731 static int otf_featrec(void *otf, void *gtab, void *featrec, char *script, struct otflookup *lookups)
733 void *feats = gtab + U16(gtab, 6);
734 void *feat = feats + U16(featrec, 4);
735 int nlookups = U16(feat, 2);
736 int i;
737 for (i = 0; i < nlookups; i++) {
738 memcpy(lookups[i].feat, featrec, 4);
739 lookups[i].feat[4] = '\0';
740 strcpy(lookups[i].scrp, script);
741 lookups[i].lookup = U16(feat, 4 + 2 * i);
743 return nlookups;
746 /* parse the given language table and its feature tables */
747 static int otf_lang(void *otf, void *gtab, void *lang, char *script, struct otflookup *lookups)
749 void *feats = gtab + U16(gtab, 6);
750 int featidx = U16(lang, 2);
751 int nfeat = U16(lang, 4);
752 int n = 0;
753 int i;
754 if (featidx != 0xffff)
755 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, script, lookups + n);
756 for (i = 0; i < nfeat; i++)
757 n += otf_featrec(otf, gtab,
758 feats + 2 + 6 * U16(lang, 6 + 2 * i), script, lookups + n);
759 return n;
762 static int lookupcmp(void *v1, void *v2)
764 struct otflookup *l1 = v1;
765 struct otflookup *l2 = v2;
766 if (strcmp(l1->scrp, l2->scrp))
767 return strcmp(l1->scrp, l2->scrp);
768 if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
769 return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
770 return l1->lookup - l2->lookup;
773 /* extract lookup tables for all features of the given gsub/gpos table */
774 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
776 void *scripts = gpos + U16(gpos, 4);
777 int nscripts, nlangs;
778 void *script;
779 char stag[8], ltag[8]; /* script and language tags */
780 int i, j;
781 int n = 0;
782 nscripts = U16(scripts, 0);
783 for (i = 0; i < nscripts; i++) {
784 void *grec = scripts + 2 + 6 * i;
785 memcpy(stag, grec, 4);
786 stag[4] = '\0';
787 if (!trfn_script(stag, nscripts))
788 continue;
789 script = scripts + U16(grec, 4);
790 nlangs = U16(script, 2);
791 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
792 n += otf_lang(otf, gpos, script + U16(script, 0),
793 stag, lookups + n);
794 for (j = 0; j < nlangs; j++) {
795 void *lrec = script + 4 + 6 * j;
796 memcpy(ltag, lrec, 4);
797 ltag[4] = '\0';
798 if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
799 n += otf_lang(otf, gpos, script + U16(lrec, 4),
800 stag, lookups + n);
803 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
804 return n;
807 static void otf_gpos(void *otf, void *gpos)
809 struct otflookup lookups[NLOOKUPS];
810 void *lookuplist = gpos + U16(gpos, 8);
811 int nlookups = otf_gtab(otf, gpos, lookups);
812 char tag[16];
813 int i, j;
814 for (i = 0; i < nlookups; i++) {
815 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
816 int ltype = U16(lookup, 0);
817 int ntabs = U16(lookup, 4);
818 sprintf(tag, "%s:%s", lookups[i].feat,
819 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
820 for (j = 0; j < ntabs; j++) {
821 void *tab = lookup + U16(lookup, 6 + 2 * j);
822 int type = ltype;
823 if (type == 9) { /* extension positioning */
824 type = U16(tab, 2);
825 tab = tab + U32(tab, 4);
827 switch (type) {
828 case 1:
829 otf_gpostype1(otf, tab, tag);
830 break;
831 case 2:
832 otf_gpostype2(otf, tab, tag);
833 break;
834 case 3:
835 otf_gpostype3(otf, tab, tag);
836 break;
837 case 4:
838 otf_gpostype4(otf, tab, tag);
839 break;
840 default:
841 otf_unsupported("GPOS", type, 0);
847 static void otf_gsub(void *otf, void *gsub)
849 struct otflookup lookups[NLOOKUPS];
850 void *lookuplist = gsub + U16(gsub, 8);
851 int nlookups = otf_gtab(otf, gsub, lookups);
852 char tag[16];
853 int i, j;
854 for (i = 0; i < nlookups; i++) {
855 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
856 int ltype = U16(lookup, 0);
857 int ntabs = U16(lookup, 4);
858 sprintf(tag, "%s:%s", lookups[i].feat,
859 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
860 for (j = 0; j < ntabs; j++) {
861 void *tab = lookup + U16(lookup, 6 + 2 * j);
862 int type = ltype;
863 if (type == 7) { /* extension substitution */
864 type = U16(tab, 2);
865 tab = tab + U32(tab, 4);
867 switch (type) {
868 case 1:
869 otf_gsubtype1(otf, tab, tag, NULL);
870 break;
871 case 3:
872 otf_gsubtype3(otf, tab, tag, NULL);
873 break;
874 case 4:
875 otf_gsubtype4(otf, tab, tag, NULL);
876 break;
877 case 6:
878 otf_gsubtype6(otf, tab, tag, gsub);
879 break;
880 default:
881 otf_unsupported("GSUB", type, 0);
887 static void *otf_input(int fd)
889 struct sbuf *sb = sbuf_make();
890 char buf[1 << 12];
891 int nr = 0;
892 while ((nr = read(fd, buf, sizeof(buf))) > 0)
893 sbuf_mem(sb, buf, nr);
894 return sbuf_done(sb);
897 static char *otf_buf;
899 int otf_read(void)
901 int i;
902 otf_buf = otf_input(0);
903 upm = U16(otf_table(otf_buf, "head"), 18);
904 otf_name(otf_buf, otf_table(otf_buf, "name"));
905 otf_cmap(otf_buf, otf_table(otf_buf, "cmap"));
906 otf_post(otf_buf, otf_table(otf_buf, "post"));
907 if (otf_table(otf_buf, "glyf"))
908 otf_glyf(otf_buf, otf_table(otf_buf, "glyf"));
909 otf_hmtx(otf_buf, otf_table(otf_buf, "hmtx"));
910 for (i = 0; i < glyph_n; i++) {
911 trfn_char(glyph_name[i], -1,
912 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
913 owid(glyph_wid[i]),
914 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
915 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
917 if (otf_table(otf_buf, "kern"))
918 otf_kern(otf_buf, otf_table(otf_buf, "kern"));
919 return 0;
922 void otf_feat(int r, int k, int w)
924 res = r;
925 kmin = k;
926 warn = w;
927 if (otf_table(otf_buf, "GSUB"))
928 otf_gsub(otf_buf, otf_table(otf_buf, "GSUB"));
929 if (otf_table(otf_buf, "GPOS"))
930 otf_gpos(otf_buf, otf_table(otf_buf, "GPOS"));
933 /* glyph groups */
934 static int *ggrp_g[NGRPS];
935 static int ggrp_len[NGRPS];
936 static int ggrp_n;
938 static int ggrp_find(int *src, int n)
940 int i, j;
941 for (i = 0; i < ggrp_n; i++) {
942 if (ggrp_len[i] == n) {
943 for (j = 0; j < n; j++)
944 if (src[j] != ggrp_g[i][j])
945 break;
946 if (j == n)
947 return i;
950 return -1;
953 static int ggrp_make(int *src, int n)
955 int id = ggrp_find(src, n);
956 int i;
957 if (id >= 0)
958 return id;
959 id = ggrp_n++;
960 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
961 ggrp_len[id] = n;
962 for (i = 0; i < n; i++)
963 ggrp_g[id][i] = src[i];
964 printf("ggrp %d %d", id, n);
965 for (i = 0; i < n; i++)
966 printf(" %s", glyph_name[src[i]]);
967 printf("\n");
968 return id;
971 static char *macset[] = {
972 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
973 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
974 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
975 "comma", "hyphen", "period", "slash", "zero",
976 "one", "two", "three", "four", "five",
977 "six", "seven", "eight", "nine", "colon",
978 "semicolon", "less", "equal", "greater", "question",
979 "at", "A", "B", "C", "D",
980 "E", "F", "G", "H", "I",
981 "J", "K", "L", "M", "N",
982 "O", "P", "Q", "R", "S",
983 "T", "U", "V", "W", "X",
984 "Y", "Z", "bracketleft", "backslash", "bracketright",
985 "asciicircum", "underscore", "grave", "a", "b",
986 "c", "d", "e", "f", "g",
987 "h", "i", "j", "k", "l",
988 "m", "n", "o", "p", "q",
989 "r", "s", "t", "u", "v",
990 "w", "x", "y", "z", "braceleft",
991 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
992 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
993 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
994 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
995 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
996 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
997 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
998 "dagger", "degree", "cent", "sterling", "section",
999 "bullet", "paragraph", "germandbls", "registered", "copyright",
1000 "trademark", "acute", "dieresis", "notequal", "AE",
1001 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1002 "yen", "mu", "partialdiff", "summation", "product",
1003 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1004 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1005 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1006 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1007 "Otilde", "OE", "oe", "endash", "emdash",
1008 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1009 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1010 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1011 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1012 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1013 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1014 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1015 "dotlessi", "circumflex", "tilde", "macron", "breve",
1016 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1017 "caron", "Lslash", "lslash", "Scaron", "scaron",
1018 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1019 "Yacute", "yacute", "Thorn", "thorn", "minus",
1020 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1021 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1022 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1023 "Ccaron", "ccaron", "dcroat",