mkfn: order otf features automatically based on script name
[neatmkfn.git] / otf.c
bloba9f95e481997fb8fcc04d0f6a7f9183e017f25fd
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 OTFLEN 12 /* otf header length */
23 #define OTFRECLEN 16 /* otf header record length */
24 #define CMAPLEN 4 /* cmap header length */
25 #define CMAPRECLEN 8 /* cmap record length */
26 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
27 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
29 typedef unsigned int u32;
30 typedef unsigned short u16;
31 typedef unsigned char u8;
32 typedef int s32;
33 typedef short s16;
35 static char glyph_name[NGLYPHS][GNLEN];
36 static int glyph_code[NGLYPHS];
37 static int glyph_bbox[NGLYPHS][4];
38 static int glyph_wid[NGLYPHS];
39 static int glyph_n;
40 static int upm; /* units per em */
41 static int res; /* device resolution */
42 static int kmin; /* minimum kerning value */
43 static int warn;
45 static char *macset[];
47 static int owid(int w)
49 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
52 static int uwid(int w)
54 int d = 7200 / res;
55 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
58 /* report unsupported otf tables */
59 static void otf_unsupported(char *sub, int type, int fmt)
61 if (warn) {
62 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
63 if (fmt > 0)
64 fprintf(stderr, " format %d", fmt);
65 fprintf(stderr, "\n");
69 /* find the otf table with the given name */
70 static void *otf_table(void *otf, char *name)
72 void *recs = otf + OTFLEN; /* otf table records */
73 void *rec; /* beginning of a table record */
74 int nrecs = U16(otf, 4);
75 int i;
76 for (i = 0; i < nrecs; i++) {
77 rec = recs + i * OTFRECLEN;
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 void *recs = cmap + CMAPLEN; /* cmap records */
139 void *rec; /* a cmap record */
140 void *tab; /* a cmap subtable */
141 int plat, enc;
142 int fmt;
143 int nrecs = U16(cmap, 2);
144 int i;
145 for (i = 0; i < nrecs; i++) {
146 rec = recs + i * CMAPRECLEN;
147 plat = U16(rec, 0);
148 enc = U16(rec, 2);
149 tab = cmap + U32(rec, 4);
150 fmt = U16(tab, 0);
151 if (plat == 3 && enc == 1 && fmt == 4)
152 otf_cmap4(otf, tab);
156 static void otf_post(void *otf, void *post)
158 void *post2; /* version 2.0 header */
159 void *index; /* glyph name indices */
160 void *names; /* glyph names */
161 int i, idx;
162 int cname = 0;
163 if (U32(post, 0) != 0x00020000)
164 return;
165 post2 = post + 32;
166 glyph_n = U16(post2, 0);
167 index = post2 + 2;
168 names = index + 2 * glyph_n;
169 for (i = 0; i < glyph_n; i++) {
170 idx = U16(index, 2 * i);
171 if (idx <= 257) {
172 strcpy(glyph_name[i], macset[idx]);
173 } else {
174 memcpy(glyph_name[i], names + cname + 1,
175 U8(names, cname));
176 glyph_name[i][U8(names, cname)] = '\0';
177 cname += U8(names, cname) + 1;
182 static void otf_glyf(void *otf, void *glyf)
184 void *maxp = otf_table(otf, "maxp");
185 void *head = otf_table(otf, "head");
186 void *loca = otf_table(otf, "loca");
187 void *gdat;
188 void *gdat_next;
189 int n = U16(maxp, 4);
190 int fmt = U16(head, 50);
191 int i, j;
192 for (i = 0; i < n; i++) {
193 if (fmt) {
194 gdat = glyf + U32(loca, 4 * i);
195 gdat_next = glyf + U32(loca, 4 * (i + 1));
196 } else {
197 gdat = glyf + U16(loca, 2 * i) * 2;
198 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
200 if (gdat < gdat_next)
201 for (j = 0; j < 4; j++)
202 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
206 static void otf_hmtx(void *otf, void *hmtx)
208 void *hhea = otf_table(otf, "hhea");
209 int n;
210 int i;
211 n = U16(hhea, 34);
212 for (i = 0; i < n; i++)
213 glyph_wid[i] = U16(hmtx, i * 4);
214 for (i = n; i < glyph_n; i++)
215 glyph_wid[i] = glyph_wid[n - 1];
218 static void otf_kern(void *otf, void *kern)
220 int n; /* number of kern subtables */
221 void *tab; /* a kern subtable */
222 int off = 4;
223 int npairs;
224 int cov;
225 int i, j;
226 int c1, c2, val;
227 n = U16(kern, 2);
228 for (i = 0; i < n; i++) {
229 tab = kern + off;
230 off += U16(tab, 2);
231 cov = U16(tab, 4);
232 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
233 npairs = U16(tab, 6);
234 for (j = 0; j < npairs; j++) {
235 c1 = U16(tab, 14 + 6 * j);
236 c2 = U16(tab, 14 + 6 * j + 2);
237 val = S16(tab, 14 + 6 * j + 4);
238 trfn_kern(glyph_name[c1], glyph_name[c2],
239 owid(val));
245 static int coverage(void *cov, int *out)
247 int fmt = U16(cov, 0);
248 int n = U16(cov, 2);
249 int beg, end;
250 int ncov = 0;
251 int i, j;
252 if (fmt == 1) {
253 for (i = 0; i < n; i++)
254 out[ncov++] = U16(cov, 4 + 2 * i);
256 if (fmt == 2) {
257 for (i = 0; i < n; i++) {
258 beg = U16(cov, 4 + 6 * i);
259 end = U16(cov, 4 + 6 * i + 2);
260 for (j = beg; j <= end; j++)
261 out[ncov++] = j;
264 return ncov;
267 static int classdef(void *tab, int *gl, int *cls)
269 int fmt = U16(tab, 0);
270 int beg, end;
271 int n, ngl = 0;
272 int i, j;
273 if (fmt == 1) {
274 beg = U16(tab, 2);
275 ngl = U16(tab, 4);
276 for (i = 0; i < ngl; i++) {
277 gl[i] = beg + i;
278 cls[i] = U16(tab, 6 + 2 * i);
281 if (fmt == 2) {
282 n = U16(tab, 2);
283 for (i = 0; i < n; i++) {
284 beg = U16(tab, 4 + 6 * i);
285 end = U16(tab, 4 + 6 * i + 2);
286 for (j = beg; j <= end; j++) {
287 gl[ngl] = j;
288 cls[ngl] = U16(tab, 4 + 6 * i + 4);
289 ngl++;
293 return ngl;
296 static int intcmp(void *v1, void *v2)
298 return *(int *) v1 - *(int *) v2;
301 int ggrp_make(int *src, int n);
303 static int ggrp_class(int *src, int *cls, int nsrc, int id)
305 int g[NGLYPHS];
306 int n = 0;
307 int i;
308 for (i = 0; i < nsrc; i++)
309 if (cls[i] == id)
310 g[n++] = src[i];
311 qsort(g, n, sizeof(g[0]), (void *) intcmp);
312 return ggrp_make(g, n);
315 static int ggrp_coverage(int *g, int n)
317 qsort(g, n, sizeof(g[0]), (void *) intcmp);
318 return ggrp_make(g, n);
321 static int valuerecord_len(int fmt)
323 int off = 0;
324 int i;
325 for (i = 0; i < 8; i++)
326 if (fmt & (1 << i))
327 off += 2;
328 return off;
331 static void valuerecord_print(int fmt, void *rec)
333 int vals[8] = {0};
334 int off = 0;
335 int i;
336 for (i = 0; i < 8; i++) {
337 if (fmt & (1 << i)) {
338 vals[i] = uwid(S16(rec, off));
339 off += 2;
342 if (fmt)
343 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
346 static int valuerecord_small(int fmt, void *rec)
348 int off = 0;
349 int i;
350 for (i = 0; i < 8; i++) {
351 if (fmt & (1 << i)) {
352 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
353 return 0;
354 off += 2;
357 return 1;
360 /* single adjustment positioning */
361 static void otf_gpostype1(void *otf, void *sub, char *feat)
363 int fmt = U16(sub, 0);
364 int vfmt = U16(sub, 4);
365 int cov[NGLYPHS];
366 int ncov, nvals;
367 int vlen = valuerecord_len(vfmt);
368 int i;
369 ncov = coverage(sub + U16(sub, 2), cov);
370 if (fmt == 1) {
371 for (i = 0; i < ncov; i++) {
372 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
373 valuerecord_print(vfmt, sub + 6);
374 printf("\n");
377 if (fmt == 2) {
378 nvals = U16(sub, 6);
379 for (i = 0; i < nvals; i++) {
380 printf("gpos %s 1 %s", feat, glyph_name[cov[i]]);
381 valuerecord_print(vfmt, sub + 8 + i * vlen);
382 printf("\n");
387 /* pair adjustment positioning */
388 static void otf_gpostype2(void *otf, void *sub, char *feat)
390 int fmt = U16(sub, 0);
391 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
392 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
393 int fmtoff1, fmtoff2;
394 int vrlen; /* the length of vfmt1 and vfmt2 */
395 int i, j;
396 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
397 if (fmt == 1) {
398 int cov[NGLYPHS];
399 int nc1 = U16(sub, 8);
400 coverage(sub + U16(sub, 2), cov);
401 for (i = 0; i < nc1; i++) {
402 void *c2 = sub + U16(sub, 10 + 2 * i);
403 int nc2 = U16(c2, 0);
404 for (j = 0; j < nc2; j++) {
405 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
406 fmtoff1 = 2 + (2 + vrlen) * j + 2;
407 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
408 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
409 valuerecord_small(vfmt2, c2 + fmtoff2))
410 continue;
411 printf("gpos %s 2", feat);
412 printf(" %s", glyph_name[cov[i]]);
413 valuerecord_print(vfmt1, c2 + fmtoff1);
414 printf(" %s", glyph_name[second]);
415 valuerecord_print(vfmt2, c2 + fmtoff2);
416 printf("\n");
420 if (fmt == 2) {
421 int gl1[NGLYPHS], gl2[NGLYPHS];
422 int cls1[NGLYPHS], cls2[NGLYPHS];
423 int grp1[NGLYPHS], grp2[NGLYPHS];
424 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
425 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
426 int ncls1 = U16(sub, 12);
427 int ncls2 = U16(sub, 14);
428 for (i = 0; i < ncls1; i++)
429 grp1[i] = ggrp_class(gl1, cls1, ngl1, i);
430 for (i = 0; i < ncls2; i++)
431 grp2[i] = ggrp_class(gl2, cls2, ngl2, i);
432 for (i = 0; i < ncls1; i++) {
433 for (j = 0; j < ncls2; j++) {
434 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
435 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
436 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
437 valuerecord_small(vfmt2, sub + fmtoff2))
438 continue;
439 printf("gpos %s %d", feat, 2);
440 printf(" @%d", grp1[i]);
441 valuerecord_print(vfmt1, sub + fmtoff1);
442 printf(" @%d", grp2[j]);
443 valuerecord_print(vfmt2, sub + fmtoff2);
444 printf("\n");
450 /* cursive attachment positioning */
451 static void otf_gpostype3(void *otf, void *sub, char *feat)
453 int fmt = U16(sub, 0);
454 int cov[NGLYPHS];
455 int i, n;
456 coverage(sub + U16(sub, 2), cov);
457 if (fmt != 1)
458 return;
459 n = U16(sub, 4);
460 for (i = 0; i < n; i++) {
461 int prev = U16(sub, 6 + 4 * i);
462 int next = U16(sub, 6 + 4 * i + 2);
463 printf("gcur %s %s", feat, glyph_name[cov[i]]);
464 if (prev)
465 printf(" %d %d", uwid(S16(sub, prev + 2)),
466 uwid(S16(sub, prev + 4)));
467 else
468 printf(" - -");
469 if (next)
470 printf(" %d %d", uwid(S16(sub, next + 2)),
471 uwid(S16(sub, next + 4)));
472 else
473 printf(" - -");
474 printf("\n");
478 /* gsub context */
479 struct gctx {
480 int bgrp[GCTXLEN]; /* backtrack coverage arrays */
481 int igrp[GCTXLEN]; /* input coverage arrays */
482 int lgrp[GCTXLEN]; /* lookahead coverage arrays*/
483 int bn, in, ln; /* size of b[], i[], l[] */
484 int seqidx; /* sequence index */
487 static int gctx_len(struct gctx *ctx, int patlen)
489 return ctx ? ctx->bn + ctx->in + ctx->ln - patlen : 0;
492 static void gctx_backtrack(struct gctx *ctx)
494 int i;
495 if (!ctx)
496 return;
497 for (i = 0; i < ctx->bn; i++)
498 printf(" =@%d", ctx->bgrp[i]);
499 for (i = 0; i < ctx->seqidx; i++)
500 printf(" =@%d", ctx->igrp[i]);
503 static void gctx_lookahead(struct gctx *ctx, int patlen)
505 int i;
506 if (!ctx)
507 return;
508 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
509 printf(" =@%d", ctx->igrp[i]);
510 for (i = 0; i < ctx->ln; i++)
511 printf(" =@%d", ctx->lgrp[i]);
514 /* single substitution */
515 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
517 int cov[NGLYPHS];
518 int fmt = U16(sub, 0);
519 int ncov;
520 int n;
521 int i;
522 ncov = coverage(sub + U16(sub, 2), cov);
523 if (fmt == 1) {
524 for (i = 0; i < ncov; i++) {
525 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
526 gctx_backtrack(ctx);
527 printf(" -%s +%s", glyph_name[cov[i]],
528 glyph_name[cov[i] + S16(sub, 4)]);
529 gctx_lookahead(ctx, 1);
530 printf("\n");
533 if (fmt == 2) {
534 n = U16(sub, 4);
535 for (i = 0; i < n; i++) {
536 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
537 gctx_backtrack(ctx);
538 printf(" -%s +%s", glyph_name[cov[i]],
539 glyph_name[U16(sub, 6 + 2 * i)]);
540 gctx_lookahead(ctx, 1);
541 printf("\n");
546 /* alternate substitution */
547 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
549 int cov[NGLYPHS];
550 int fmt = U16(sub, 0);
551 int n, i, j;
552 if (fmt != 1)
553 return;
554 coverage(sub + U16(sub, 2), cov);
555 n = U16(sub, 4);
556 for (i = 0; i < n; i++) {
557 void *alt = sub + U16(sub, 6 + 2 * i);
558 int nalt = U16(alt, 0);
559 for (j = 0; j < nalt; j++) {
560 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
561 gctx_backtrack(ctx);
562 printf(" -%s +%s", glyph_name[cov[i]],
563 glyph_name[U16(alt, 2 + 2 * j)]);
564 gctx_lookahead(ctx, 1);
565 printf("\n");
570 /* ligature substitution */
571 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
573 int fmt = U16(sub, 0);
574 int cov[NGLYPHS];
575 int n, i, j, k;
576 if (fmt != 1)
577 return;
578 coverage(sub + U16(sub, 2), cov);
579 n = U16(sub, 4);
580 for (i = 0; i < n; i++) {
581 void *set = sub + U16(sub, 6 + 2 * i);
582 int nset = U16(set, 0);
583 for (j = 0; j < nset; j++) {
584 void *lig = set + U16(set, 2 + 2 * j);
585 int nlig = U16(lig, 2);
586 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
587 gctx_backtrack(ctx);
588 printf(" -%s", glyph_name[cov[i]]);
589 for (k = 0; k < nlig - 1; k++)
590 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
591 printf(" +%s", glyph_name[U16(lig, 0)]);
592 gctx_lookahead(ctx, nlig);
593 printf("\n");
598 /* chaining contextual substitution */
599 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
601 struct gctx ctx = {{0}};
602 void *lookups = gsub + U16(gsub, 8);
603 int fmt = U16(sub, 0);
604 int cov[NGLYPHS];
605 int i, j, nsub, ncov;
606 int off = 2;
607 if (fmt != 3) {
608 otf_unsupported("GSUB", 6, fmt);
609 return;
611 ctx.bn = U16(sub, off);
612 for (i = 0; i < ctx.bn; i++) {
613 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
614 ctx.bgrp[i] = ggrp_coverage(cov, ncov);
616 off += 2 + 2 * ctx.bn;
617 ctx.in = U16(sub, off);
618 for (i = 0; i < ctx.in; i++) {
619 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
620 ctx.igrp[i] = ggrp_coverage(cov, ncov);
622 off += 2 + 2 * ctx.in;
623 ctx.ln = U16(sub, off);
624 for (i = 0; i < ctx.ln; i ++) {
625 ncov = coverage(sub + U16(sub, off + 2 + 2 * i), cov);
626 ctx.lgrp[i] = ggrp_coverage(cov, ncov);
628 off += 2 + 2 * ctx.ln;
629 nsub = U16(sub, off); /* nsub > 1 is not supported */
630 for (i = 0; i < nsub && i < 1; i++) {
631 int lidx = U16(sub, off + 2 + 4 * i + 2);
632 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
633 int ltype = U16(lookup, 0);
634 int ntabs = U16(lookup, 4);
635 ctx.seqidx = U16(sub, off + 2 + 4 * i);
636 for (j = 0; j < ntabs; j++) {
637 void *tab = lookup + U16(lookup, 6 + 2 * j);
638 int type = ltype;
639 if (type == 7) { /* extension substitution */
640 type = U16(tab, 2);
641 tab = tab + U32(tab, 4);
643 if (type == 1)
644 otf_gsubtype1(otf, tab, feat, &ctx);
645 if (type == 3)
646 otf_gsubtype3(otf, tab, feat, &ctx);
647 if (type == 4)
648 otf_gsubtype4(otf, tab, feat, &ctx);
653 /* an otf gsub/gpos lookup */
654 struct otflookup {
655 char feat[8]; /* feature name */
656 int lookup; /* index into the lookup table */
659 /* parse the given gsub/gpos feature table */
660 static int otf_featrec(void *otf, void *gtab, void *featrec, struct otflookup *lookups)
662 void *feats = gtab + U16(gtab, 6);
663 void *feat = feats + U16(featrec, 4);
664 int nlookups = U16(feat, 2);
665 int i;
666 for (i = 0; i < nlookups; i++) {
667 memcpy(lookups[i].feat, featrec, 4);
668 lookups[i].feat[4] = '\0';
669 lookups[i].lookup = U16(feat, 4 + 2 * i);
671 return nlookups;
674 /* parse the given language table and its feature tables */
675 static int otf_lang(void *otf, void *gtab, void *lang, struct otflookup *lookups)
677 void *feats = gtab + U16(gtab, 6);
678 int featidx = U16(lang, 2);
679 int nfeat = U16(lang, 4);
680 int n = 0;
681 int i;
682 if (featidx != 0xffff)
683 n += otf_featrec(otf, gtab, feats + 2 + 6 * featidx, lookups + n);
684 for (i = 0; i < nfeat; i++)
685 n += otf_featrec(otf, gtab,
686 feats + 2 + 6 * U16(lang, 6 + 2 * i), lookups + n);
687 return n;
690 static int lookupcmp(void *v1, void *v2)
692 struct otflookup *l1 = v1;
693 struct otflookup *l2 = v2;
694 if (trfn_featrank(l1->feat) != trfn_featrank(l2->feat))
695 return trfn_featrank(l1->feat) - trfn_featrank(l2->feat);
696 return l1->lookup - l2->lookup;
699 /* extract lookup tables for all features of the given gsub/gpos table */
700 static int otf_gtab(void *otf, void *gpos, struct otflookup *lookups)
702 void *scripts = gpos + U16(gpos, 4);
703 int nscripts, nlangs;
704 void *script;
705 void *grec, *lrec;
706 char tag[8];
707 int i, j;
708 int n = 0;
709 nscripts = U16(scripts, 0);
710 for (i = 0; i < nscripts; i++) {
711 grec = scripts + 2 + 6 * i;
712 memcpy(tag, grec, 4);
713 tag[4] = '\0';
714 if (!trfn_script(tag, nscripts))
715 continue;
716 script = scripts + U16(grec, 4);
717 nlangs = U16(script, 2);
718 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
719 n += otf_lang(otf, gpos, script + U16(script, 0), lookups + n);
720 for (j = 0; j < nlangs; j++) {
721 lrec = script + 4 + 6 * j;
722 memcpy(tag, lrec, 4);
723 tag[4] = '\0';
724 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
725 n += otf_lang(otf, gpos, script + U16(lrec, 4), lookups + n);
728 qsort(lookups, n, sizeof(lookups[0]), (void *) lookupcmp);
729 return n;
732 static void otf_gpos(void *otf, void *gpos)
734 struct otflookup lookups[NLOOKUPS];
735 void *lookuplist = gpos + U16(gpos, 8);
736 int nlookups = otf_gtab(otf, gpos, lookups);
737 int i, j;
738 for (i = 0; i < nlookups; i++) {
739 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
740 char *tag = lookups[i].feat;
741 int ltype = U16(lookup, 0);
742 int ntabs = U16(lookup, 4);
743 for (j = 0; j < ntabs; j++) {
744 void *tab = lookup + U16(lookup, 6 + 2 * j);
745 int type = ltype;
746 if (type == 9) { /* extension positioning */
747 type = U16(tab, 2);
748 tab = tab + U32(tab, 4);
750 switch (type) {
751 case 1:
752 otf_gpostype1(otf, tab, tag);
753 break;
754 case 2:
755 otf_gpostype2(otf, tab, tag);
756 break;
757 case 3:
758 otf_gpostype3(otf, tab, tag);
759 break;
760 default:
761 otf_unsupported("GPOS", type, 0);
767 static void otf_gsub(void *otf, void *gsub)
769 struct otflookup lookups[NLOOKUPS];
770 void *lookuplist = gsub + U16(gsub, 8);
771 int nlookups = otf_gtab(otf, gsub, lookups);
772 int i, j;
773 for (i = 0; i < nlookups; i++) {
774 void *lookup = lookuplist + U16(lookuplist, 2 + 2 * lookups[i].lookup);
775 char *tag = lookups[i].feat;
776 int ltype = U16(lookup, 0);
777 int ntabs = U16(lookup, 4);
778 for (j = 0; j < ntabs; j++) {
779 void *tab = lookup + U16(lookup, 6 + 2 * j);
780 int type = ltype;
781 if (type == 7) { /* extension substitution */
782 type = U16(tab, 2);
783 tab = tab + U32(tab, 4);
785 switch (type) {
786 case 1:
787 otf_gsubtype1(otf, tab, tag, NULL);
788 break;
789 case 3:
790 otf_gsubtype3(otf, tab, tag, NULL);
791 break;
792 case 4:
793 otf_gsubtype4(otf, tab, tag, NULL);
794 break;
795 case 6:
796 otf_gsubtype6(otf, tab, tag, gsub);
797 break;
798 default:
799 otf_unsupported("GSUB", type, 0);
805 int xread(int fd, char *buf, int len)
807 int nr = 0;
808 while (nr < len) {
809 int ret = read(fd, buf + nr, len - nr);
810 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
811 continue;
812 if (ret <= 0)
813 break;
814 nr += ret;
816 return nr;
819 static char buf[BUFLEN];
821 int otf_read(void)
823 int i;
824 if (xread(0, buf, sizeof(buf)) <= 0)
825 return 1;
826 upm = U16(otf_table(buf, "head"), 18);
827 otf_name(buf, otf_table(buf, "name"));
828 otf_cmap(buf, otf_table(buf, "cmap"));
829 otf_post(buf, otf_table(buf, "post"));
830 if (otf_table(buf, "glyf"))
831 otf_glyf(buf, otf_table(buf, "glyf"));
832 otf_hmtx(buf, otf_table(buf, "hmtx"));
833 for (i = 0; i < glyph_n; i++) {
834 trfn_char(glyph_name[i], -1,
835 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
836 owid(glyph_wid[i]),
837 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
838 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
840 if (otf_table(buf, "kern"))
841 otf_kern(buf, otf_table(buf, "kern"));
842 return 0;
845 void otf_feat(int r, int k, int w)
847 res = r;
848 kmin = k;
849 warn = w;
850 if (otf_table(buf, "GSUB"))
851 otf_gsub(buf, otf_table(buf, "GSUB"));
852 if (otf_table(buf, "GPOS"))
853 otf_gpos(buf, otf_table(buf, "GPOS"));
856 /* glyph groups */
857 static int *ggrp_g[NGRPS];
858 static int ggrp_len[NGRPS];
859 static int ggrp_n;
861 static int ggrp_find(int *src, int n)
863 int i, j;
864 for (i = 0; i < ggrp_n; i++) {
865 if (ggrp_len[i] == n) {
866 for (j = 0; j < n; j++)
867 if (src[j] != ggrp_g[i][j])
868 break;
869 if (j == n)
870 return i;
873 return -1;
876 int ggrp_make(int *src, int n)
878 int id = ggrp_find(src, n);
879 int i;
880 if (id >= 0)
881 return id;
882 id = ggrp_n++;
883 ggrp_g[id] = malloc(n * sizeof(ggrp_g[id][0]));
884 ggrp_len[id] = n;
885 for (i = 0; i < n; i++)
886 ggrp_g[id][i] = src[i];
887 printf("ggrp %d %d", id, n);
888 for (i = 0; i < n; i++)
889 printf(" %s", glyph_name[src[i]]);
890 printf("\n");
891 return id;
894 static char *macset[] = {
895 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
896 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
897 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
898 "comma", "hyphen", "period", "slash", "zero",
899 "one", "two", "three", "four", "five",
900 "six", "seven", "eight", "nine", "colon",
901 "semicolon", "less", "equal", "greater", "question",
902 "at", "A", "B", "C", "D",
903 "E", "F", "G", "H", "I",
904 "J", "K", "L", "M", "N",
905 "O", "P", "Q", "R", "S",
906 "T", "U", "V", "W", "X",
907 "Y", "Z", "bracketleft", "backslash", "bracketright",
908 "asciicircum", "underscore", "grave", "a", "b",
909 "c", "d", "e", "f", "g",
910 "h", "i", "j", "k", "l",
911 "m", "n", "o", "p", "q",
912 "r", "s", "t", "u", "v",
913 "w", "x", "y", "z", "braceleft",
914 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
915 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
916 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
917 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
918 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
919 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
920 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
921 "dagger", "degree", "cent", "sterling", "section",
922 "bullet", "paragraph", "germandbls", "registered", "copyright",
923 "trademark", "acute", "dieresis", "notequal", "AE",
924 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
925 "yen", "mu", "partialdiff", "summation", "product",
926 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
927 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
928 "radical", "florin", "approxequal", "Delta", "guillemotleft",
929 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
930 "Otilde", "OE", "oe", "endash", "emdash",
931 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
932 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
933 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
934 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
935 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
936 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
937 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
938 "dotlessi", "circumflex", "tilde", "macron", "breve",
939 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
940 "caron", "Lslash", "lslash", "Scaron", "scaron",
941 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
942 "Yacute", "yacute", "Thorn", "thorn", "minus",
943 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
944 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
945 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
946 "Ccaron", "ccaron", "dcroat",