otf: prefix gpos glyph names with =
[neatmkfn.git] / otf.c
blob94be216f02a4dbfbddb8d6efb7dec97236f4ceb4
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 MAX(a, b) ((a) < (b) ? (b) : (a))
14 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
15 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
16 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
17 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
18 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
20 #define OTFLEN 12 /* otf header length */
21 #define OTFRECLEN 16 /* otf header record length */
22 #define CMAPLEN 4 /* cmap header length */
23 #define CMAPRECLEN 8 /* cmap record length */
24 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
25 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
27 typedef unsigned int u32;
28 typedef unsigned short u16;
29 typedef unsigned char u8;
30 typedef int s32;
31 typedef short s16;
33 static char glyph_name[NGLYPHS][GNLEN];
34 static int glyph_code[NGLYPHS];
35 static int glyph_bbox[NGLYPHS][4];
36 static int glyph_wid[NGLYPHS];
37 static int glyph_n;
38 static int upm; /* units per em */
39 static int res; /* device resolution */
40 static int kmin; /* minimum kerning value */
41 static int warn;
43 static char *macset[];
45 static int owid(int w)
47 return (w < 0 ? w * 1000 - upm / 2 : w * 1000 + upm / 2) / upm;
50 static int uwid(int w)
52 int d = 7200 / res;
53 return (w < 0 ? owid(w) - d / 2 : owid(w) + d / 2) / d;
56 /* report unsupported otf tables */
57 static void otf_unsupported(char *sub, int type, int fmt)
59 if (warn) {
60 fprintf(stderr, "neatmkfn: unsupported %s lookup %d", sub, type);
61 if (fmt > 0)
62 fprintf(stderr, " format %d", fmt);
63 fprintf(stderr, "\n");
67 /* find the otf table with the given name */
68 static void *otf_table(void *otf, char *name)
70 void *recs = otf + OTFLEN; /* otf table records */
71 void *rec; /* beginning of a table record */
72 int nrecs = U16(otf, 4);
73 int i;
74 for (i = 0; i < nrecs; i++) {
75 rec = recs + i * OTFRECLEN;
76 if (!strncmp(rec, name, 4))
77 return otf + U32(rec, 8);
79 return NULL;
82 /* parse otf cmap format 4 subtable */
83 static void otf_cmap4(void *otf, void *cmap4)
85 int nsegs;
86 void *ends, *begs, *deltas, *offsets;
87 int beg, end, delta, offset;
88 int i, j;
89 nsegs = U16(cmap4, 6) / 2;
90 ends = cmap4 + 14;
91 begs = ends + 2 * nsegs + 2;
92 deltas = begs + 2 * nsegs;
93 offsets = deltas + 2 * nsegs;
94 for (i = 0; i < nsegs; i++) {
95 beg = U16(begs, 2 * i);
96 end = U16(ends, 2 * i);
97 delta = U16(deltas, 2 * i);
98 offset = U16(offsets, 2 * i);
99 if (offset) {
100 for (j = beg; j <= end; j++)
101 glyph_code[(U16(offsets + 2 * i,
102 offset + (j - beg) * 2) + delta) & 0xffff] = j;
103 } else {
104 for (j = beg; j <= end; j++)
105 glyph_code[(j + delta) & 0xffff] = j;
110 /* parse otf cmap header */
111 static void otf_cmap(void *otf, void *cmap)
113 void *recs = cmap + CMAPLEN; /* cmap records */
114 void *rec; /* a cmap record */
115 void *tab; /* a cmap subtable */
116 int plat, enc;
117 int fmt;
118 int nrecs = U16(cmap, 2);
119 int i;
120 for (i = 0; i < nrecs; i++) {
121 rec = recs + i * CMAPRECLEN;
122 plat = U16(rec, 0);
123 enc = U16(rec, 2);
124 tab = cmap + U32(rec, 4);
125 fmt = U16(tab, 0);
126 if (plat == 3 && enc == 1 && fmt == 4)
127 otf_cmap4(otf, tab);
131 static void otf_post(void *otf, void *post)
133 void *post2; /* version 2.0 header */
134 void *index; /* glyph name indices */
135 void *names; /* glyph names */
136 int i, idx;
137 int cname = 0;
138 if (U32(post, 0) != 0x00020000)
139 return;
140 post2 = post + 32;
141 glyph_n = U16(post2, 0);
142 index = post2 + 2;
143 names = index + 2 * glyph_n;
144 for (i = 0; i < glyph_n; i++) {
145 idx = U16(index, 2 * i);
146 if (idx <= 257) {
147 strcpy(glyph_name[i], macset[idx]);
148 } else {
149 memcpy(glyph_name[i], names + cname + 1,
150 U8(names, cname));
151 glyph_name[i][U8(names, cname)] = '\0';
152 cname += U8(names, cname) + 1;
157 static void otf_glyf(void *otf, void *glyf)
159 void *maxp = otf_table(otf, "maxp");
160 void *head = otf_table(otf, "head");
161 void *loca = otf_table(otf, "loca");
162 void *gdat;
163 void *gdat_next;
164 int n = U16(maxp, 4);
165 int fmt = U16(head, 50);
166 int i, j;
167 for (i = 0; i < n; i++) {
168 if (fmt) {
169 gdat = glyf + U32(loca, 4 * i);
170 gdat_next = glyf + U32(loca, 4 * (i + 1));
171 } else {
172 gdat = glyf + U16(loca, 2 * i) * 2;
173 gdat_next = glyf + U16(loca, 2 * (i + 1)) * 2;
175 if (gdat < gdat_next)
176 for (j = 0; j < 4; j++)
177 glyph_bbox[i][j] = S16(gdat, 2 + 2 * j);
181 static void otf_hmtx(void *otf, void *hmtx)
183 void *hhea = otf_table(otf, "hhea");
184 int n;
185 int i;
186 n = U16(hhea, 34);
187 for (i = 0; i < n; i++)
188 glyph_wid[i] = U16(hmtx, i * 4);
189 for (i = n; i < glyph_n; i++)
190 glyph_wid[i] = glyph_wid[n - 1];
193 static void otf_kern(void *otf, void *kern)
195 int n; /* number of kern subtables */
196 void *tab; /* a kern subtable */
197 int off = 4;
198 int npairs;
199 int cov;
200 int i, j;
201 int c1, c2, val;
202 n = U16(kern, 2);
203 for (i = 0; i < n; i++) {
204 tab = kern + off;
205 off += U16(tab, 2);
206 cov = U16(tab, 4);
207 if ((cov >> 8) == 0 && (cov & 1)) { /* format 0 */
208 npairs = U16(tab, 6);
209 for (j = 0; j < npairs; j++) {
210 c1 = U16(tab, 14 + 6 * j);
211 c2 = U16(tab, 14 + 6 * j + 2);
212 val = S16(tab, 14 + 6 * j + 4);
213 trfn_kern(glyph_name[c1], glyph_name[c2],
214 owid(val));
220 static int coverage(void *cov, int *out)
222 int fmt = U16(cov, 0);
223 int n = U16(cov, 2);
224 int beg, end;
225 int ncov = 0;
226 int i, j;
227 if (fmt == 1) {
228 for (i = 0; i < n; i++)
229 out[ncov++] = U16(cov, 4 + 2 * i);
231 if (fmt == 2) {
232 for (i = 0; i < n; i++) {
233 beg = U16(cov, 4 + 6 * i);
234 end = U16(cov, 4 + 6 * i + 2);
235 for (j = beg; j <= end; j++)
236 out[ncov++] = j;
239 return ncov;
242 static int classdef(void *tab, int *gl, int *cls)
244 int fmt = U16(tab, 0);
245 int beg, end;
246 int n, ngl = 0;
247 int i, j;
248 if (fmt == 1) {
249 beg = U16(tab, 2);
250 ngl = U16(tab, 4);
251 for (i = 0; i < ngl; i++) {
252 gl[i] = beg + i;
253 cls[i] = U16(tab, 6 + 2 * i);
256 if (fmt == 2) {
257 n = U16(tab, 2);
258 for (i = 0; i < n; i++) {
259 beg = U16(tab, 4 + 6 * i);
260 end = U16(tab, 4 + 6 * i + 2);
261 for (j = beg; j <= end; j++) {
262 gl[ngl] = j;
263 cls[ngl] = U16(tab, 4 + 6 * i + 4);
264 ngl++;
268 return ngl;
271 static int valuerecord_len(int fmt)
273 int off = 0;
274 int i;
275 for (i = 0; i < 8; i++)
276 if (fmt & (1 << i))
277 off += 2;
278 return off;
281 static void valuerecord_print(int fmt, void *rec)
283 int vals[8] = {0};
284 int off = 0;
285 int i;
286 for (i = 0; i < 8; i++) {
287 if (fmt & (1 << i)) {
288 vals[i] = uwid(S16(rec, off));
289 off += 2;
292 if (fmt)
293 printf(":%+d%+d%+d%+d", vals[0], vals[1], vals[2], vals[3]);
296 static int valuerecord_small(int fmt, void *rec)
298 int off = 0;
299 int i;
300 for (i = 0; i < 8; i++) {
301 if (fmt & (1 << i)) {
302 if (abs(uwid(S16(rec, off))) >= MAX(1, kmin))
303 return 0;
304 off += 2;
307 return 1;
310 /* single adjustment positioning */
311 static void otf_gpostype1(void *otf, void *sub, char *feat)
313 int fmt = U16(sub, 0);
314 int vfmt = U16(sub, 4);
315 int cov[NGLYPHS];
316 int ncov, nvals;
317 int vlen = valuerecord_len(vfmt);
318 int i;
319 ncov = coverage(sub + U16(sub, 2), cov);
320 if (fmt == 1) {
321 for (i = 0; i < ncov; i++) {
322 printf("gpos %s 1 =%s", feat, glyph_name[cov[i]]);
323 valuerecord_print(vfmt, sub + 6);
324 printf("\n");
327 if (fmt == 2) {
328 nvals = U16(sub, 6);
329 for (i = 0; i < nvals; i++) {
330 printf("gpos %s 1 =%s", feat, glyph_name[cov[i]]);
331 valuerecord_print(vfmt, sub + 8 + i * vlen);
332 printf("\n");
337 /* pair adjustment positioning */
338 static void otf_gpostype2(void *otf, void *sub, char *feat)
340 int fmt = U16(sub, 0);
341 int vfmt1 = U16(sub, 4); /* valuerecord 1 */
342 int vfmt2 = U16(sub, 6); /* valuerecord 2 */
343 int fmtoff1, fmtoff2;
344 int vrlen; /* the length of vfmt1 and vfmt2 */
345 int i, j, k, l;
346 vrlen = valuerecord_len(vfmt1) + valuerecord_len(vfmt2);
347 if (fmt == 1) {
348 int cov[NGLYPHS];
349 int nc1 = U16(sub, 8);
350 coverage(sub + U16(sub, 2), cov);
351 for (i = 0; i < nc1; i++) {
352 void *c2 = sub + U16(sub, 10 + 2 * i);
353 int nc2 = U16(c2, 0);
354 for (j = 0; j < nc2; j++) {
355 int second = U16(c2 + 2 + (2 + vrlen) * j, 0);
356 fmtoff1 = 2 + (2 + vrlen) * j + 2;
357 fmtoff2 = fmtoff1 + valuerecord_len(vfmt2);
358 if (valuerecord_small(vfmt1, c2 + fmtoff1) &&
359 valuerecord_small(vfmt2, c2 + fmtoff2))
360 continue;
361 printf("gpos %s 2", feat);
362 printf(" =%s", glyph_name[cov[i]]);
363 valuerecord_print(vfmt1, c2 + fmtoff1);
364 printf(" =%s", glyph_name[second]);
365 valuerecord_print(vfmt2, c2 + fmtoff2);
366 printf("\n");
370 if (fmt == 2) {
371 int gl1[NGLYPHS], gl2[NGLYPHS];
372 int cls1[NGLYPHS], cls2[NGLYPHS];
373 int ngl1 = classdef(sub + U16(sub, 8), gl1, cls1);
374 int ngl2 = classdef(sub + U16(sub, 10), gl2, cls2);
375 int ncls1 = U16(sub, 12);
376 int ncls2 = U16(sub, 14);
377 for (i = 0; i < ncls1; i++) {
378 for (j = 0; j < ncls2; j++) {
379 int n1 = 0, n2 = 0;
380 fmtoff1 = 16 + (i * ncls2 + j) * vrlen;
381 fmtoff2 = fmtoff1 + valuerecord_len(vfmt1);
382 if (valuerecord_small(vfmt1, sub + fmtoff1) &&
383 valuerecord_small(vfmt2, sub + fmtoff2))
384 continue;
385 for (k = 0; k < ngl1; k++)
386 if (cls1[k] == i)
387 n1++;
388 for (k = 0; k < ngl2; k++)
389 if (cls2[k] == j)
390 n2++;
391 printf("gpos %s %d", feat, n1 + n2);
392 l = 0;
393 for (k = 0; k < ngl1; k++) {
394 if (cls1[k] == i) {
395 printf(" %c%s", !l++ ? '=' : '|',
396 glyph_name[gl1[k]]);
397 valuerecord_print(vfmt1, sub + fmtoff1);
400 l = 0;
401 for (k = 0; k < ngl2; k++) {
402 if (cls2[k] == j) {
403 printf(" %c%s", !l++ ? '=' : '|',
404 glyph_name[gl2[k]]);
405 valuerecord_print(vfmt2, sub + fmtoff2);
408 printf("\n");
414 /* cursive attachment positioning */
415 static void otf_gpostype3(void *otf, void *sub, char *feat)
417 int fmt = U16(sub, 0);
418 int cov[NGLYPHS];
419 int i, n;
420 coverage(sub + U16(sub, 2), cov);
421 if (fmt != 1)
422 return;
423 n = U16(sub, 4);
424 for (i = 0; i < n; i++) {
425 int prev = U16(sub, 6 + 4 * i);
426 int next = U16(sub, 6 + 4 * i + 2);
427 printf("gcur %s %s", feat, glyph_name[cov[i]]);
428 if (prev)
429 printf(" %d %d", uwid(S16(sub, prev + 2)),
430 uwid(S16(sub, prev + 4)));
431 else
432 printf(" - -");
433 if (next)
434 printf(" %d %d", uwid(S16(sub, next + 2)),
435 uwid(S16(sub, next + 4)));
436 else
437 printf(" - -");
438 printf("\n");
442 /* parse the given gpos feature table */
443 static void otf_gposfeatrec(void *otf, void *gpos, void *featrec)
445 void *feats = gpos + U16(gpos, 6);
446 void *lookups = gpos + U16(gpos, 8);
447 void *feat, *lookup, *tab;
448 int nlookups, type, ntabs;
449 char tag[8] = "";
450 int i, j;
451 memcpy(tag, featrec, 4);
452 feat = feats + U16(featrec, 4);
453 nlookups = U16(feat, 2);
454 for (i = 0; i < nlookups; i++) {
455 lookup = lookups + U16(lookups, 2 + 2 * U16(feat, 4 + 2 * i));
456 type = U16(lookup, 0);
457 ntabs = U16(lookup, 4);
458 for (j = 0; j < ntabs; j++) {
459 tab = lookup + U16(lookup, 6 + 2 * j);
460 switch (type) {
461 case 1:
462 otf_gpostype1(otf, tab, tag);
463 break;
464 case 2:
465 otf_gpostype2(otf, tab, tag);
466 break;
467 case 3:
468 otf_gpostype3(otf, tab, tag);
469 break;
470 default:
471 otf_unsupported("GPOS", type, 0);
477 /* parse the given gpos language table and its feature tables */
478 static void otf_gposlang(void *otf, void *gpos, void *lang)
480 void *feats = gpos + U16(gpos, 6);
481 int featidx = U16(lang, 2);
482 int nfeat = U16(lang, 4);
483 int i;
484 if (featidx != 0xffff)
485 otf_gposfeatrec(otf, gpos, feats + 2 + 6 * featidx);
486 for (i = 0; i < nfeat; i++)
487 otf_gposfeatrec(otf, gpos,
488 feats + 2 + 6 * U16(lang, 6 + 2 * i));
491 static void otf_gpos(void *otf, void *gpos)
493 void *scripts = gpos + U16(gpos, 4);
494 int nscripts, nlangs;
495 void *script;
496 void *grec, *lrec;
497 char tag[8];
498 int i, j;
499 nscripts = U16(scripts, 0);
500 for (i = 0; i < nscripts; i++) {
501 grec = scripts + 2 + 6 * i;
502 memcpy(tag, grec, 4);
503 tag[4] = '\0';
504 if (!trfn_script(tag, nscripts))
505 continue;
506 script = scripts + U16(grec, 4);
507 nlangs = U16(script, 2);
508 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
509 otf_gposlang(otf, gpos, script + U16(script, 0));
510 for (j = 0; j < nlangs; j++) {
511 lrec = script + 4 + 6 * j;
512 memcpy(tag, lrec, 4);
513 tag[4] = '\0';
514 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
515 otf_gposlang(otf, gpos, script + U16(lrec, 4));
520 /* gsub context */
521 struct gctx {
522 int *b[GCTXLEN], blen[GCTXLEN]; /* backtrack coverage arrays */
523 int *i[GCTXLEN], ilen[GCTXLEN]; /* input coverage arrays */
524 int *l[GCTXLEN], llen[GCTXLEN]; /* lookahead coverage arrays*/
525 int bn, in, ln; /* size of b[], i[], l[] */
526 int seqidx; /* sequence index */
529 static int gctx_len(struct gctx *ctx, int patlen)
531 int i, n = 0;
532 if (!ctx)
533 return 0;
534 for (i = 0; i < ctx->bn; i++)
535 n += ctx->blen[i];
536 for (i = 0; i < ctx->seqidx; i++)
537 n += ctx->ilen[i];
538 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
539 n += ctx->ilen[i];
540 for (i = 0; i < ctx->ln; i++)
541 n += ctx->llen[i];
542 return n;
545 static void gctx_backtrack(struct gctx *ctx)
547 int i, j;
548 if (!ctx)
549 return;
550 for (i = 0; i < ctx->bn; i++)
551 for (j = 0; j < ctx->blen[i]; j++)
552 printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->b[i][j]]);
553 for (i = 0; i < ctx->seqidx; i++)
554 for (j = 0; j < ctx->ilen[i]; j++)
555 printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->i[i][j]]);
558 static void gctx_lookahead(struct gctx *ctx, int patlen)
560 int i, j;
561 if (!ctx)
562 return;
563 for (i = ctx->seqidx + patlen; i < ctx->in; i++)
564 for (j = 0; j < ctx->ilen[i]; j++)
565 printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->i[i][j]]);
566 for (i = 0; i < ctx->ln; i++)
567 for (j = 0; j < ctx->llen[i]; j++)
568 printf(" %c%s", !j ? '=' : '|', glyph_name[ctx->l[i][j]]);
571 /* single substitution */
572 static void otf_gsubtype1(void *otf, void *sub, char *feat, struct gctx *ctx)
574 int cov[NGLYPHS];
575 int fmt = U16(sub, 0);
576 int ncov;
577 int n;
578 int i;
579 ncov = coverage(sub + U16(sub, 2), cov);
580 if (fmt == 1) {
581 for (i = 0; i < ncov; i++) {
582 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
583 gctx_backtrack(ctx);
584 printf(" -%s +%s", glyph_name[cov[i]],
585 glyph_name[cov[i] + S16(sub, 4)]);
586 gctx_lookahead(ctx, 1);
587 printf("\n");
590 if (fmt == 2) {
591 n = U16(sub, 4);
592 for (i = 0; i < n; i++) {
593 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
594 gctx_backtrack(ctx);
595 printf(" -%s +%s", glyph_name[cov[i]],
596 glyph_name[U16(sub, 6 + 2 * i)]);
597 gctx_lookahead(ctx, 1);
598 printf("\n");
603 /* alternate substitution */
604 static void otf_gsubtype3(void *otf, void *sub, char *feat, struct gctx *ctx)
606 int cov[NGLYPHS];
607 int fmt = U16(sub, 0);
608 int n, i, j;
609 if (fmt != 1)
610 return;
611 coverage(sub + U16(sub, 2), cov);
612 n = U16(sub, 4);
613 for (i = 0; i < n; i++) {
614 void *alt = sub + U16(sub, 6 + 2 * i);
615 int nalt = U16(alt, 0);
616 for (j = 0; j < nalt; j++) {
617 printf("gsub %s %d", feat, 2 + gctx_len(ctx, 1));
618 gctx_backtrack(ctx);
619 printf(" -%s +%s", glyph_name[cov[i]],
620 glyph_name[U16(alt, 2 + 2 * j)]);
621 gctx_lookahead(ctx, 1);
622 printf("\n");
627 /* ligature substitution */
628 static void otf_gsubtype4(void *otf, void *sub, char *feat, struct gctx *ctx)
630 int fmt = U16(sub, 0);
631 int cov[NGLYPHS];
632 int n, i, j, k;
633 if (fmt != 1)
634 return;
635 coverage(sub + U16(sub, 2), cov);
636 n = U16(sub, 4);
637 for (i = 0; i < n; i++) {
638 void *set = sub + U16(sub, 6 + 2 * i);
639 int nset = U16(set, 0);
640 for (j = 0; j < nset; j++) {
641 void *lig = set + U16(set, 2 + 2 * j);
642 int nlig = U16(lig, 2);
643 printf("gsub %s %d", feat, nlig + 1 + gctx_len(ctx, nlig));
644 gctx_backtrack(ctx);
645 printf(" -%s", glyph_name[cov[i]]);
646 for (k = 0; k < nlig - 1; k++)
647 printf(" -%s", glyph_name[U16(lig, 4 + 2 * k)]);
648 printf(" +%s", glyph_name[U16(lig, 0)]);
649 gctx_lookahead(ctx, nlig);
650 printf("\n");
655 /* chaining contextual substitution */
656 static void otf_gsubtype6(void *otf, void *sub, char *feat, void *gsub)
658 struct gctx ctx = {{NULL}};
659 void *lookups = gsub + U16(gsub, 8);
660 int fmt = U16(sub, 0);
661 int gbank[NGLYPHS];
662 int gbank_pos = 0;
663 int n, i, j, nsub;
664 int off = 2;
665 if (fmt != 3) {
666 otf_unsupported("GSUB", 6, fmt);
667 return;
669 ctx.bn = U16(sub, off);
670 for (i = 0; i < ctx.bn; i++) {
671 n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
672 ctx.b[i] = gbank + gbank_pos;
673 ctx.blen[i] = n;
674 gbank_pos += n;
676 off += 2 + 2 * ctx.bn;
677 ctx.in = U16(sub, off);
678 for (i = 0; i < ctx.in; i ++) {
679 n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
680 ctx.i[i] = gbank + gbank_pos;
681 ctx.ilen[i] = n;
682 gbank_pos += n;
684 off += 2 + 2 * ctx.in;
685 ctx.ln = U16(sub, off);
686 for (i = 0; i < ctx.ln; i ++) {
687 n = coverage(sub + U16(sub, off + 2 + 2 * i), gbank + gbank_pos);
688 ctx.l[i] = gbank + gbank_pos;
689 ctx.llen[i] = n;
690 gbank_pos += n;
692 off += 2 + 2 * ctx.ln;
693 nsub = U16(sub, off); /* nsub > 1 is not supported */
694 for (i = 0; i < nsub && i < 1; i++) {
695 int lidx = U16(sub, off + 2 + 4 * i + 2);
696 void *lookup = lookups + U16(lookups, 2 + 2 * lidx);
697 int type = U16(lookup, 0);
698 int ntabs = U16(lookup, 4);
699 ctx.seqidx = U16(sub, off + 2 + 4 * i);
700 for (j = 0; j < ntabs; j++) {
701 void *tab = lookup + U16(lookup, 6 + 2 * j);
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 type = 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 switch (type) {
731 case 1:
732 otf_gsubtype1(otf, tab, tag, NULL);
733 break;
734 case 3:
735 otf_gsubtype3(otf, tab, tag, NULL);
736 break;
737 case 4:
738 otf_gsubtype4(otf, tab, tag, NULL);
739 break;
740 case 6:
741 otf_gsubtype6(otf, tab, tag, gsub);
742 break;
743 default:
744 otf_unsupported("GSUB", type, 0);
750 /* parse the given gsub language table and its feature tables */
751 static void otf_gsublang(void *otf, void *gsub, void *lang)
753 void *feats = gsub + U16(gsub, 6);
754 int featidx = U16(lang, 2);
755 int nfeat = U16(lang, 4);
756 int i;
757 if (featidx != 0xffff)
758 otf_gsubfeatrec(otf, gsub, feats + 2 + 6 * featidx);
759 for (i = 0; i < nfeat; i++)
760 otf_gsubfeatrec(otf, gsub,
761 feats + 2 + 6 * U16(lang, 6 + 2 * i));
764 static void otf_gsub(void *otf, void *gsub)
766 void *scripts = gsub + U16(gsub, 4);
767 int nscripts, nlangs;
768 void *script;
769 void *grec, *lrec;
770 char tag[8];
771 int i, j;
772 nscripts = U16(scripts, 0);
773 for (i = 0; i < nscripts; i++) {
774 grec = scripts + 2 + 6 * i;
775 memcpy(tag, grec, 4);
776 tag[4] = '\0';
777 if (!trfn_script(tag, nscripts))
778 continue;
779 script = scripts + U16(scripts + 2 + 6 * i, 4);
780 nlangs = U16(script, 2);
781 if (U16(script, 0) && trfn_lang(NULL, nlangs + (U16(script, 0) != 0)))
782 otf_gsublang(otf, gsub, script + U16(script, 0));
783 for (j = 0; j < nlangs; j++) {
784 lrec = script + 4 + 6 * j;
785 memcpy(tag, lrec, 4);
786 tag[4] = '\0';
787 if (trfn_lang(tag, nlangs + (U16(script, 0) != 0)))
788 otf_gsublang(otf, gsub, script + U16(lrec, 4));
793 int xread(int fd, char *buf, int len)
795 int nr = 0;
796 while (nr < len) {
797 int ret = read(fd, buf + nr, len - nr);
798 if (ret == -1 && (errno == EAGAIN || errno == EINTR))
799 continue;
800 if (ret <= 0)
801 break;
802 nr += ret;
804 return nr;
807 static char buf[BUFLEN];
809 int otf_read(void)
811 int i;
812 if (xread(0, buf, sizeof(buf)) <= 0)
813 return 1;
814 upm = U16(otf_table(buf, "head"), 18);
815 otf_cmap(buf, otf_table(buf, "cmap"));
816 otf_post(buf, otf_table(buf, "post"));
817 if (otf_table(buf, "glyf"))
818 otf_glyf(buf, otf_table(buf, "glyf"));
819 otf_hmtx(buf, otf_table(buf, "hmtx"));
820 for (i = 0; i < glyph_n; i++) {
821 trfn_char(glyph_name[i], -1,
822 glyph_code[i] != 0xffff ? glyph_code[i] : 0,
823 owid(glyph_wid[i]),
824 owid(glyph_bbox[i][0]), owid(glyph_bbox[i][1]),
825 owid(glyph_bbox[i][2]), owid(glyph_bbox[i][3]));
827 if (otf_table(buf, "kern"))
828 otf_kern(buf, otf_table(buf, "kern"));
829 return 0;
832 void otf_feat(int r, int k, int w)
834 res = r;
835 kmin = k;
836 warn = w;
837 if (otf_table(buf, "GSUB"))
838 otf_gsub(buf, otf_table(buf, "GSUB"));
839 if (otf_table(buf, "GPOS"))
840 otf_gpos(buf, otf_table(buf, "GPOS"));
843 static char *macset[] = {
844 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
845 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
846 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
847 "comma", "hyphen", "period", "slash", "zero",
848 "one", "two", "three", "four", "five",
849 "six", "seven", "eight", "nine", "colon",
850 "semicolon", "less", "equal", "greater", "question",
851 "at", "A", "B", "C", "D",
852 "E", "F", "G", "H", "I",
853 "J", "K", "L", "M", "N",
854 "O", "P", "Q", "R", "S",
855 "T", "U", "V", "W", "X",
856 "Y", "Z", "bracketleft", "backslash", "bracketright",
857 "asciicircum", "underscore", "grave", "a", "b",
858 "c", "d", "e", "f", "g",
859 "h", "i", "j", "k", "l",
860 "m", "n", "o", "p", "q",
861 "r", "s", "t", "u", "v",
862 "w", "x", "y", "z", "braceleft",
863 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
864 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
865 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
866 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
867 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
868 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
869 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
870 "dagger", "degree", "cent", "sterling", "section",
871 "bullet", "paragraph", "germandbls", "registered", "copyright",
872 "trademark", "acute", "dieresis", "notequal", "AE",
873 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
874 "yen", "mu", "partialdiff", "summation", "product",
875 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
876 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
877 "radical", "florin", "approxequal", "Delta", "guillemotleft",
878 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
879 "Otilde", "OE", "oe", "endash", "emdash",
880 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
881 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
882 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
883 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
884 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
885 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
886 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
887 "dotlessi", "circumflex", "tilde", "macron", "breve",
888 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
889 "caron", "Lslash", "lslash", "Scaron", "scaron",
890 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
891 "Yacute", "yacute", "Thorn", "thorn", "minus",
892 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
893 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
894 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
895 "Ccaron", "ccaron", "dcroat",