9 #define NGLYPHS (1 << 14)
10 #define NLOOKUPS (1 << 12)
12 #define BUFLEN (1 << 23)
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
;
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
];
40 static int upm
; /* units per em */
41 static int res
; /* device resolution */
42 static int kmin
; /* minimum kerning value */
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
)
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
)
62 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
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);
76 for (i
= 0; i
< nrecs
; i
++) {
77 rec
= recs
+ i
* OTFRECLEN
;
78 if (!strncmp(rec
, name
, 4))
79 return otf
+ U32(rec
, 8);
84 /* obtain postscript font name from name table */
85 static void otf_name(void *otf
, void *tab
)
88 void *str
= tab
+ U16(tab
, 4); /* storage area */
89 int n
= U16(tab
, 2); /* number of name records */
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
);
107 /* parse otf cmap format 4 subtable */
108 static void otf_cmap4(void *otf
, void *cmap4
)
111 void *ends
, *begs
, *deltas
, *offsets
;
112 int beg
, end
, delta
, offset
;
114 nsegs
= U16(cmap4
, 6) / 2;
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
);
125 for (j
= beg
; j
<= end
; j
++)
126 glyph_code
[(U16(offsets
+ 2 * i
,
127 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
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 */
143 int nrecs
= U16(cmap
, 2);
145 for (i
= 0; i
< nrecs
; i
++) {
146 rec
= recs
+ i
* CMAPRECLEN
;
149 tab
= cmap
+ U32(rec
, 4);
151 if (plat
== 3 && enc
== 1 && fmt
== 4)
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 */
163 if (U32(post
, 0) != 0x00020000)
166 glyph_n
= U16(post2
, 0);
168 names
= index
+ 2 * glyph_n
;
169 for (i
= 0; i
< glyph_n
; i
++) {
170 idx
= U16(index
, 2 * i
);
172 strcpy(glyph_name
[i
], macset
[idx
]);
174 memcpy(glyph_name
[i
], names
+ cname
+ 1,
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");
189 int n
= U16(maxp
, 4);
190 int fmt
= U16(head
, 50);
192 for (i
= 0; i
< n
; i
++) {
194 gdat
= glyf
+ U32(loca
, 4 * i
);
195 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
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");
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 */
228 for (i
= 0; i
< n
; i
++) {
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
],
245 static int coverage(void *cov
, int *out
)
247 int fmt
= U16(cov
, 0);
253 for (i
= 0; i
< n
; i
++)
254 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
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
++)
267 static int classdef(void *tab
, int *gl
, int *cls
)
269 int fmt
= U16(tab
, 0);
276 for (i
= 0; i
< ngl
; i
++) {
278 cls
[i
] = U16(tab
, 6 + 2 * i
);
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
++) {
288 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
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
)
308 for (i
= 0; i
< nsrc
; 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
)
325 for (i
= 0; i
< 8; i
++)
331 static void valuerecord_print(int fmt
, void *rec
)
336 for (i
= 0; i
< 8; i
++) {
337 if (fmt
& (1 << i
)) {
338 vals
[i
] = uwid(S16(rec
, off
));
343 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
346 static int valuerecord_small(int fmt
, void *rec
)
350 for (i
= 0; i
< 8; i
++) {
351 if (fmt
& (1 << i
)) {
352 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
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);
367 int vlen
= valuerecord_len(vfmt
);
369 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
371 for (i
= 0; i
< ncov
; i
++) {
372 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
373 valuerecord_print(vfmt
, 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
);
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 */
396 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
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
))
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
);
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
))
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
);
450 /* cursive attachment positioning */
451 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
453 int fmt
= U16(sub
, 0);
456 coverage(sub
+ U16(sub
, 2), cov
);
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
]]);
465 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
466 uwid(S16(sub
, prev
+ 4)));
470 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
471 uwid(S16(sub
, next
+ 4)));
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
)
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
)
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
)
518 int fmt
= U16(sub
, 0);
522 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
524 for (i
= 0; i
< ncov
; i
++) {
525 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
527 printf(" -%s +%s", glyph_name
[cov
[i
]],
528 glyph_name
[cov
[i
] + S16(sub
, 4)]);
529 gctx_lookahead(ctx
, 1);
535 for (i
= 0; i
< n
; i
++) {
536 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
538 printf(" -%s +%s", glyph_name
[cov
[i
]],
539 glyph_name
[U16(sub
, 6 + 2 * i
)]);
540 gctx_lookahead(ctx
, 1);
546 /* alternate substitution */
547 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
550 int fmt
= U16(sub
, 0);
554 coverage(sub
+ U16(sub
, 2), cov
);
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));
562 printf(" -%s +%s", glyph_name
[cov
[i
]],
563 glyph_name
[U16(alt
, 2 + 2 * j
)]);
564 gctx_lookahead(ctx
, 1);
570 /* ligature substitution */
571 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
573 int fmt
= U16(sub
, 0);
578 coverage(sub
+ U16(sub
, 2), cov
);
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
));
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
);
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);
605 int i
, j
, nsub
, ncov
;
608 otf_unsupported("GSUB", 6, fmt
);
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
);
639 if (type
== 7) { /* extension substitution */
641 tab
= tab
+ U32(tab
, 4);
644 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
646 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
648 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
653 /* an otf gsub/gpos lookup */
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);
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
);
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);
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
);
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
;
709 nscripts
= U16(scripts
, 0);
710 for (i
= 0; i
< nscripts
; i
++) {
711 grec
= scripts
+ 2 + 6 * i
;
712 memcpy(tag
, grec
, 4);
714 if (!trfn_script(tag
, nscripts
))
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);
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
);
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
);
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
);
746 if (type
== 9) { /* extension positioning */
748 tab
= tab
+ U32(tab
, 4);
752 otf_gpostype1(otf
, tab
, tag
);
755 otf_gpostype2(otf
, tab
, tag
);
758 otf_gpostype3(otf
, tab
, tag
);
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
);
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
);
781 if (type
== 7) { /* extension substitution */
783 tab
= tab
+ U32(tab
, 4);
787 otf_gsubtype1(otf
, tab
, tag
, NULL
);
790 otf_gsubtype3(otf
, tab
, tag
, NULL
);
793 otf_gsubtype4(otf
, tab
, tag
, NULL
);
796 otf_gsubtype6(otf
, tab
, tag
, gsub
);
799 otf_unsupported("GSUB", type
, 0);
805 int xread(int fd
, char *buf
, int len
)
809 int ret
= read(fd
, buf
+ nr
, len
- nr
);
810 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
819 static char buf
[BUFLEN
];
824 if (xread(0, buf
, sizeof(buf
)) <= 0)
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,
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"));
845 void otf_feat(int r
, int k
, int 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"));
857 static int *ggrp_g
[NGRPS
];
858 static int ggrp_len
[NGRPS
];
861 static int ggrp_find(int *src
, int n
)
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
])
876 int ggrp_make(int *src
, int n
)
878 int id
= ggrp_find(src
, n
);
883 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
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
]]);
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",