otf: for each rule report its script
[neatmkfn.git] / otf.c
blob666c9ee86d72cde736ae205c0d27360229882138
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; /* report unsupported tables */
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 /* weather the script is right-to-left */
54 static int otf_r2l(char *feat)
56 char *scrp = strchr(feat, ':') + 1;
57 return !strcmp("arab", scrp) || !strcmp("hebr", scrp);
60 /* report unsupported otf tables */
61 static void otf_unsupported(char *sub, int type, int fmt)
63 if (warn) {
64 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
65 if (fmt > 0)
66 fprintf(stderr, " format %d", fmt);
67 fprintf(stderr, "\n");
71 /* find the otf table with the given name */
72 static void *otf_table(void *otf, char *name)
74 int nrecs = U16(otf, 4);
75 int i;
76 for (i = 0; i < nrecs; i++) {
77 void *rec = otf + 12 + i * 16; /* an otf table record */
78 if (!strncmp(rec, name, 4))
79 return otf + U32(rec, 8);
81 return NULL;
84 /* obtain postscript font name from name table */
85 static void otf_name(void *otf, void *tab)
87 char name[256];
88 void *str = tab + U16(tab, 4); /* storage area */
89 int n = U16(tab, 2); /* number of name records */
90 int i;
91 for (i = 0; i < n; i++) {
92 void *rec = tab + 6 + 12 * i;
93 int pid = U16(rec, 0); /* platform id */
94 int eid = U16(rec, 2); /* encoding id */
95 int lid = U16(rec, 4); /* language id */
96 int nid = U16(rec, 6); /* name id */
97 int len = U16(rec, 8); /* string length */
98 int off = U16(rec, 10); /* string offset */
99 if (pid == 1 && eid == 0 && lid == 0 && nid == 6) {
100 memcpy(name, str + off, len);
101 name[len] = '\0';
102 trfn_psfont(name);
107 /* parse otf cmap format 4 subtable */
108 static void otf_cmap4(void *otf, void *cmap4)
110 int nsegs;
111 void *ends, *begs, *deltas, *offsets;
112 int beg, end, delta, offset;
113 int i, j;
114 nsegs = U16(cmap4, 6) / 2;
115 ends = cmap4 + 14;
116 begs = ends + 2 * nsegs + 2;
117 deltas = begs + 2 * nsegs;
118 offsets = deltas + 2 * nsegs;
119 for (i = 0; i < nsegs; i++) {
120 beg = U16(begs, 2 * i);
121 end = U16(ends, 2 * i);
122 delta = U16(deltas, 2 * i);
123 offset = U16(offsets, 2 * i);
124 if (offset) {
125 for (j = beg; j <= end; j++)
126 glyph_code[(U16(offsets + 2 * i,
127 offset + (j - beg) * 2) + delta) & 0xffff] = j;
128 } else {
129 for (j = beg; j <= end; j++)
130 glyph_code[(j + delta) & 0xffff] = j;
135 /* parse otf cmap header */
136 static void otf_cmap(void *otf, void *cmap)
138 int nrecs = U16(cmap, 2);
139 int i;
140 for (i = 0; i < nrecs; i++) {
141 void *rec = cmap + 4 + i * 8; /* a cmap record */
142 int plat = U16(rec, 0);
143 int enc = U16(rec, 2);
144 void *tab = cmap + U32(rec, 4); /* a cmap subtable */
145 int fmt = U16(tab, 0);
146 if (plat == 3 && enc == 1 && fmt == 4)
147 otf_cmap4(otf, tab);
151 static void otf_post(void *otf, void *post)
153 void *post2; /* version 2.0 header */
154 void *index; /* glyph name indices */
155 void *names; /* glyph names */
156 int cname = 0;
157 int i;
158 if (U32(post, 0) != 0x00020000)
159 return;
160 post2 = post + 32;
161 glyph_n = U16(post2, 0);
162 index = post2 + 2;
163 names = index + 2 * glyph_n;
164 for (i = 0; i < glyph_n; i++) {
165 int idx = U16(index, 2 * i);
166 if (idx <= 257) {
167 strcpy(glyph_name[i], macset[idx]);
168 } else {
169 memcpy(glyph_name[i], names + cname + 1,
170 U8(names, cname));
171 glyph_name[i][U8(names, cname)] = '\0';
172 cname += U8(names, cname) + 1;
177 static void otf_glyf(void *otf, void *glyf)
179 void *maxp = otf_table(otf, "maxp");
180 void *head = otf_table(otf, "head");
181 void *loca = otf_table(otf, "loca");
182 void *gdat;
183 void *gdat_next;
184 int n = U16(maxp, 4);
185 int fmt = U16(head, 50);
186 int i, j;
187 for (i = 0; i < n; i++) {
188 if (fmt) {
189 gdat = glyf + U32(loca, 4 * i);
190 gdat_next = glyf + U32(loca, 4 * (i + 1));
191 } else {
192 gdat = glyf + U16(loca, 2 * i) * 2;
193 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
195 if (gdat < gdat_next)
196 for (j = 0; j < 4; j++)
197 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
201 static void otf_hmtx(void *otf, void *hmtx)
203 void *hhea = otf_table(otf, "hhea");
204 int n;
205 int i;
206 n = U16(hhea, 34);
207 for (i = 0; i < n; i++)
208 glyph_wid[i] = U16(hmtx, i * 4);
209 for (i = n; i < glyph_n; i++)
210 glyph_wid[i] = glyph_wid[n - 1];
213 static void otf_kern(void *otf, void *kern)
215 int off = 4;
216 int i, j;
217 int n = U16(kern, 2); /* number of kern subtables */
218 for (i = 0; i < n; i++) {
219 void *tab = kern + off; /* a kern subtable */
220 int cov = U16(tab, 4);
221 off += U16(tab, 2);
222 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
223 int npairs = U16(tab, 6);
224 for (j = 0; j < npairs; j++) {
225 int c1 = U16(tab, 14 + 6 * j);
226 int c2 = U16(tab, 14 + 6 * j + 2);
227 int val = S16(tab, 14 + 6 * j + 4);
228 trfn_kern(glyph_name[c1], glyph_name[c2],
229 owid(val));
235 static int coverage(void *cov, int *out)
237 int fmt = U16(cov, 0);
238 int n = U16(cov, 2);
239 int beg, end;
240 int ncov = 0;
241 int i, j;
242 if (fmt == 1) {
243 for (i = 0; i < n; i++)
244 out[ncov++] = U16(cov, 4 + 2 * i);
246 if (fmt == 2) {
247 for (i = 0; i < n; i++) {
248 beg = U16(cov, 4 + 6 * i);
249 end = U16(cov, 4 + 6 * i + 2);
250 for (j = beg; j <= end; j++)
251 out[ncov++] = j;
254 return ncov;
257 static int classdef(void *tab, int *gl, int *cls)
259 int fmt = U16(tab, 0);
260 int ngl = 0;
261 int i, j;
262 if (fmt == 1) {
263 int beg = U16(tab, 2);
264 ngl = U16(tab, 4);
265 for (i = 0; i < ngl; i++) {
266 gl[i] = beg + i;
267 cls[i] = U16(tab, 6 + 2 * i);
270 if (fmt == 2) {
271 int n = U16(tab, 2);
272 for (i = 0; i < n; i++) {
273 int beg = U16(tab, 4 + 6 * i);
274 int end = U16(tab, 4 + 6 * i + 2);
275 for (j = beg; j <= end; j++) {
276 gl[ngl] = j;
277 cls[ngl] = U16(tab, 4 + 6 * i + 4);
278 ngl++;
282 return ngl;
285 static int intcmp(void *v1, void *v2)
287 return *(int *) v1 - *(int *) v2;
290 int ggrp_make(int *src, int n);
292 static int ggrp_class(int *src, int *cls, int nsrc, int id)
294 int g[NGLYPHS];
295 int n = 0;
296 int i;
297 for (i = 0; i < nsrc; i++)
298 if (cls[i] == id)
299 g[n++] = src[i];
300 qsort(g, n, sizeof(g[0]), (void *) intcmp);
301 return ggrp_make(g, n);
304 static int ggrp_coverage(int *g, int n)
306 qsort(g, n, sizeof(g[0]), (void *) intcmp);
307 return ggrp_make(g, n);
310 static int valuerecord_len(int fmt)
312 int off = 0;
313 int i;
314 for (i = 0; i < 8; i++)
315 if (fmt & (1 << i))
316 off += 2;
317 return off;
320 static void valuerecord_print(int fmt, void *rec)
322 int vals[8] = {0};
323 int off = 0;
324 int i;
325 for (i = 0; i < 8; i++) {
326 if (fmt & (1 << i)) {
327 vals[i] = uwid(S16(rec, off));
328 off += 2;
331 if (fmt)
332 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
335 static int valuerecord_small(int fmt, void *rec)
337 int off = 0;
338 int i;
339 for (i = 0; i < 8; i++) {
340 if (fmt & (1 << i)) {
341 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
342 return 0;
343 off += 2;
346 return 1;
349 /* single adjustment positioning */
350 static void otf_gpostype1(void *otf, void *sub, char *feat)
352 int fmt = U16(sub, 0);
353 int vfmt = U16(sub, 4);
354 int cov[NGLYPHS];
355 int ncov, nvals;
356 int vlen = valuerecord_len(vfmt);
357 int i;
358 ncov = coverage(sub + U16(sub, 2), cov);
359 if (fmt == 1) {
360 for (i = 0; i < ncov; i++) {
361 if (valuerecord_small(vfmt, sub + 6))
362 continue;
363 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
364 valuerecord_print(vfmt, sub + 6);
365 printf("\n");
368 if (fmt == 2) {
369 nvals = U16(sub, 6);
370 for (i = 0; i < nvals; i++) {
371 if (valuerecord_small(vfmt, sub + 6))
372 continue;
373 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
374 valuerecord_print(vfmt, sub + 8 + i * vlen);
375 printf("\n");
380 /* pair adjustment positioning */
381 static void otf_gpostype2(void *otf, void *sub, char *feat)
383 int fmt = U16(sub, 0);
384 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
385 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
386 int fmtoff1, fmtoff2;
387 int vrlen; /* the length of vfmt1 and vfmt2 */
388 int i, j;
389 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
390 if (fmt == 1) {
391 int cov[NGLYPHS];
392 int nc1 = U16(sub, 8);
393 coverage(sub + U16(sub, 2), cov);
394 for (i = 0; i < nc1; i++) {
395 void *c2 = sub + U16(sub, 10 + 2 * i);
396 int nc2 = U16(c2, 0);
397 for (j = 0; j < nc2; j++) {
398 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
399 fmtoff1 = 2 + (2 + vrlen) * j + 2;
400 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
401 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
402 valuerecord_small(vfmt2, c2 + fmtoff2))
403 continue;
404 printf("gpos %s 2", feat);
405 printf(" %s", glyph_name[cov[i]]);
406 valuerecord_print(vfmt1, c2 + fmtoff1);
407 printf(" %s", glyph_name[second]);
408 valuerecord_print(vfmt2, c2 + fmtoff2);
409 printf("\n");
413 if (fmt == 2) {
414 int gl1[NGLYPHS], gl2[NGLYPHS];
415 int cls1[NGLYPHS], cls2[NGLYPHS];
416 int grp1[NGLYPHS], grp2[NGLYPHS];
417 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
418 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
419 int ncls1 = U16(sub, 12);
420 int ncls2 = U16(sub, 14);
421 for (i = 0; i < ncls1; i++)
422 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
423 for (i = 0; i < ncls2; i++)
424 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
425 for (i = 0; i < ncls1; i++) {
426 for (j = 0; j < ncls2; j++) {
427 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
428 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
429 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
430 valuerecord_small(vfmt2, sub + fmtoff2))
431 continue;
432 printf("gpos %s %d", feat, 2);
433 printf(" @%d", grp1[i]);
434 valuerecord_print(vfmt1, sub + fmtoff1);
435 printf(" @%d", grp2[j]);
436 valuerecord_print(vfmt2, sub + fmtoff2);
437 printf("\n");
443 /* cursive attachment positioning */
444 static void otf_gpostype3(void *otf, void *sub, char *feat)
446 int fmt = U16(sub, 0);
447 int cov[NGLYPHS];
448 int i, n;
449 coverage(sub + U16(sub, 2), cov);
450 if (fmt != 1)
451 return;
452 n = U16(sub, 4);
453 for (i = 0; i < n; i++) {
454 int prev = U16(sub, 6 + 4 * i);
455 int next = U16(sub, 6 + 4 * i + 2);
456 printf("gcur %s %s", feat, glyph_name[cov[i]]);
457 if (prev)
458 printf(" %d %d", uwid(S16(sub, prev + 2)),
459 uwid(S16(sub, prev + 4)));
460 else
461 printf(" - -");
462 if (next)
463 printf(" %d %d", uwid(S16(sub, next + 2)),
464 uwid(S16(sub, next + 4)));
465 else
466 printf(" - -");
467 printf("\n");
471 /* mark-to-base attachment positioning */
472 static void otf_gpostype4(void *otf, void *sub, char *feat)
474 int fmt = U16(sub, 0);
475 int mcov[NGLYPHS]; /* mark coverage */
476 int bcov[NGLYPHS]; /* base coverage */
477 int cgrp[1024]; /* glyph groups assigned to classes */
478 int bgrp; /* the group assigned to base glyphs */
479 int mcnt; /* mark coverage size */
480 int bcnt; /* base coverage size */
481 int ccnt; /* class count */
482 void *marks; /* mark array table */
483 void *bases; /* base array table */
484 int i, j;
485 if (fmt != 1)
486 return;
487 mcnt = coverage(sub + U16(sub, 2), mcov);
488 bcnt = coverage(sub + U16(sub, 4), bcov);
489 ccnt = U16(sub, 6);
490 marks = sub + U16(sub, 8);
491 bases = sub + U16(sub, 10);
492 bgrp = ggrp_coverage(bcov, bcnt);
493 for (i = 0; i < ccnt; i++) {
494 int grp[NGLYPHS];
495 int cnt = 0;
496 for (j = 0; j < mcnt; j++)
497 if (U16(marks, 2 + 4 * j) == i)
498 grp[cnt++] = mcov[j];
499 cgrp[i] = ggrp_coverage(grp, cnt);
501 for (i = 0; i < mcnt; i++) {
502 void *mark = marks + U16(marks, 2 + 4 * i + 2); /* mark anchor */
503 int dx = -uwid(S16(mark, 2));
504 int dy = -uwid(S16(mark, 4));
505 if (otf_r2l(feat)) {
506 dx += uwid(glyph_wid[mcov[i]]);
507 dy = -dy;
509 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
510 feat, bgrp, glyph_name[mcov[i]], dx, dy, 0, 0);
512 for (i = 0; i < bcnt; i++) {
513 for (j = 0; j < ccnt; j++) {
514 void *base = bases + U16(bases, 2 + ccnt * 2 * i + 2 * j);
515 int dx = uwid(S16(base, 2)) - uwid(glyph_wid[bcov[i]]);
516 int dy = uwid(S16(base, 4));
517 if (otf_r2l(feat)) {
518 dx += uwid(glyph_wid[bcov[i]]);
519 dy = -dy;
521 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
522 feat, glyph_name[bcov[i]], cgrp[j], dx, dy, 0, 0);
527 /* gsub context */
528 struct gctx {
529 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
530 int igrp[GCTXLEN]; /* input coverage arrays */
531 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
532 int bn, in, ln; /* size of b[], i[], l[] */
533 int seqidx; /* sequence index */
536 static int gctx_len(struct gctx *ctx, int patlen)
538 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
541 static void gctx_backtrack(struct gctx *ctx)
543 int i;
544 if (!ctx)
545 return;
546 for (i = 0; i < ctx->bn; i++)
547 printf(" =@%d", ctx->bgrp[i]);
548 for (i = 0; i < ctx->seqidx; i++)
549 printf(" =@%d", ctx->igrp[i]);
552 static void gctx_lookahead(struct gctx *ctx, int patlen)
554 int i;
555 if (!ctx)
556 return;
557 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
558 printf(" =@%d", ctx->igrp[i]);
559 for (i = 0; i < ctx->ln; i++)
560 printf(" =@%d", ctx->lgrp[i]);
563 /* single substitution */
564 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
566 int cov[NGLYPHS];
567 int fmt = U16(sub, 0);
568 int ncov;
569 int i;
570 ncov = coverage(sub + U16(sub, 2), cov);
571 if (fmt == 1) {
572 for (i = 0; i < ncov; i++) {
573 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
574 gctx_backtrack(ctx);
575 printf(" -%s +%s", glyph_name[cov[i]],
576 glyph_name[cov[i] + S16(sub, 4)]);
577 gctx_lookahead(ctx, 1);
578 printf("\n");
581 if (fmt == 2) {
582 int n = U16(sub, 4);
583 for (i = 0; i < n; 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[U16(sub, 6 + 2 * i)]);
588 gctx_lookahead(ctx, 1);
589 printf("\n");
594 /* alternate substitution */
595 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
597 int cov[NGLYPHS];
598 int fmt = U16(sub, 0);
599 int n, i, j;
600 if (fmt != 1)
601 return;
602 coverage(sub + U16(sub, 2), cov);
603 n = U16(sub, 4);
604 for (i = 0; i < n; i++) {
605 void *alt = sub + U16(sub, 6 + 2 * i);
606 int nalt = U16(alt, 0);
607 for (j = 0; j < nalt; j++) {
608 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
609 gctx_backtrack(ctx);
610 printf(" -%s +%s", glyph_name[cov[i]],
611 glyph_name[U16(alt, 2 + 2 * j)]);
612 gctx_lookahead(ctx, 1);
613 printf("\n");
618 /* ligature substitution */
619 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
621 int fmt = U16(sub, 0);
622 int cov[NGLYPHS];
623 int n, i, j, k;
624 if (fmt != 1)
625 return;
626 coverage(sub + U16(sub, 2), cov);
627 n = U16(sub, 4);
628 for (i = 0; i < n; i++) {
629 void *set = sub + U16(sub, 6 + 2 * i);
630 int nset = U16(set, 0);
631 for (j = 0; j < nset; j++) {
632 void *lig = set + U16(set, 2 + 2 * j);
633 int nlig = U16(lig, 2);
634 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
635 gctx_backtrack(ctx);
636 printf(" -%s", glyph_name[cov[i]]);
637 for (k = 0; k < nlig - 1; k++)
638 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
639 printf(" +%s", glyph_name[U16(lig, 0)]);
640 gctx_lookahead(ctx, nlig);
641 printf("\n");
646 /* chaining contextual substitution */
647 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
649 struct gctx ctx = {{0}};
650 void *lookups = gsub + U16(gsub, 8);
651 int fmt = U16(sub, 0);
652 int cov[NGLYPHS];
653 int i, j, nsub, ncov;
654 int off = 2;
655 if (fmt != 3) {
656 otf_unsupported("GSUB", 6, fmt);
657 return;
659 ctx.bn = U16(sub, off);
660 for (i = 0; i < ctx.bn; i++) {
661 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
662 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
664 off += 2 + 2 * ctx.bn;
665 ctx.in = U16(sub, off);
666 for (i = 0; i < ctx.in; i++) {
667 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
668 ctx.igrp[i] = ggrp_coverage(cov, ncov);
670 off += 2 + 2 * ctx.in;
671 ctx.ln = U16(sub, off);
672 for (i = 0; i < ctx.ln; i ++) {
673 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
674 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
676 off += 2 + 2 * ctx.ln;
677 nsub = U16(sub, off); /* nsub > 1 is not supported */
678 for (i = 0; i < nsub && i < 1; i++) {
679 int lidx = U16(sub, off + 2 + 4 * i + 2);
680 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
681 int ltype = U16(lookup, 0);
682 int ntabs = U16(lookup, 4);
683 ctx.seqidx = U16(sub, off + 2 + 4 * i);
684 for (j = 0; j < ntabs; j++) {
685 void *tab = lookup + U16(lookup, 6 + 2 * j);
686 int type = ltype;
687 if (type == 7) { /* extension substitution */
688 type = U16(tab, 2);
689 tab = tab + U32(tab, 4);
691 if (type == 1)
692 otf_gsubtype1(otf, tab, feat, &ctx);
693 if (type == 3)
694 otf_gsubtype3(otf, tab, feat, &ctx);
695 if (type == 4)
696 otf_gsubtype4(otf, tab, feat, &ctx);
701 /* an otf gsub/gpos lookup */
702 struct otflookup {
703 char scrp[8]; /* script name */
704 char feat[8]; /* feature name */
705 int lookup; /* index into the lookup table */
708 /* parse the given gsub/gpos feature table */
709 static int otf_featrec(void *otf, void *gtab, void *featrec, char *script, struct otflookup *lookups)
711 void *feats = gtab + U16(gtab, 6);
712 void *feat = feats + U16(featrec, 4);
713 int nlookups = U16(feat, 2);
714 int i;
715 for (i = 0; i < nlookups; i++) {
716 memcpy(lookups[i].feat, featrec, 4);
717 lookups[i].feat[4] = '\0';
718 strcpy(lookups[i].scrp, script);
719 lookups[i].lookup = U16(feat, 4 + 2 * i);
721 return nlookups;
724 /* parse the given language table and its feature tables */
725 static int otf_lang(void *otf, void *gtab, void *lang, char *script, struct otflookup *lookups)
727 void *feats = gtab + U16(gtab, 6);
728 int featidx = U16(lang, 2);
729 int nfeat = U16(lang, 4);
730 int n = 0;
731 int i;
732 if (featidx != 0xffff)
733 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, script, lookups + n);
734 for (i = 0; i < nfeat; i++)
735 n += otf_featrec(otf, gtab,
736 feats + 2 + 6 * U16(lang, 6 + 2 * i), script, lookups + n);
737 return n;
740 static int lookupcmp(void *v1, void *v2)
742 struct otflookup *l1 = v1;
743 struct otflookup *l2 = v2;
744 if (strcmp(l1->scrp, l2->scrp))
745 return strcmp(l1->scrp, l2->scrp);
746 if (trfn_featrank(l1->scrp, l1->feat) != trfn_featrank(l1->scrp, l2->feat))
747 return trfn_featrank(l1->scrp, l1->feat) - trfn_featrank(l1->scrp, l2->feat);
748 return l1->lookup - l2->lookup;
751 /* extract lookup tables for all features of the given gsub/gpos table */
752 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
754 void *scripts = gpos + U16(gpos, 4);
755 int nscripts, nlangs;
756 void *script;
757 char stag[8], ltag[8]; /* script and language tags */
758 int i, j;
759 int n = 0;
760 nscripts = U16(scripts, 0);
761 for (i = 0; i < nscripts; i++) {
762 void *grec = scripts + 2 + 6 * i;
763 memcpy(stag, grec, 4);
764 stag[4] = '\0';
765 if (!trfn_script(stag, nscripts))
766 continue;
767 script = scripts + U16(grec, 4);
768 nlangs = U16(script, 2);
769 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
770 n += otf_lang(otf, gpos, script + U16(script, 0),
771 stag, lookups + n);
772 for (j = 0; j < nlangs; j++) {
773 void *lrec = script + 4 + 6 * j;
774 memcpy(ltag, lrec, 4);
775 ltag[4] = '\0';
776 if (trfn_lang(ltag, nlangs + (U16(script, 0) != 0)))
777 n += otf_lang(otf, gpos, script + U16(lrec, 4),
778 stag, lookups + n);
781 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
782 return n;
785 static void otf_gpos(void *otf, void *gpos)
787 struct otflookup lookups[NLOOKUPS];
788 void *lookuplist = gpos + U16(gpos, 8);
789 int nlookups = otf_gtab(otf, gpos, lookups);
790 char tag[16];
791 int i, j;
792 for (i = 0; i < nlookups; i++) {
793 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
794 int ltype = U16(lookup, 0);
795 int ntabs = U16(lookup, 4);
796 sprintf(tag, "%s:%s", lookups[i].feat,
797 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
798 for (j = 0; j < ntabs; j++) {
799 void *tab = lookup + U16(lookup, 6 + 2 * j);
800 int type = ltype;
801 if (type == 9) { /* extension positioning */
802 type = U16(tab, 2);
803 tab = tab + U32(tab, 4);
805 switch (type) {
806 case 1:
807 otf_gpostype1(otf, tab, tag);
808 break;
809 case 2:
810 otf_gpostype2(otf, tab, tag);
811 break;
812 case 3:
813 otf_gpostype3(otf, tab, tag);
814 break;
815 case 4:
816 otf_gpostype4(otf, tab, tag);
817 break;
818 default:
819 otf_unsupported("GPOS", type, 0);
825 static void otf_gsub(void *otf, void *gsub)
827 struct otflookup lookups[NLOOKUPS];
828 void *lookuplist = gsub + U16(gsub, 8);
829 int nlookups = otf_gtab(otf, gsub, lookups);
830 char tag[16];
831 int i, j;
832 for (i = 0; i < nlookups; i++) {
833 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
834 int ltype = U16(lookup, 0);
835 int ntabs = U16(lookup, 4);
836 sprintf(tag, "%s:%s", lookups[i].feat,
837 lookups[i].scrp[0] ? lookups[i].scrp : "DFLT");
838 for (j = 0; j < ntabs; j++) {
839 void *tab = lookup + U16(lookup, 6 + 2 * j);
840 int type = ltype;
841 if (type == 7) { /* extension substitution */
842 type = U16(tab, 2);
843 tab = tab + U32(tab, 4);
845 switch (type) {
846 case 1:
847 otf_gsubtype1(otf, tab, tag, NULL);
848 break;
849 case 3:
850 otf_gsubtype3(otf, tab, tag, NULL);
851 break;
852 case 4:
853 otf_gsubtype4(otf, tab, tag, NULL);
854 break;
855 case 6:
856 otf_gsubtype6(otf, tab, tag, gsub);
857 break;
858 default:
859 otf_unsupported("GSUB", type, 0);
865 static int xread(int fd, char *buf, int len)
867 int nr = 0;
868 while (nr < len) {
869 int ret = read(fd, buf + nr, len - nr);
870 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
871 continue;
872 if (ret <= 0)
873 break;
874 nr += ret;
876 return nr;
879 static char buf[BUFLEN];
881 int otf_read(void)
883 int i;
884 if (xread(0, buf, sizeof(buf)) <= 0)
885 return 1;
886 upm = U16(otf_table(buf, "head"), 18);
887 otf_name(buf, otf_table(buf, "name"));
888 otf_cmap(buf, otf_table(buf, "cmap"));
889 otf_post(buf, otf_table(buf, "post"));
890 if (otf_table(buf, "glyf"))
891 otf_glyf(buf, otf_table(buf, "glyf"));
892 otf_hmtx(buf, otf_table(buf, "hmtx"));
893 for (i = 0; i < glyph_n; i++) {
894 trfn_char(glyph_name[i], -1,
895 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
896 owid(glyph_wid[i]),
897 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
898 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
900 if (otf_table(buf, "kern"))
901 otf_kern(buf, otf_table(buf, "kern"));
902 return 0;
905 void otf_feat(int r, int k, int w)
907 res = r;
908 kmin = k;
909 warn = w;
910 if (otf_table(buf, "GSUB"))
911 otf_gsub(buf, otf_table(buf, "GSUB"));
912 if (otf_table(buf, "GPOS"))
913 otf_gpos(buf, otf_table(buf, "GPOS"));
916 /* glyph groups */
917 static int *ggrp_g[NGRPS];
918 static int ggrp_len[NGRPS];
919 static int ggrp_n;
921 static int ggrp_find(int *src, int n)
923 int i, j;
924 for (i = 0; i < ggrp_n; i++) {
925 if (ggrp_len[i] == n) {
926 for (j = 0; j < n; j++)
927 if (src[j] != ggrp_g[i][j])
928 break;
929 if (j == n)
930 return i;
933 return -1;
936 int ggrp_make(int *src, int n)
938 int id = ggrp_find(src, n);
939 int i;
940 if (id >= 0)
941 return id;
942 id = ggrp_n++;
943 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
944 ggrp_len[id] = n;
945 for (i = 0; i < n; i++)
946 ggrp_g[id][i] = src[i];
947 printf("ggrp %d %d", id, n);
948 for (i = 0; i < n; i++)
949 printf(" %s", glyph_name[src[i]]);
950 printf("\n");
951 return id;
954 static char *macset[] = {
955 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
956 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
957 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
958 "comma", "hyphen", "period", "slash", "zero",
959 "one", "two", "three", "four", "five",
960 "six", "seven", "eight", "nine", "colon",
961 "semicolon", "less", "equal", "greater", "question",
962 "at", "A", "B", "C", "D",
963 "E", "F", "G", "H", "I",
964 "J", "K", "L", "M", "N",
965 "O", "P", "Q", "R", "S",
966 "T", "U", "V", "W", "X",
967 "Y", "Z", "bracketleft", "backslash", "bracketright",
968 "asciicircum", "underscore", "grave", "a", "b",
969 "c", "d", "e", "f", "g",
970 "h", "i", "j", "k", "l",
971 "m", "n", "o", "p", "q",
972 "r", "s", "t", "u", "v",
973 "w", "x", "y", "z", "braceleft",
974 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
975 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
976 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
977 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
978 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
979 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
980 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
981 "dagger", "degree", "cent", "sterling", "section",
982 "bullet", "paragraph", "germandbls", "registered", "copyright",
983 "trademark", "acute", "dieresis", "notequal", "AE",
984 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
985 "yen", "mu", "partialdiff", "summation", "product",
986 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
987 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
988 "radical", "florin", "approxequal", "Delta", "guillemotleft",
989 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
990 "Otilde", "OE", "oe", "endash", "emdash",
991 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
992 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
993 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
994 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
995 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
996 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
997 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
998 "dotlessi", "circumflex", "tilde", "macron", "breve",
999 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1000 "caron", "Lslash", "lslash", "Scaron", "scaron",
1001 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1002 "Yacute", "yacute", "Thorn", "thorn", "minus",
1003 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1004 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1005 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1006 "Ccaron", "ccaron", "dcroat",