10 #define MAX(a, b) ((a) < (b) ? (b) : (a))
11 #define LEN(a) (sizeof(a) / sizeof((a)[0]))
13 #define NGLYPHS (1 << 14)
14 #define NLOOKUPS (1 << 12)
18 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
19 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
20 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
21 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
22 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
24 #define GCTXLEN 16 /* number of context backtrack coverage arrays */
26 typedef unsigned int u32
;
27 typedef unsigned short u16
;
28 typedef unsigned char u8
;
32 static char glyph_name
[NGLYPHS
][GNLEN
];
33 static int glyph_code
[NGLYPHS
];
34 static int glyph_bbox
[NGLYPHS
][4];
35 static int glyph_wid
[NGLYPHS
];
37 static int upm
; /* units per em */
38 static int res
; /* device resolution */
39 static int kmin
; /* minimum kerning value */
40 static int warn
; /* report unsupported tables */
42 static char *macset
[];
43 static char *stdset
[];
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
)
53 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
56 /* weather the script is right-to-left */
57 static int otf_r2l(char *feat
)
59 char *scrp
= strchr(feat
, ':') + 1;
60 return !strcmp("arab", scrp
) || !strcmp("hebr", scrp
);
63 /* report unsupported otf tables */
64 static void otf_unsupported(char *sub
, int type
, int fmt
)
67 fprintf(stderr
, "neatmkfn: unsupported %s lookup %d", sub
, type
);
69 fprintf(stderr
, " format %d", fmt
);
70 fprintf(stderr
, "\n");
74 /* find the otf table with the given name */
75 static void *otf_table(void *otf
, char *name
)
77 int nrecs
= U16(otf
, 4);
79 for (i
= 0; i
< nrecs
; i
++) {
80 void *rec
= otf
+ 12 + i
* 16; /* an otf table record */
81 if (!strncmp(rec
, name
, 4))
82 return otf
+ U32(rec
, 8);
87 /* obtain postscript font name from name table */
88 static void otf_name(void *otf
, void *tab
)
91 void *str
= tab
+ U16(tab
, 4); /* storage area */
92 int n
= U16(tab
, 2); /* number of name records */
94 for (i
= 0; i
< n
; i
++) {
95 void *rec
= tab
+ 6 + 12 * i
;
96 int pid
= U16(rec
, 0); /* platform id */
97 int eid
= U16(rec
, 2); /* encoding id */
98 int lid
= U16(rec
, 4); /* language id */
99 int nid
= U16(rec
, 6); /* name id */
100 int len
= U16(rec
, 8); /* string length */
101 int off
= U16(rec
, 10); /* string offset */
102 if (pid
== 1 && eid
== 0 && lid
== 0 && nid
== 6) {
103 memcpy(name
, str
+ off
, len
);
110 /* parse otf cmap format 4 subtable */
111 static void otf_cmap4(void *otf
, void *cmap4
)
114 void *ends
, *begs
, *deltas
, *offsets
;
115 int beg
, end
, delta
, offset
;
117 nsegs
= U16(cmap4
, 6) / 2;
119 begs
= ends
+ 2 * nsegs
+ 2;
120 deltas
= begs
+ 2 * nsegs
;
121 offsets
= deltas
+ 2 * nsegs
;
122 for (i
= 0; i
< nsegs
; i
++) {
123 beg
= U16(begs
, 2 * i
);
124 end
= U16(ends
, 2 * i
);
125 delta
= U16(deltas
, 2 * i
);
126 offset
= U16(offsets
, 2 * i
);
128 for (j
= beg
; j
<= end
; j
++)
129 glyph_code
[(U16(offsets
+ 2 * i
,
130 offset
+ (j
- beg
) * 2) + delta
) & 0xffff] = j
;
132 for (j
= beg
; j
<= end
; j
++)
133 glyph_code
[(j
+ delta
) & 0xffff] = j
;
138 /* parse otf cmap header */
139 static void otf_cmap(void *otf
, void *cmap
)
141 int nrecs
= U16(cmap
, 2);
143 for (i
= 0; i
< nrecs
; i
++) {
144 void *rec
= cmap
+ 4 + i
* 8; /* a cmap record */
145 int plat
= U16(rec
, 0);
146 int enc
= U16(rec
, 2);
147 void *tab
= cmap
+ U32(rec
, 4); /* a cmap subtable */
148 int fmt
= U16(tab
, 0);
149 if (plat
== 3 && enc
== 1 && fmt
== 4)
154 static void otf_post(void *otf
, void *post
)
156 void *post2
; /* version 2.0 header */
157 void *index
; /* glyph name indices */
158 void *names
; /* glyph names */
162 glyph_n
= U16(post2
, 0);
163 if (U32(post
, 0) != 0x20000)
166 names
= index
+ 2 * glyph_n
;
167 for (i
= 0; i
< glyph_n
; i
++) {
168 int idx
= U16(index
, 2 * i
);
170 strcpy(glyph_name
[i
], macset
[idx
]);
172 memcpy(glyph_name
[i
], names
+ cname
+ 1,
174 glyph_name
[i
][U8(names
, cname
)] = '\0';
175 cname
+= U8(names
, cname
) + 1;
180 static void otf_glyf(void *otf
, void *glyf
)
182 void *maxp
= otf_table(otf
, "maxp");
183 void *head
= otf_table(otf
, "head");
184 void *loca
= otf_table(otf
, "loca");
187 int n
= U16(maxp
, 4);
188 int fmt
= U16(head
, 50);
190 for (i
= 0; i
< n
; i
++) {
192 gdat
= glyf
+ U32(loca
, 4 * i
);
193 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
195 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
196 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
198 if (gdat
< gdat_next
)
199 for (j
= 0; j
< 4; j
++)
200 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
204 static void otf_hmtx(void *otf
, void *hmtx
)
206 void *hhea
= otf_table(otf
, "hhea");
210 for (i
= 0; i
< n
; i
++)
211 glyph_wid
[i
] = U16(hmtx
, i
* 4);
212 for (i
= n
; i
< glyph_n
; i
++)
213 glyph_wid
[i
] = glyph_wid
[n
- 1];
216 static void otf_kern(void *otf
, void *kern
)
220 int n
= U16(kern
, 2); /* number of kern subtables */
221 for (i
= 0; i
< n
; i
++) {
222 void *tab
= kern
+ off
; /* a kern subtable */
223 int cov
= U16(tab
, 4);
225 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
226 int npairs
= U16(tab
, 6);
227 for (j
= 0; j
< npairs
; j
++) {
228 int c1
= U16(tab
, 14 + 6 * j
);
229 int c2
= U16(tab
, 14 + 6 * j
+ 2);
230 int val
= S16(tab
, 14 + 6 * j
+ 4);
231 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
238 static int coverage(void *cov
, int *out
)
240 int fmt
= U16(cov
, 0);
246 for (i
= 0; i
< n
; i
++)
247 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
250 for (i
= 0; i
< n
; i
++) {
251 beg
= U16(cov
, 4 + 6 * i
);
252 end
= U16(cov
, 4 + 6 * i
+ 2);
253 for (j
= beg
; j
<= end
; j
++)
260 static int classdef(void *tab
, int *gl
, int *cls
)
262 int fmt
= U16(tab
, 0);
266 int beg
= U16(tab
, 2);
268 for (i
= 0; i
< ngl
; i
++) {
270 cls
[i
] = U16(tab
, 6 + 2 * i
);
275 for (i
= 0; i
< n
; i
++) {
276 int beg
= U16(tab
, 4 + 6 * i
);
277 int end
= U16(tab
, 4 + 6 * i
+ 2);
278 for (j
= beg
; j
<= end
; j
++) {
280 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
288 static int intcmp(void *v1
, void *v2
)
290 return *(int *) v1
- *(int *) v2
;
293 static int ggrp_make(int *src
, int n
);
295 static int ggrp_class(int *src
, int *cls
, int nsrc
, int id
)
300 for (i
= 0; i
< nsrc
; i
++)
303 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
304 return ggrp_make(g
, n
);
307 static int ggrp_coverage(int *g
, int n
)
309 qsort(g
, n
, sizeof(g
[0]), (void *) intcmp
);
310 return ggrp_make(g
, n
);
313 static int valuerecord_len(int fmt
)
317 for (i
= 0; i
< 8; i
++)
323 static void valuerecord_print(int fmt
, void *rec
)
328 for (i
= 0; i
< 8; i
++) {
329 if (fmt
& (1 << i
)) {
330 vals
[i
] = uwid(S16(rec
, off
));
335 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
338 static int valuerecord_small(int fmt
, void *rec
)
342 for (i
= 0; i
< 8; i
++) {
343 if (fmt
& (1 << i
)) {
344 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
352 /* single adjustment positioning */
353 static void otf_gpostype1(void *otf
, void *sub
, char *feat
)
355 int fmt
= U16(sub
, 0);
356 int vfmt
= U16(sub
, 4);
359 int vlen
= valuerecord_len(vfmt
);
361 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
363 for (i
= 0; i
< ncov
; i
++) {
364 if (valuerecord_small(vfmt
, sub
+ 6))
366 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
367 valuerecord_print(vfmt
, sub
+ 6);
373 for (i
= 0; i
< nvals
; i
++) {
374 if (valuerecord_small(vfmt
, sub
+ 6))
376 printf("gpos %s 1 %s", feat
, glyph_name
[cov
[i
]]);
377 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
383 /* pair adjustment positioning */
384 static void otf_gpostype2(void *otf
, void *sub
, char *feat
)
386 int fmt
= U16(sub
, 0);
387 int vfmt1
= U16(sub
, 4); /* valuerecord 1 */
388 int vfmt2
= U16(sub
, 6); /* valuerecord 2 */
389 int fmtoff1
, fmtoff2
;
390 int vrlen
; /* the length of vfmt1 and vfmt2 */
392 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
395 int nc1
= U16(sub
, 8);
396 coverage(sub
+ U16(sub
, 2), cov
);
397 for (i
= 0; i
< nc1
; i
++) {
398 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
399 int nc2
= U16(c2
, 0);
400 for (j
= 0; j
< nc2
; j
++) {
401 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
402 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
403 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
404 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
405 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
407 printf("gpos %s 2", feat
);
408 printf(" %s", glyph_name
[cov
[i
]]);
409 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
410 printf(" %s", glyph_name
[second
]);
411 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
417 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
418 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
419 int grp1
[NGLYPHS
], grp2
[NGLYPHS
];
420 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
421 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
422 int ncls1
= U16(sub
, 12);
423 int ncls2
= U16(sub
, 14);
424 for (i
= 0; i
< ncls1
; i
++)
425 grp1
[i
] = ggrp_class(gl1
, cls1
, ngl1
, i
);
426 for (i
= 0; i
< ncls2
; i
++)
427 grp2
[i
] = ggrp_class(gl2
, cls2
, ngl2
, i
);
428 for (i
= 0; i
< ncls1
; i
++) {
429 for (j
= 0; j
< ncls2
; j
++) {
430 fmtoff1
= 16 + (i
* ncls2
+ j
) * vrlen
;
431 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
432 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
433 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
435 printf("gpos %s %d", feat
, 2);
436 printf(" @%d", grp1
[i
]);
437 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
438 printf(" @%d", grp2
[j
]);
439 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
446 /* cursive attachment positioning */
447 static void otf_gpostype3(void *otf
, void *sub
, char *feat
)
449 int fmt
= U16(sub
, 0);
457 coverage(sub
+ U16(sub
, 2), cov
);
461 for (i
= 0; i
< n
; i
++)
462 if (U16(sub
, 6 + 4 * i
))
463 ocov
[ocnt
++] = cov
[i
];
464 for (i
= 0; i
< n
; i
++)
465 if (U16(sub
, 6 + 4 * i
+ 2))
466 icov
[icnt
++] = cov
[i
];
467 igrp
= ggrp_coverage(icov
, icnt
);
468 ogrp
= ggrp_coverage(ocov
, ocnt
);
469 for (i
= 0; i
< n
; i
++) {
470 int prev
= U16(sub
, 6 + 4 * i
);
471 int next
= U16(sub
, 6 + 4 * i
+ 2);
473 int dx
= -uwid(S16(sub
, prev
+ 2));
474 int dy
= -uwid(S16(sub
, prev
+ 4));
476 dx
+= uwid(glyph_wid
[cov
[i
]]);
478 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
479 feat
, igrp
, glyph_name
[cov
[i
]],
483 int dx
= uwid(S16(sub
, next
+ 2)) - uwid(glyph_wid
[cov
[i
]]);
484 int dy
= uwid(S16(sub
, next
+ 4));
486 dx
+= uwid(glyph_wid
[cov
[i
]]);
488 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
489 feat
, glyph_name
[cov
[i
]], ogrp
,
495 /* mark-to-base attachment positioning */
496 static void otf_gpostype4(void *otf
, void *sub
, char *feat
)
498 int fmt
= U16(sub
, 0);
499 int mcov
[NGLYPHS
]; /* mark coverage */
500 int bcov
[NGLYPHS
]; /* base coverage */
501 int cgrp
[1024]; /* glyph groups assigned to classes */
502 int bgrp
; /* the group assigned to base glyphs */
503 int mcnt
; /* mark coverage size */
504 int bcnt
; /* base coverage size */
505 int ccnt
; /* class count */
506 void *marks
; /* mark array table */
507 void *bases
; /* base array table */
511 mcnt
= coverage(sub
+ U16(sub
, 2), mcov
);
512 bcnt
= coverage(sub
+ U16(sub
, 4), bcov
);
514 marks
= sub
+ U16(sub
, 8);
515 bases
= sub
+ U16(sub
, 10);
516 bgrp
= ggrp_coverage(bcov
, bcnt
);
517 for (i
= 0; i
< ccnt
; i
++) {
520 for (j
= 0; j
< mcnt
; j
++)
521 if (U16(marks
, 2 + 4 * j
) == i
)
522 grp
[cnt
++] = mcov
[j
];
523 cgrp
[i
] = ggrp_coverage(grp
, cnt
);
525 for (i
= 0; i
< mcnt
; i
++) {
526 void *mark
= marks
+ U16(marks
, 2 + 4 * i
+ 2); /* mark anchor */
527 int dx
= -uwid(S16(mark
, 2));
528 int dy
= -uwid(S16(mark
, 4));
530 dx
+= uwid(glyph_wid
[mcov
[i
]]);
533 printf("gpos %s 2 @%d %s:%+d%+d%+d%+d\n",
534 feat
, bgrp
, glyph_name
[mcov
[i
]], dx
, dy
, 0, 0);
536 for (i
= 0; i
< bcnt
; i
++) {
537 for (j
= 0; j
< ccnt
; j
++) {
538 void *base
= bases
+ U16(bases
, 2 + ccnt
* 2 * i
+ 2 * j
);
539 int dx
= uwid(S16(base
, 2)) - uwid(glyph_wid
[bcov
[i
]]);
540 int dy
= uwid(S16(base
, 4));
542 dx
+= uwid(glyph_wid
[bcov
[i
]]);
545 printf("gpos %s 2 %s @%d:%+d%+d%+d%+d\n",
546 feat
, glyph_name
[bcov
[i
]], cgrp
[j
], dx
, dy
, 0, 0);
553 int bgrp
[GCTXLEN
]; /* backtrack coverage arrays */
554 int igrp
[GCTXLEN
]; /* input coverage arrays */
555 int lgrp
[GCTXLEN
]; /* lookahead coverage arrays*/
556 int bn
, in
, ln
; /* size of b[], i[], l[] */
557 int seqidx
; /* sequence index */
560 static int gctx_len(struct gctx
*ctx
, int patlen
)
562 return ctx
? ctx
->bn
+ ctx
->in
+ ctx
->ln
- patlen
: 0;
565 static void gctx_backtrack(struct gctx
*ctx
)
570 for (i
= 0; i
< ctx
->bn
; i
++)
571 printf(" =@%d", ctx
->bgrp
[i
]);
572 for (i
= 0; i
< ctx
->seqidx
; i
++)
573 printf(" =@%d", ctx
->igrp
[i
]);
576 static void gctx_lookahead(struct gctx
*ctx
, int patlen
)
581 for (i
= ctx
->seqidx
+ patlen
; i
< ctx
->in
; i
++)
582 printf(" =@%d", ctx
->igrp
[i
]);
583 for (i
= 0; i
< ctx
->ln
; i
++)
584 printf(" =@%d", ctx
->lgrp
[i
]);
587 /* single substitution */
588 static void otf_gsubtype1(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
591 int fmt
= U16(sub
, 0);
594 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
596 for (i
= 0; i
< ncov
; i
++) {
597 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
599 printf(" -%s +%s", glyph_name
[cov
[i
]],
600 glyph_name
[cov
[i
] + S16(sub
, 4)]);
601 gctx_lookahead(ctx
, 1);
607 for (i
= 0; i
< n
; i
++) {
608 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
610 printf(" -%s +%s", glyph_name
[cov
[i
]],
611 glyph_name
[U16(sub
, 6 + 2 * i
)]);
612 gctx_lookahead(ctx
, 1);
618 /* alternate substitution */
619 static void otf_gsubtype3(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
622 int fmt
= U16(sub
, 0);
626 coverage(sub
+ U16(sub
, 2), cov
);
628 for (i
= 0; i
< n
; i
++) {
629 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
630 int nalt
= U16(alt
, 0);
631 for (j
= 0; j
< nalt
; j
++) {
632 printf("gsub %s %d", feat
, 2 + gctx_len(ctx
, 1));
634 printf(" -%s +%s", glyph_name
[cov
[i
]],
635 glyph_name
[U16(alt
, 2 + 2 * j
)]);
636 gctx_lookahead(ctx
, 1);
642 /* ligature substitution */
643 static void otf_gsubtype4(void *otf
, void *sub
, char *feat
, struct gctx
*ctx
)
645 int fmt
= U16(sub
, 0);
650 coverage(sub
+ U16(sub
, 2), cov
);
652 for (i
= 0; i
< n
; i
++) {
653 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
654 int nset
= U16(set
, 0);
655 for (j
= 0; j
< nset
; j
++) {
656 void *lig
= set
+ U16(set
, 2 + 2 * j
);
657 int nlig
= U16(lig
, 2);
658 printf("gsub %s %d", feat
, nlig
+ 1 + gctx_len(ctx
, nlig
));
660 printf(" -%s", glyph_name
[cov
[i
]]);
661 for (k
= 0; k
< nlig
- 1; k
++)
662 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
663 printf(" +%s", glyph_name
[U16(lig
, 0)]);
664 gctx_lookahead(ctx
, nlig
);
670 /* chaining contextual substitution */
671 static void otf_gsubtype6(void *otf
, void *sub
, char *feat
, void *gsub
)
673 struct gctx ctx
= {{0}};
674 void *lookups
= gsub
+ U16(gsub
, 8);
675 int fmt
= U16(sub
, 0);
677 int i
, j
, nsub
, ncov
;
680 otf_unsupported("GSUB", 6, fmt
);
683 ctx
.bn
= U16(sub
, off
);
684 for (i
= 0; i
< ctx
.bn
; i
++) {
685 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
686 ctx
.bgrp
[i
] = ggrp_coverage(cov
, ncov
);
688 off
+= 2 + 2 * ctx
.bn
;
689 ctx
.in
= U16(sub
, off
);
690 for (i
= 0; i
< ctx
.in
; i
++) {
691 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
692 ctx
.igrp
[i
] = ggrp_coverage(cov
, ncov
);
694 off
+= 2 + 2 * ctx
.in
;
695 ctx
.ln
= U16(sub
, off
);
696 for (i
= 0; i
< ctx
.ln
; i
++) {
697 ncov
= coverage(sub
+ U16(sub
, off
+ 2 + 2 * i
), cov
);
698 ctx
.lgrp
[i
] = ggrp_coverage(cov
, ncov
);
700 off
+= 2 + 2 * ctx
.ln
;
701 nsub
= U16(sub
, off
); /* nsub > 1 is not supported */
702 for (i
= 0; i
< nsub
&& i
< 1; i
++) {
703 int lidx
= U16(sub
, off
+ 2 + 4 * i
+ 2);
704 void *lookup
= lookups
+ U16(lookups
, 2 + 2 * lidx
);
705 int ltype
= U16(lookup
, 0);
706 int ntabs
= U16(lookup
, 4);
707 ctx
.seqidx
= U16(sub
, off
+ 2 + 4 * i
);
708 for (j
= 0; j
< ntabs
; j
++) {
709 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
711 if (type
== 7) { /* extension substitution */
713 tab
= tab
+ U32(tab
, 4);
716 otf_gsubtype1(otf
, tab
, feat
, &ctx
);
718 otf_gsubtype3(otf
, tab
, feat
, &ctx
);
720 otf_gsubtype4(otf
, tab
, feat
, &ctx
);
725 /* an otf gsub/gpos lookup */
727 char scrp
[8]; /* script name */
728 char feat
[8]; /* feature name */
729 int lookup
; /* index into the lookup table */
732 /* parse the given gsub/gpos feature table */
733 static int otf_featrec(void *otf
, void *gtab
, void *featrec
, char *script
, struct otflookup
*lookups
)
735 void *feats
= gtab
+ U16(gtab
, 6);
736 void *feat
= feats
+ U16(featrec
, 4);
737 int nlookups
= U16(feat
, 2);
739 for (i
= 0; i
< nlookups
; i
++) {
740 memcpy(lookups
[i
].feat
, featrec
, 4);
741 lookups
[i
].feat
[4] = '\0';
742 strcpy(lookups
[i
].scrp
, script
);
743 lookups
[i
].lookup
= U16(feat
, 4 + 2 * i
);
748 /* parse the given language table and its feature tables */
749 static int otf_lang(void *otf
, void *gtab
, void *lang
, char *script
, struct otflookup
*lookups
)
751 void *feats
= gtab
+ U16(gtab
, 6);
752 int featidx
= U16(lang
, 2);
753 int nfeat
= U16(lang
, 4);
756 if (featidx
!= 0xffff)
757 n
+= otf_featrec(otf
, gtab
, feats
+ 2 + 6 * featidx
, script
, lookups
+ n
);
758 for (i
= 0; i
< nfeat
; i
++)
759 n
+= otf_featrec(otf
, gtab
,
760 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
), script
, lookups
+ n
);
764 static int lookupcmp(void *v1
, void *v2
)
766 struct otflookup
*l1
= v1
;
767 struct otflookup
*l2
= v2
;
768 if (strcmp(l1
->scrp
, l2
->scrp
))
769 return strcmp(l1
->scrp
, l2
->scrp
);
770 if (trfn_featrank(l1
->scrp
, l1
->feat
) != trfn_featrank(l1
->scrp
, l2
->feat
))
771 return trfn_featrank(l1
->scrp
, l1
->feat
) - trfn_featrank(l1
->scrp
, l2
->feat
);
772 return l1
->lookup
- l2
->lookup
;
775 /* extract lookup tables for all features of the given gsub/gpos table */
776 static int otf_gtab(void *otf
, void *gpos
, struct otflookup
*lookups
)
778 void *scripts
= gpos
+ U16(gpos
, 4);
779 int nscripts
, nlangs
;
781 char stag
[8], ltag
[8]; /* script and language tags */
784 nscripts
= U16(scripts
, 0);
785 for (i
= 0; i
< nscripts
; i
++) {
786 void *grec
= scripts
+ 2 + 6 * i
;
787 memcpy(stag
, grec
, 4);
789 if (!trfn_script(stag
, nscripts
))
791 script
= scripts
+ U16(grec
, 4);
792 nlangs
= U16(script
, 2);
793 if (U16(script
, 0) && trfn_lang(NULL
, nlangs
+ (U16(script
, 0) != 0)))
794 n
+= otf_lang(otf
, gpos
, script
+ U16(script
, 0),
796 for (j
= 0; j
< nlangs
; j
++) {
797 void *lrec
= script
+ 4 + 6 * j
;
798 memcpy(ltag
, lrec
, 4);
800 if (trfn_lang(ltag
, nlangs
+ (U16(script
, 0) != 0)))
801 n
+= otf_lang(otf
, gpos
, script
+ U16(lrec
, 4),
805 qsort(lookups
, n
, sizeof(lookups
[0]), (void *) lookupcmp
);
809 static void otf_gpos(void *otf
, void *gpos
)
811 struct otflookup lookups
[NLOOKUPS
];
812 void *lookuplist
= gpos
+ U16(gpos
, 8);
813 int nlookups
= otf_gtab(otf
, gpos
, lookups
);
816 for (i
= 0; i
< nlookups
; i
++) {
817 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
818 int ltype
= U16(lookup
, 0);
819 int ntabs
= U16(lookup
, 4);
820 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
821 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
822 for (j
= 0; j
< ntabs
; j
++) {
823 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
825 if (type
== 9) { /* extension positioning */
827 tab
= tab
+ U32(tab
, 4);
831 otf_gpostype1(otf
, tab
, tag
);
834 otf_gpostype2(otf
, tab
, tag
);
837 otf_gpostype3(otf
, tab
, tag
);
840 otf_gpostype4(otf
, tab
, tag
);
843 otf_unsupported("GPOS", type
, 0);
849 static void otf_gsub(void *otf
, void *gsub
)
851 struct otflookup lookups
[NLOOKUPS
];
852 void *lookuplist
= gsub
+ U16(gsub
, 8);
853 int nlookups
= otf_gtab(otf
, gsub
, lookups
);
856 for (i
= 0; i
< nlookups
; i
++) {
857 void *lookup
= lookuplist
+ U16(lookuplist
, 2 + 2 * lookups
[i
].lookup
);
858 int ltype
= U16(lookup
, 0);
859 int ntabs
= U16(lookup
, 4);
860 sprintf(tag
, "%s:%s", lookups
[i
].feat
,
861 lookups
[i
].scrp
[0] ? lookups
[i
].scrp
: "DFLT");
862 for (j
= 0; j
< ntabs
; j
++) {
863 void *tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
865 if (type
== 7) { /* extension substitution */
867 tab
= tab
+ U32(tab
, 4);
871 otf_gsubtype1(otf
, tab
, tag
, NULL
);
874 otf_gsubtype3(otf
, tab
, tag
, NULL
);
877 otf_gsubtype4(otf
, tab
, tag
, NULL
);
880 otf_gsubtype6(otf
, tab
, tag
, gsub
);
883 otf_unsupported("GSUB", type
, 0);
889 /* read a cff offset, which has sz bytes */
890 static int cff_int(void *tab
, int off
, int sz
)
894 for (i
= 0; i
< sz
; i
++)
895 n
= n
* 256 + U8(tab
, off
+ i
);
899 /* cff dict operand/operator */
900 static int cff_op(void *tab
, int off
, int *val
)
902 int b0
= U8(tab
, off
);
904 if (b0
>= 32 && b0
<= 246) {
908 if (b0
>= 247 && b0
<= 250) {
909 *val
= (b0
- 247) * 256 + U8(tab
, off
+ 1) + 108;
912 if (b0
>= 251 && b0
<= 254) {
913 *val
= -(b0
- 251) * 256 - U8(tab
, off
+ 1) - 108;
917 *val
= (U8(tab
, off
+ 1) << 8) | U8(tab
, off
+ 2);
921 *val
= (U8(tab
, off
+ 1) << 24) | (U8(tab
, off
+ 2) << 16) |
922 (U8(tab
, off
+ 3) << 8) | U8(tab
, off
+ 4);
926 for (i
= 1; i
< 32; i
++) {
927 int nib
= U8(tab
, off
+ i
);
928 if ((nib
& 0x0f) == 0x0f || (nib
& 0xf0) == 0xf0)
938 static int cffidx_cnt(void *idx
)
943 static void *cffidx_get(void *idx
, int i
)
945 int cnt
= U16(idx
, 0);
947 return idx
+ 3 + (cnt
+ 1) * sz
- 1 + cff_int(idx
, 3 + i
* sz
, sz
);
950 static int cffidx_len(void *idx
, int i
)
952 return cffidx_get(idx
, i
+ 1) - cffidx_get(idx
, i
);
955 static void *cffidx_end(void *idx
)
957 return cffidx_get(idx
, cffidx_cnt(idx
));
960 static int cffdict_get(void *dict
, int len
, int key
)
965 /* operators: keys (one or two bytes); operands: values */
968 off
+= cff_op(dict
, off
, &op
);
969 if (op
== 12) { /* two-byte operator */
970 off
+= cff_op(dict
, off
, &op
);
979 static void cff_char(void *stridx
, int id
, char *dst
)
983 strcpy(dst
, stdset
[id
]);
987 len
= cffidx_len(stridx
, id
);
988 memcpy(dst
, cffidx_get(stridx
, id
), len
);
992 static void otf_cff(void *otf
, void *cff
)
994 void *nameidx
; /* name index */
995 void *topidx
; /* top dict index */
996 void *stridx
; /* string idx */
997 void *chridx
; /* charstrings index */
998 void *charset
; /* charset offset of top dict table */
1000 if (U8(cff
, 0) != 1)
1002 nameidx
= cff
+ U8(cff
, 2);
1003 topidx
= cffidx_end(nameidx
);
1004 if (cffidx_cnt(nameidx
) < 1)
1006 stridx
= cffidx_end(topidx
);
1007 chridx
= cff
+ cffdict_get(cffidx_get(topidx
, 0), cffidx_len(topidx
, 0), 17);
1008 charset
= cff
+ cffdict_get(cffidx_get(topidx
, 0), cffidx_len(topidx
, 0), 15);
1009 glyph_n
= cffidx_cnt(chridx
);
1010 strcpy(glyph_name
[0], ".notdef");
1011 if (U8(charset
, 0) == 0) {
1012 for (i
= 0; i
< glyph_n
; i
++)
1013 cff_char(stridx
, i
, glyph_name
[i
]);
1015 if (U8(charset
, 0) == 1) {
1017 for (i
= 0; g
< glyph_n
; i
++) {
1018 int sid
= U16(charset
, 1 + i
* 3);
1019 int cnt
= U8(charset
, 1 + i
* 3 + 2);
1020 for (j
= 0; j
<= cnt
&& g
< glyph_n
; j
++) {
1021 cff_char(stridx
, sid
+ j
, glyph_name
[g
]);
1026 if (U8(charset
, 0) == 2) {
1028 for (i
= 0; g
< glyph_n
; i
++) {
1029 int sid
= U16(charset
, 1 + i
* 4);
1030 int cnt
= U16(charset
, 1 + i
* 4 + 2);
1031 for (j
= 0; j
<= cnt
&& g
< glyph_n
; j
++) {
1032 cff_char(stridx
, sid
+ j
, glyph_name
[g
]);
1039 static void *otf_input(int fd
)
1041 struct sbuf
*sb
= sbuf_make();
1044 while ((nr
= read(fd
, buf
, sizeof(buf
))) > 0)
1045 sbuf_mem(sb
, buf
, nr
);
1046 return sbuf_done(sb
);
1049 static char *otf_buf
;
1054 otf_buf
= otf_input(0);
1055 upm
= U16(otf_table(otf_buf
, "head"), 18);
1056 otf_name(otf_buf
, otf_table(otf_buf
, "name"));
1057 otf_cmap(otf_buf
, otf_table(otf_buf
, "cmap"));
1058 otf_post(otf_buf
, otf_table(otf_buf
, "post"));
1059 if (otf_table(otf_buf
, "glyf"))
1060 otf_glyf(otf_buf
, otf_table(otf_buf
, "glyf"));
1061 if (otf_table(otf_buf
, "CFF "))
1062 otf_cff(otf_buf
, otf_table(otf_buf
, "CFF "));
1063 otf_hmtx(otf_buf
, otf_table(otf_buf
, "hmtx"));
1064 for (i
= 0; i
< glyph_n
; i
++) {
1065 trfn_char(glyph_name
[i
], -1,
1066 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
1068 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
1069 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
1071 if (otf_table(otf_buf
, "kern"))
1072 otf_kern(otf_buf
, otf_table(otf_buf
, "kern"));
1076 void otf_feat(int r
, int k
, int w
)
1081 if (otf_table(otf_buf
, "GSUB"))
1082 otf_gsub(otf_buf
, otf_table(otf_buf
, "GSUB"));
1083 if (otf_table(otf_buf
, "GPOS"))
1084 otf_gpos(otf_buf
, otf_table(otf_buf
, "GPOS"));
1088 static int *ggrp_g
[NGRPS
];
1089 static int ggrp_len
[NGRPS
];
1092 static int ggrp_find(int *src
, int n
)
1095 for (i
= 0; i
< ggrp_n
; i
++) {
1096 if (ggrp_len
[i
] == n
) {
1097 for (j
= 0; j
< n
; j
++)
1098 if (src
[j
] != ggrp_g
[i
][j
])
1107 static int ggrp_make(int *src
, int n
)
1109 int id
= ggrp_find(src
, n
);
1114 ggrp_g
[id
] = malloc(n
* sizeof(ggrp_g
[id
][0]));
1116 for (i
= 0; i
< n
; i
++)
1117 ggrp_g
[id
][i
] = src
[i
];
1118 printf("ggrp %d %d", id
, n
);
1119 for (i
= 0; i
< n
; i
++)
1120 printf(" %s", glyph_name
[src
[i
]]);
1125 static char *macset
[] = {
1126 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
1127 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
1128 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
1129 "comma", "hyphen", "period", "slash", "zero",
1130 "one", "two", "three", "four", "five",
1131 "six", "seven", "eight", "nine", "colon",
1132 "semicolon", "less", "equal", "greater", "question",
1133 "at", "A", "B", "C", "D",
1134 "E", "F", "G", "H", "I",
1135 "J", "K", "L", "M", "N",
1136 "O", "P", "Q", "R", "S",
1137 "T", "U", "V", "W", "X",
1138 "Y", "Z", "bracketleft", "backslash", "bracketright",
1139 "asciicircum", "underscore", "grave", "a", "b",
1140 "c", "d", "e", "f", "g",
1141 "h", "i", "j", "k", "l",
1142 "m", "n", "o", "p", "q",
1143 "r", "s", "t", "u", "v",
1144 "w", "x", "y", "z", "braceleft",
1145 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
1146 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
1147 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
1148 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
1149 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
1150 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
1151 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
1152 "dagger", "degree", "cent", "sterling", "section",
1153 "bullet", "paragraph", "germandbls", "registered", "copyright",
1154 "trademark", "acute", "dieresis", "notequal", "AE",
1155 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
1156 "yen", "mu", "partialdiff", "summation", "product",
1157 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
1158 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
1159 "radical", "florin", "approxequal", "Delta", "guillemotleft",
1160 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
1161 "Otilde", "OE", "oe", "endash", "emdash",
1162 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
1163 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
1164 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
1165 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
1166 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
1167 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
1168 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
1169 "dotlessi", "circumflex", "tilde", "macron", "breve",
1170 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
1171 "caron", "Lslash", "lslash", "Scaron", "scaron",
1172 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
1173 "Yacute", "yacute", "Thorn", "thorn", "minus",
1174 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
1175 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
1176 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
1177 "Ccaron", "ccaron", "dcroat",
1180 static char *stdset
[] = {
1181 ".notdef", "space", "exclam", "quotedbl", "numbersign",
1182 "dollar", "percent", "ampersand", "quoteright", "parenleft",
1183 "parenright", "asterisk", "plus", "comma", "hyphen",
1184 "period", "slash", "zero", "one", "two",
1185 "three", "four", "five", "six", "seven",
1186 "eight", "nine", "colon", "semicolon", "less",
1187 "equal", "greater", "question", "at", "A",
1188 "B", "C", "D", "E", "F",
1189 "G", "H", "I", "J", "K",
1190 "L", "M", "N", "O", "P",
1191 "Q", "R", "S", "T", "U",
1192 "V", "W", "X", "Y", "Z",
1193 "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
1194 "quoteleft", "a", "b", "c", "d",
1195 "e", "f", "g", "h", "i",
1196 "j", "k", "l", "m", "n",
1197 "o", "p", "q", "r", "s",
1198 "t", "u", "v", "w", "x",
1199 "y", "z", "braceleft", "bar", "braceright",
1200 "asciitilde", "exclamdown", "cent", "sterling", "fraction",
1201 "yen", "florin", "section", "currency", "quotesingle",
1202 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
1203 "fl", "endash", "dagger", "daggerdbl", "periodcentered",
1204 "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
1205 "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
1206 "acute", "circumflex", "tilde", "macron", "breve",
1207 "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
1208 "ogonek", "caron", "emdash", "AE", "ordfeminine",
1209 "Lslash", "Oslash", "OE", "ordmasculine", "ae",
1210 "dotlessi", "lslash", "oslash", "oe", "germandbls",
1211 "onesuperior", "logicalnot", "mu", "trademark", "Eth",
1212 "onehalf", "plusminus", "Thorn", "onequarter", "divide",
1213 "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
1214 "registered", "minus", "eth", "multiply", "threesuperior",
1215 "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
1216 "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
1217 "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
1218 "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
1219 "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
1220 "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
1221 "aacute", "acircumflex", "adieresis", "agrave", "aring",
1222 "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
1223 "egrave", "iacute", "icircumflex", "idieresis", "igrave",
1224 "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
1225 "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
1226 "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
1227 "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
1228 "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
1229 "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
1230 "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
1231 "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
1232 "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
1233 "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
1234 "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
1235 "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
1236 "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
1237 "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
1238 "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
1239 "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
1240 "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
1241 "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
1242 "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
1243 "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
1244 "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
1245 "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
1246 "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
1247 "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
1248 "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
1249 "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
1250 "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
1251 "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
1252 "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
1253 "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
1254 "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
1255 "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
1256 "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall", "001.000",
1257 "001.001", "001.002", "001.003", "Black", "Bold",
1258 "Book", "Light", "Medium", "Regular", "Roman",