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 GCTXLEN 16 /* number of context backtrack coverage arrays */
24 typedef unsigned int u32
;
25 typedef unsigned short u16
;
26 typedef unsigned char u8
;
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
];
35 static int upm
; /* units per em */
36 static int res
; /* device resolution */
37 static int kmin
; /* minimum kerning value */
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
)
50 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
53 /* report unsupported otf tables */
54 static void otf_unsupported(char *sub
, int type
, int fmt
)
57 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
59 fprintf(stderr
, " format %d", fmt
);
60 fprintf(stderr
, "\n");
64 /* find the otf table with the given name */
65 static void *otf_table(void *otf
, char *name
)
67 int nrecs
= U16(otf
, 4);
69 for (i
= 0; i
< nrecs
; i
++) {
70 void *rec
= otf
+ 12 + i
* 16; /* an otf table record */
71 if (!strncmp(rec
, name
, 4))
72 return otf
+ U32(rec
, 8);
77 /* obtain postscript font name from name table */
78 static void otf_name(void *otf
, void *tab
)
81 void *str
= tab
+ U16(tab
, 4); /* storage area */
82 int n
= U16(tab
, 2); /* number of name records */
84 for (i
= 0; i
< n
; i
++) {
85 void *rec
= tab
+ 6 + 12 * i
;
86 int pid
= U16(rec
, 0); /* platform id */
87 int eid
= U16(rec
, 2); /* encoding id */
88 int lid
= U16(rec
, 4); /* language id */
89 int nid
= U16(rec
, 6); /* name id */
90 int len
= U16(rec
, 8); /* string length */
91 int off
= U16(rec
, 10); /* string offset */
92 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
93 memcpy(name
, str
+ off
, len
);
100 /* parse otf cmap format 4 subtable */
101 static void otf_cmap4(void *otf
, void *cmap4
)
104 void *ends
, *begs
, *deltas
, *offsets
;
105 int beg
, end
, delta
, offset
;
107 nsegs
= U16(cmap4
, 6) / 2;
109 begs
= ends
+ 2 * nsegs
+ 2;
110 deltas
= begs
+ 2 * nsegs
;
111 offsets
= deltas
+ 2 * nsegs
;
112 for (i
= 0; i
< nsegs
; i
++) {
113 beg
= U16(begs
, 2 * i
);
114 end
= U16(ends
, 2 * i
);
115 delta
= U16(deltas
, 2 * i
);
116 offset
= U16(offsets
, 2 * i
);
118 for (j
= beg
; j
<= end
; j
++)
119 glyph_code
[(U16(offsets
+ 2 * i
,
120 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
122 for (j
= beg
; j
<= end
; j
++)
123 glyph_code
[(j
+ delta
) & 0xffff] = j
;
128 /* parse otf cmap header */
129 static void otf_cmap(void *otf
, void *cmap
)
131 int nrecs
= U16(cmap
, 2);
133 for (i
= 0; i
< nrecs
; i
++) {
134 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
135 int plat
= U16(rec
, 0);
136 int enc
= U16(rec
, 2);
137 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
138 int fmt
= U16(tab
, 0);
139 if (plat
== 3 && enc
== 1 && fmt
== 4)
144 static void otf_post(void *otf
, void *post
)
146 void *post2
; /* version 2.0 header */
147 void *index
; /* glyph name indices */
148 void *names
; /* glyph names */
151 if (U32(post
, 0) != 0x00020000)
154 glyph_n
= U16(post2
, 0);
156 names
= index
+ 2 * glyph_n
;
157 for (i
= 0; i
< glyph_n
; i
++) {
158 int idx
= U16(index
, 2 * i
);
160 strcpy(glyph_name
[i
], macset
[idx
]);
162 memcpy(glyph_name
[i
], names
+ cname
+ 1,
164 glyph_name
[i
][U8(names
, cname
)] = '\0';
165 cname
+= U8(names
, cname
) + 1;
170 static void otf_glyf(void *otf
, void *glyf
)
172 void *maxp
= otf_table(otf
, "maxp");
173 void *head
= otf_table(otf
, "head");
174 void *loca
= otf_table(otf
, "loca");
177 int n
= U16(maxp
, 4);
178 int fmt
= U16(head
, 50);
180 for (i
= 0; i
< n
; i
++) {
182 gdat
= glyf
+ U32(loca
, 4 * i
);
183 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
185 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
186 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
188 if (gdat
< gdat_next
)
189 for (j
= 0; j
< 4; j
++)
190 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
194 static void otf_hmtx(void *otf
, void *hmtx
)
196 void *hhea
= otf_table(otf
, "hhea");
200 for (i
= 0; i
< n
; i
++)
201 glyph_wid
[i
] = U16(hmtx
, i
* 4);
202 for (i
= n
; i
< glyph_n
; i
++)
203 glyph_wid
[i
] = glyph_wid
[n
- 1];
206 static void otf_kern(void *otf
, void *kern
)
210 int n
= U16(kern
, 2); /* number of kern subtables */
211 for (i
= 0; i
< n
; i
++) {
212 void *tab
= kern
+ off
; /* a kern subtable */
213 int cov
= U16(tab
, 4);
215 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
216 int npairs
= U16(tab
, 6);
217 for (j
= 0; j
< npairs
; j
++) {
218 int c1
= U16(tab
, 14 + 6 * j
);
219 int c2
= U16(tab
, 14 + 6 * j
+ 2);
220 int val
= S16(tab
, 14 + 6 * j
+ 4);
221 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
228 static int coverage(void *cov
, int *out
)
230 int fmt
= U16(cov
, 0);
236 for (i
= 0; i
< n
; i
++)
237 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
240 for (i
= 0; i
< n
; i
++) {
241 beg
= U16(cov
, 4 + 6 * i
);
242 end
= U16(cov
, 4 + 6 * i
+ 2);
243 for (j
= beg
; j
<= end
; j
++)
250 static int classdef(void *tab
, int *gl
, int *cls
)
252 int fmt
= U16(tab
, 0);
256 int beg
= U16(tab
, 2);
258 for (i
= 0; i
< ngl
; i
++) {
260 cls
[i
] = U16(tab
, 6 + 2 * i
);
265 for (i
= 0; i
< n
; i
++) {
266 int beg
= U16(tab
, 4 + 6 * i
);
267 int end
= U16(tab
, 4 + 6 * i
+ 2);
268 for (j
= beg
; j
<= end
; j
++) {
270 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
278 static int intcmp(void *v1
, void *v2
)
280 return *(int *) v1
- *(int *) v2
;
283 int ggrp_make(int *src
, int n
);
285 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
290 for (i
= 0; i
< nsrc
; i
++)
293 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
294 return ggrp_make(g
, n
);
297 static int ggrp_coverage(int *g
, int n
)
299 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
300 return ggrp_make(g
, n
);
303 static int valuerecord_len(int fmt
)
307 for (i
= 0; i
< 8; i
++)
313 static void valuerecord_print(int fmt
, void *rec
)
318 for (i
= 0; i
< 8; i
++) {
319 if (fmt
& (1 << i
)) {
320 vals
[i
] = uwid(S16(rec
, off
));
325 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
328 static int valuerecord_small(int fmt
, void *rec
)
332 for (i
= 0; i
< 8; i
++) {
333 if (fmt
& (1 << i
)) {
334 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
342 /* single adjustment positioning */
343 static void otf_gpostype1(void *otf
, void *sub
, char *feat
)
345 int fmt
= U16(sub
, 0);
346 int vfmt
= U16(sub
, 4);
349 int vlen
= valuerecord_len(vfmt
);
351 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
353 for (i
= 0; i
< ncov
; i
++) {
354 if (valuerecord_small(vfmt
, sub
+ 6))
356 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
357 valuerecord_print(vfmt
, sub
+ 6);
363 for (i
= 0; i
< nvals
; i
++) {
364 if (valuerecord_small(vfmt
, sub
+ 6))
366 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
367 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
373 /* pair adjustment positioning */
374 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
376 int fmt
= U16(sub
, 0);
377 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
378 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
379 int fmtoff1
, fmtoff2
;
380 int vrlen
; /* the length of vfmt1 and vfmt2 */
382 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
385 int nc1
= U16(sub
, 8);
386 coverage(sub
+ U16(sub
, 2), cov
);
387 for (i
= 0; i
< nc1
; i
++) {
388 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
389 int nc2
= U16(c2
, 0);
390 for (j
= 0; j
< nc2
; j
++) {
391 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
392 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
393 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
394 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
395 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
397 printf("gpos %s 2", feat
);
398 printf(" %s", glyph_name
[cov
[i
]]);
399 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
400 printf(" %s", glyph_name
[second
]);
401 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
407 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
408 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
409 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
410 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
411 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
412 int ncls1
= U16(sub
, 12);
413 int ncls2
= U16(sub
, 14);
414 for (i
= 0; i
< ncls1
; i
++)
415 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
416 for (i
= 0; i
< ncls2
; i
++)
417 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
418 for (i
= 0; i
< ncls1
; i
++) {
419 for (j
= 0; j
< ncls2
; j
++) {
420 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
421 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
422 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
423 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
425 printf("gpos %s %d", feat
, 2);
426 printf(" @%d", grp1
[i
]);
427 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
428 printf(" @%d", grp2
[j
]);
429 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
436 /* cursive attachment positioning */
437 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
439 int fmt
= U16(sub
, 0);
442 coverage(sub
+ U16(sub
, 2), cov
);
446 for (i
= 0; i
< n
; i
++) {
447 int prev
= U16(sub
, 6 + 4 * i
);
448 int next
= U16(sub
, 6 + 4 * i
+ 2);
449 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
451 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
452 uwid(S16(sub
, prev
+ 4)));
456 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
457 uwid(S16(sub
, next
+ 4)));
466 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
467 int igrp
[GCTXLEN
]; /* input coverage arrays */
468 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
469 int bn
, in
, ln
; /* size of b[], i[], l[] */
470 int seqidx
; /* sequence index */
473 static int gctx_len(struct gctx
*ctx
, int patlen
)
475 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
478 static void gctx_backtrack(struct gctx
*ctx
)
483 for (i
= 0; i
< ctx
->bn
; i
++)
484 printf(" =@%d", ctx
->bgrp
[i
]);
485 for (i
= 0; i
< ctx
->seqidx
; i
++)
486 printf(" =@%d", ctx
->igrp
[i
]);
489 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
494 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
495 printf(" =@%d", ctx
->igrp
[i
]);
496 for (i
= 0; i
< ctx
->ln
; i
++)
497 printf(" =@%d", ctx
->lgrp
[i
]);
500 /* single substitution */
501 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
504 int fmt
= U16(sub
, 0);
507 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
509 for (i
= 0; i
< ncov
; i
++) {
510 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
512 printf(" -%s +%s", glyph_name
[cov
[i
]],
513 glyph_name
[cov
[i
] + S16(sub
, 4)]);
514 gctx_lookahead(ctx
, 1);
520 for (i
= 0; i
< n
; i
++) {
521 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
523 printf(" -%s +%s", glyph_name
[cov
[i
]],
524 glyph_name
[U16(sub
, 6 + 2 * i
)]);
525 gctx_lookahead(ctx
, 1);
531 /* alternate substitution */
532 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
535 int fmt
= U16(sub
, 0);
539 coverage(sub
+ U16(sub
, 2), cov
);
541 for (i
= 0; i
< n
; i
++) {
542 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
543 int nalt
= U16(alt
, 0);
544 for (j
= 0; j
< nalt
; j
++) {
545 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
547 printf(" -%s +%s", glyph_name
[cov
[i
]],
548 glyph_name
[U16(alt
, 2 + 2 * j
)]);
549 gctx_lookahead(ctx
, 1);
555 /* ligature substitution */
556 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
558 int fmt
= U16(sub
, 0);
563 coverage(sub
+ U16(sub
, 2), cov
);
565 for (i
= 0; i
< n
; i
++) {
566 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
567 int nset
= U16(set
, 0);
568 for (j
= 0; j
< nset
; j
++) {
569 void *lig
= set
+ U16(set
, 2 + 2 * j
);
570 int nlig
= U16(lig
, 2);
571 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
573 printf(" -%s", glyph_name
[cov
[i
]]);
574 for (k
= 0; k
< nlig
- 1; k
++)
575 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
576 printf(" +%s", glyph_name
[U16(lig
, 0)]);
577 gctx_lookahead(ctx
, nlig
);
583 /* chaining contextual substitution */
584 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
586 struct gctx ctx
= {{0}};
587 void *lookups
= gsub
+ U16(gsub
, 8);
588 int fmt
= U16(sub
, 0);
590 int i
, j
, nsub
, ncov
;
593 otf_unsupported("GSUB", 6, fmt
);
596 ctx
.bn
= U16(sub
, off
);
597 for (i
= 0; i
< ctx
.bn
; i
++) {
598 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
599 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
601 off
+= 2 + 2 * ctx
.bn
;
602 ctx
.in
= U16(sub
, off
);
603 for (i
= 0; i
< ctx
.in
; i
++) {
604 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
605 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
607 off
+= 2 + 2 * ctx
.in
;
608 ctx
.ln
= U16(sub
, off
);
609 for (i
= 0; i
< ctx
.ln
; i
++) {
610 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
611 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
613 off
+= 2 + 2 * ctx
.ln
;
614 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
615 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
616 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
617 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
618 int ltype
= U16(lookup
, 0);
619 int ntabs
= U16(lookup
, 4);
620 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
621 for (j
= 0; j
< ntabs
; j
++) {
622 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
624 if (type
== 7) { /* extension substitution */
626 tab
= tab
+ U32(tab
, 4);
629 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
631 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
633 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
638 /* an otf gsub/gpos lookup */
640 char feat
[8]; /* feature name */
641 int lookup
; /* index into the lookup table */
644 /* parse the given gsub/gpos feature table */
645 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, struct otflookup
*lookups
)
647 void *feats
= gtab
+ U16(gtab
, 6);
648 void *feat
= feats
+ U16(featrec
, 4);
649 int nlookups
= U16(feat
, 2);
651 for (i
= 0; i
< nlookups
; i
++) {
652 memcpy(lookups
[i
].feat
, featrec
, 4);
653 lookups
[i
].feat
[4] = '\0';
654 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
659 /* parse the given language table and its feature tables */
660 static int otf_lang(void *otf
, void *gtab
, void *lang
, struct otflookup
*lookups
)
662 void *feats
= gtab
+ U16(gtab
, 6);
663 int featidx
= U16(lang
, 2);
664 int nfeat
= U16(lang
, 4);
667 if (featidx
!= 0xffff)
668 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, lookups
+ n
);
669 for (i
= 0; i
< nfeat
; i
++)
670 n
+= otf_featrec(otf
, gtab
,
671 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), lookups
+ n
);
675 static int lookupcmp(void *v1
, void *v2
)
677 struct otflookup
*l1
= v1
;
678 struct otflookup
*l2
= v2
;
679 if (trfn_featrank(l1
->feat
) != trfn_featrank(l2
->feat
))
680 return trfn_featrank(l1
->feat
) - trfn_featrank(l2
->feat
);
681 return l1
->lookup
- l2
->lookup
;
684 /* extract lookup tables for all features of the given gsub/gpos table */
685 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
687 void *scripts
= gpos
+ U16(gpos
, 4);
688 int nscripts
, nlangs
;
693 nscripts
= U16(scripts
, 0);
694 for (i
= 0; i
< nscripts
; i
++) {
695 void *grec
= scripts
+ 2 + 6 * i
;
696 memcpy(tag
, grec
, 4);
698 if (!trfn_script(tag
, nscripts
))
700 script
= scripts
+ U16(grec
, 4);
701 nlangs
= U16(script
, 2);
702 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
703 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0), lookups
+ n
);
704 for (j
= 0; j
< nlangs
; j
++) {
705 void *lrec
= script
+ 4 + 6 * j
;
706 memcpy(tag
, lrec
, 4);
708 if (trfn_lang(tag
, nlangs
+ (U16(script
, 0) != 0)))
709 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4), lookups
+ n
);
712 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
716 static void otf_gpos(void *otf
, void *gpos
)
718 struct otflookup lookups
[NLOOKUPS
];
719 void *lookuplist
= gpos
+ U16(gpos
, 8);
720 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
722 for (i
= 0; i
< nlookups
; i
++) {
723 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
724 char *tag
= lookups
[i
].feat
;
725 int ltype
= U16(lookup
, 0);
726 int ntabs
= U16(lookup
, 4);
727 for (j
= 0; j
< ntabs
; j
++) {
728 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
730 if (type
== 9) { /* extension positioning */
732 tab
= tab
+ U32(tab
, 4);
736 otf_gpostype1(otf
, tab
, tag
);
739 otf_gpostype2(otf
, tab
, tag
);
742 otf_gpostype3(otf
, tab
, tag
);
745 otf_unsupported("GPOS", type
, 0);
751 static void otf_gsub(void *otf
, void *gsub
)
753 struct otflookup lookups
[NLOOKUPS
];
754 void *lookuplist
= gsub
+ U16(gsub
, 8);
755 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
757 for (i
= 0; i
< nlookups
; i
++) {
758 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
759 char *tag
= lookups
[i
].feat
;
760 int ltype
= U16(lookup
, 0);
761 int ntabs
= U16(lookup
, 4);
762 for (j
= 0; j
< ntabs
; j
++) {
763 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
765 if (type
== 7) { /* extension substitution */
767 tab
= tab
+ U32(tab
, 4);
771 otf_gsubtype1(otf
, tab
, tag
, NULL
);
774 otf_gsubtype3(otf
, tab
, tag
, NULL
);
777 otf_gsubtype4(otf
, tab
, tag
, NULL
);
780 otf_gsubtype6(otf
, tab
, tag
, gsub
);
783 otf_unsupported("GSUB", type
, 0);
789 static int xread(int fd
, char *buf
, int len
)
793 int ret
= read(fd
, buf
+ nr
, len
- nr
);
794 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
803 static char buf
[BUFLEN
];
808 if (xread(0, buf
, sizeof(buf
)) <= 0)
810 upm
= U16(otf_table(buf
, "head"), 18);
811 otf_name(buf
, otf_table(buf
, "name"));
812 otf_cmap(buf
, otf_table(buf
, "cmap"));
813 otf_post(buf
, otf_table(buf
, "post"));
814 if (otf_table(buf
, "glyf"))
815 otf_glyf(buf
, otf_table(buf
, "glyf"));
816 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
817 for (i
= 0; i
< glyph_n
; i
++) {
818 trfn_char(glyph_name
[i
], -1,
819 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
821 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
822 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
824 if (otf_table(buf
, "kern"))
825 otf_kern(buf
, otf_table(buf
, "kern"));
829 void otf_feat(int r
, int k
, int w
)
834 if (otf_table(buf
, "GSUB"))
835 otf_gsub(buf
, otf_table(buf
, "GSUB"));
836 if (otf_table(buf
, "GPOS"))
837 otf_gpos(buf
, otf_table(buf
, "GPOS"));
841 static int *ggrp_g
[NGRPS
];
842 static int ggrp_len
[NGRPS
];
845 static int ggrp_find(int *src
, int n
)
848 for (i
= 0; i
< ggrp_n
; i
++) {
849 if (ggrp_len
[i
] == n
) {
850 for (j
= 0; j
< n
; j
++)
851 if (src
[j
] != ggrp_g
[i
][j
])
860 int ggrp_make(int *src
, int n
)
862 int id
= ggrp_find(src
, n
);
867 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
869 for (i
= 0; i
< n
; i
++)
870 ggrp_g
[id
][i
] = src
[i
];
871 printf("ggrp %d %d", id
, n
);
872 for (i
= 0; i
< n
; i
++)
873 printf(" %s", glyph_name
[src
[i
]]);
878 static char *macset
[] = {
879 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
880 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
881 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
882 "comma", "hyphen", "period", "slash", "zero",
883 "one", "two", "three", "four", "five",
884 "six", "seven", "eight", "nine", "colon",
885 "semicolon", "less", "equal", "greater", "question",
886 "at", "A", "B", "C", "D",
887 "E", "F", "G", "H", "I",
888 "J", "K", "L", "M", "N",
889 "O", "P", "Q", "R", "S",
890 "T", "U", "V", "W", "X",
891 "Y", "Z", "bracketleft", "backslash", "bracketright",
892 "asciicircum", "underscore", "grave", "a", "b",
893 "c", "d", "e", "f", "g",
894 "h", "i", "j", "k", "l",
895 "m", "n", "o", "p", "q",
896 "r", "s", "t", "u", "v",
897 "w", "x", "y", "z", "braceleft",
898 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
899 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
900 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
901 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
902 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
903 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
904 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
905 "dagger", "degree", "cent", "sterling", "section",
906 "bullet", "paragraph", "germandbls", "registered", "copyright",
907 "trademark", "acute", "dieresis", "notequal", "AE",
908 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
909 "yen", "mu", "partialdiff", "summation", "product",
910 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
911 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
912 "radical", "florin", "approxequal", "Delta", "guillemotleft",
913 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
914 "Otilde", "OE", "oe", "endash", "emdash",
915 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
916 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
917 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
918 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
919 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
920 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
921 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
922 "dotlessi", "circumflex", "tilde", "macron", "breve",
923 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
924 "caron", "Lslash", "lslash", "Scaron", "scaron",
925 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
926 "Yacute", "yacute", "Thorn", "thorn", "minus",
927 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
928 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
929 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
930 "Ccaron", "ccaron", "dcroat",