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 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
355 valuerecord_print(vfmt
, sub
+ 6);
361 for (i
= 0; i
< nvals
; i
++) {
362 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
363 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
369 /* pair adjustment positioning */
370 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
372 int fmt
= U16(sub
, 0);
373 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
374 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
375 int fmtoff1
, fmtoff2
;
376 int vrlen
; /* the length of vfmt1 and vfmt2 */
378 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
381 int nc1
= U16(sub
, 8);
382 coverage(sub
+ U16(sub
, 2), cov
);
383 for (i
= 0; i
< nc1
; i
++) {
384 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
385 int nc2
= U16(c2
, 0);
386 for (j
= 0; j
< nc2
; j
++) {
387 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
388 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
389 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
390 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
391 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
393 printf("gpos %s 2", feat
);
394 printf(" %s", glyph_name
[cov
[i
]]);
395 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
396 printf(" %s", glyph_name
[second
]);
397 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
403 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
404 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
405 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
406 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
407 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
408 int ncls1
= U16(sub
, 12);
409 int ncls2
= U16(sub
, 14);
410 for (i
= 0; i
< ncls1
; i
++)
411 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
412 for (i
= 0; i
< ncls2
; i
++)
413 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
414 for (i
= 0; i
< ncls1
; i
++) {
415 for (j
= 0; j
< ncls2
; j
++) {
416 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
417 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
418 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
419 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
421 printf("gpos %s %d", feat
, 2);
422 printf(" @%d", grp1
[i
]);
423 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
424 printf(" @%d", grp2
[j
]);
425 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
432 /* cursive attachment positioning */
433 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
435 int fmt
= U16(sub
, 0);
438 coverage(sub
+ U16(sub
, 2), cov
);
442 for (i
= 0; i
< n
; i
++) {
443 int prev
= U16(sub
, 6 + 4 * i
);
444 int next
= U16(sub
, 6 + 4 * i
+ 2);
445 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
447 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
448 uwid(S16(sub
, prev
+ 4)));
452 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
453 uwid(S16(sub
, next
+ 4)));
462 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
463 int igrp
[GCTXLEN
]; /* input coverage arrays */
464 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
465 int bn
, in
, ln
; /* size of b[], i[], l[] */
466 int seqidx
; /* sequence index */
469 static int gctx_len(struct gctx
*ctx
, int patlen
)
471 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
474 static void gctx_backtrack(struct gctx
*ctx
)
479 for (i
= 0; i
< ctx
->bn
; i
++)
480 printf(" =@%d", ctx
->bgrp
[i
]);
481 for (i
= 0; i
< ctx
->seqidx
; i
++)
482 printf(" =@%d", ctx
->igrp
[i
]);
485 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
490 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
491 printf(" =@%d", ctx
->igrp
[i
]);
492 for (i
= 0; i
< ctx
->ln
; i
++)
493 printf(" =@%d", ctx
->lgrp
[i
]);
496 /* single substitution */
497 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
500 int fmt
= U16(sub
, 0);
503 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
505 for (i
= 0; i
< ncov
; i
++) {
506 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
508 printf(" -%s +%s", glyph_name
[cov
[i
]],
509 glyph_name
[cov
[i
] + S16(sub
, 4)]);
510 gctx_lookahead(ctx
, 1);
516 for (i
= 0; i
< n
; i
++) {
517 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
519 printf(" -%s +%s", glyph_name
[cov
[i
]],
520 glyph_name
[U16(sub
, 6 + 2 * i
)]);
521 gctx_lookahead(ctx
, 1);
527 /* alternate substitution */
528 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
531 int fmt
= U16(sub
, 0);
535 coverage(sub
+ U16(sub
, 2), cov
);
537 for (i
= 0; i
< n
; i
++) {
538 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
539 int nalt
= U16(alt
, 0);
540 for (j
= 0; j
< nalt
; j
++) {
541 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
543 printf(" -%s +%s", glyph_name
[cov
[i
]],
544 glyph_name
[U16(alt
, 2 + 2 * j
)]);
545 gctx_lookahead(ctx
, 1);
551 /* ligature substitution */
552 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
554 int fmt
= U16(sub
, 0);
559 coverage(sub
+ U16(sub
, 2), cov
);
561 for (i
= 0; i
< n
; i
++) {
562 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
563 int nset
= U16(set
, 0);
564 for (j
= 0; j
< nset
; j
++) {
565 void *lig
= set
+ U16(set
, 2 + 2 * j
);
566 int nlig
= U16(lig
, 2);
567 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
569 printf(" -%s", glyph_name
[cov
[i
]]);
570 for (k
= 0; k
< nlig
- 1; k
++)
571 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
572 printf(" +%s", glyph_name
[U16(lig
, 0)]);
573 gctx_lookahead(ctx
, nlig
);
579 /* chaining contextual substitution */
580 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
582 struct gctx ctx
= {{0}};
583 void *lookups
= gsub
+ U16(gsub
, 8);
584 int fmt
= U16(sub
, 0);
586 int i
, j
, nsub
, ncov
;
589 otf_unsupported("GSUB", 6, fmt
);
592 ctx
.bn
= U16(sub
, off
);
593 for (i
= 0; i
< ctx
.bn
; i
++) {
594 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
595 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
597 off
+= 2 + 2 * ctx
.bn
;
598 ctx
.in
= U16(sub
, off
);
599 for (i
= 0; i
< ctx
.in
; i
++) {
600 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
601 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
603 off
+= 2 + 2 * ctx
.in
;
604 ctx
.ln
= U16(sub
, off
);
605 for (i
= 0; i
< ctx
.ln
; i
++) {
606 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
607 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
609 off
+= 2 + 2 * ctx
.ln
;
610 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
611 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
612 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
613 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
614 int ltype
= U16(lookup
, 0);
615 int ntabs
= U16(lookup
, 4);
616 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
617 for (j
= 0; j
< ntabs
; j
++) {
618 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
620 if (type
== 7) { /* extension substitution */
622 tab
= tab
+ U32(tab
, 4);
625 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
627 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
629 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
634 /* an otf gsub/gpos lookup */
636 char feat
[8]; /* feature name */
637 int lookup
; /* index into the lookup table */
640 /* parse the given gsub/gpos feature table */
641 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, struct otflookup
*lookups
)
643 void *feats
= gtab
+ U16(gtab
, 6);
644 void *feat
= feats
+ U16(featrec
, 4);
645 int nlookups
= U16(feat
, 2);
647 for (i
= 0; i
< nlookups
; i
++) {
648 memcpy(lookups
[i
].feat
, featrec
, 4);
649 lookups
[i
].feat
[4] = '\0';
650 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
655 /* parse the given language table and its feature tables */
656 static int otf_lang(void *otf
, void *gtab
, void *lang
, struct otflookup
*lookups
)
658 void *feats
= gtab
+ U16(gtab
, 6);
659 int featidx
= U16(lang
, 2);
660 int nfeat
= U16(lang
, 4);
663 if (featidx
!= 0xffff)
664 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, lookups
+ n
);
665 for (i
= 0; i
< nfeat
; i
++)
666 n
+= otf_featrec(otf
, gtab
,
667 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), lookups
+ n
);
671 static int lookupcmp(void *v1
, void *v2
)
673 struct otflookup
*l1
= v1
;
674 struct otflookup
*l2
= v2
;
675 if (trfn_featrank(l1
->feat
) != trfn_featrank(l2
->feat
))
676 return trfn_featrank(l1
->feat
) - trfn_featrank(l2
->feat
);
677 return l1
->lookup
- l2
->lookup
;
680 /* extract lookup tables for all features of the given gsub/gpos table */
681 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
683 void *scripts
= gpos
+ U16(gpos
, 4);
684 int nscripts
, nlangs
;
689 nscripts
= U16(scripts
, 0);
690 for (i
= 0; i
< nscripts
; i
++) {
691 void *grec
= scripts
+ 2 + 6 * i
;
692 memcpy(tag
, grec
, 4);
694 if (!trfn_script(tag
, nscripts
))
696 script
= scripts
+ U16(grec
, 4);
697 nlangs
= U16(script
, 2);
698 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
699 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0), lookups
+ n
);
700 for (j
= 0; j
< nlangs
; j
++) {
701 void *lrec
= script
+ 4 + 6 * j
;
702 memcpy(tag
, lrec
, 4);
704 if (trfn_lang(tag
, nlangs
+ (U16(script
, 0) != 0)))
705 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4), lookups
+ n
);
708 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
712 static void otf_gpos(void *otf
, void *gpos
)
714 struct otflookup lookups
[NLOOKUPS
];
715 void *lookuplist
= gpos
+ U16(gpos
, 8);
716 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
718 for (i
= 0; i
< nlookups
; i
++) {
719 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
720 char *tag
= lookups
[i
].feat
;
721 int ltype
= U16(lookup
, 0);
722 int ntabs
= U16(lookup
, 4);
723 for (j
= 0; j
< ntabs
; j
++) {
724 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
726 if (type
== 9) { /* extension positioning */
728 tab
= tab
+ U32(tab
, 4);
732 otf_gpostype1(otf
, tab
, tag
);
735 otf_gpostype2(otf
, tab
, tag
);
738 otf_gpostype3(otf
, tab
, tag
);
741 otf_unsupported("GPOS", type
, 0);
747 static void otf_gsub(void *otf
, void *gsub
)
749 struct otflookup lookups
[NLOOKUPS
];
750 void *lookuplist
= gsub
+ U16(gsub
, 8);
751 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
753 for (i
= 0; i
< nlookups
; i
++) {
754 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
755 char *tag
= lookups
[i
].feat
;
756 int ltype
= U16(lookup
, 0);
757 int ntabs
= U16(lookup
, 4);
758 for (j
= 0; j
< ntabs
; j
++) {
759 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
761 if (type
== 7) { /* extension substitution */
763 tab
= tab
+ U32(tab
, 4);
767 otf_gsubtype1(otf
, tab
, tag
, NULL
);
770 otf_gsubtype3(otf
, tab
, tag
, NULL
);
773 otf_gsubtype4(otf
, tab
, tag
, NULL
);
776 otf_gsubtype6(otf
, tab
, tag
, gsub
);
779 otf_unsupported("GSUB", type
, 0);
785 static int xread(int fd
, char *buf
, int len
)
789 int ret
= read(fd
, buf
+ nr
, len
- nr
);
790 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
799 static char buf
[BUFLEN
];
804 if (xread(0, buf
, sizeof(buf
)) <= 0)
806 upm
= U16(otf_table(buf
, "head"), 18);
807 otf_name(buf
, otf_table(buf
, "name"));
808 otf_cmap(buf
, otf_table(buf
, "cmap"));
809 otf_post(buf
, otf_table(buf
, "post"));
810 if (otf_table(buf
, "glyf"))
811 otf_glyf(buf
, otf_table(buf
, "glyf"));
812 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
813 for (i
= 0; i
< glyph_n
; i
++) {
814 trfn_char(glyph_name
[i
], -1,
815 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
817 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
818 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
820 if (otf_table(buf
, "kern"))
821 otf_kern(buf
, otf_table(buf
, "kern"));
825 void otf_feat(int r
, int k
, int w
)
830 if (otf_table(buf
, "GSUB"))
831 otf_gsub(buf
, otf_table(buf
, "GSUB"));
832 if (otf_table(buf
, "GPOS"))
833 otf_gpos(buf
, otf_table(buf
, "GPOS"));
837 static int *ggrp_g
[NGRPS
];
838 static int ggrp_len
[NGRPS
];
841 static int ggrp_find(int *src
, int n
)
844 for (i
= 0; i
< ggrp_n
; i
++) {
845 if (ggrp_len
[i
] == n
) {
846 for (j
= 0; j
< n
; j
++)
847 if (src
[j
] != ggrp_g
[i
][j
])
856 int ggrp_make(int *src
, int n
)
858 int id
= ggrp_find(src
, n
);
863 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
865 for (i
= 0; i
< n
; i
++)
866 ggrp_g
[id
][i
] = src
[i
];
867 printf("ggrp %d %d", id
, n
);
868 for (i
= 0; i
< n
; i
++)
869 printf(" %s", glyph_name
[src
[i
]]);
874 static char *macset
[] = {
875 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
876 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
877 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
878 "comma", "hyphen", "period", "slash", "zero",
879 "one", "two", "three", "four", "five",
880 "six", "seven", "eight", "nine", "colon",
881 "semicolon", "less", "equal", "greater", "question",
882 "at", "A", "B", "C", "D",
883 "E", "F", "G", "H", "I",
884 "J", "K", "L", "M", "N",
885 "O", "P", "Q", "R", "S",
886 "T", "U", "V", "W", "X",
887 "Y", "Z", "bracketleft", "backslash", "bracketright",
888 "asciicircum", "underscore", "grave", "a", "b",
889 "c", "d", "e", "f", "g",
890 "h", "i", "j", "k", "l",
891 "m", "n", "o", "p", "q",
892 "r", "s", "t", "u", "v",
893 "w", "x", "y", "z", "braceleft",
894 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
895 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
896 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
897 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
898 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
899 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
900 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
901 "dagger", "degree", "cent", "sterling", "section",
902 "bullet", "paragraph", "germandbls", "registered", "copyright",
903 "trademark", "acute", "dieresis", "notequal", "AE",
904 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
905 "yen", "mu", "partialdiff", "summation", "product",
906 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
907 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
908 "radical", "florin", "approxequal", "Delta", "guillemotleft",
909 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
910 "Otilde", "OE", "oe", "endash", "emdash",
911 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
912 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
913 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
914 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
915 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
916 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
917 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
918 "dotlessi", "circumflex", "tilde", "macron", "breve",
919 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
920 "caron", "Lslash", "lslash", "Scaron", "scaron",
921 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
922 "Yacute", "yacute", "Thorn", "thorn", "minus",
923 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
924 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
925 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
926 "Ccaron", "ccaron", "dcroat",