9 #define NGLYPHS (1 << 14)
11 #define BUFLEN (1 << 23)
12 #define MAX(a, b) ((a) < (b) ? (b) : (a))
14 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
15 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
16 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
17 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
18 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
20 #define OTFLEN 12 /* otf header length */
21 #define OTFRECLEN 16 /* otf header record length */
22 #define CMAPLEN 4 /* cmap header length */
23 #define CMAPRECLEN 8 /* cmap record length */
24 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
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 */
41 static char *macset
[];
43 static int owid(int w
)
45 return (w
< 0 ? w
* 1000 - upm
/ 2 : w
* 1000 + upm
/ 2) / upm
;
48 static int uwid(int w
)
51 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
54 /* find the otf table with the given name */
55 static void *otf_table(void *otf
, char *name
)
57 void *recs
= otf
+ OTFLEN
; /* otf table records */
58 void *rec
; /* beginning of a table record */
59 int nrecs
= U16(otf
, 4);
61 for (i
= 0; i
< nrecs
; i
++) {
62 rec
= recs
+ i
* OTFRECLEN
;
63 if (!strncmp(rec
, name
, 4))
64 return otf
+ U32(rec
, 8);
69 /* parse otf cmap format 4 subtable */
70 static void otf_cmap4(void *otf
, void *cmap4
)
73 void *ends
, *begs
, *deltas
, *offsets
;
75 int beg
, end
, delta
, offset
;
77 nsegs
= U16(cmap4
, 6) / 2;
79 begs
= ends
+ 2 * nsegs
+ 2;
80 deltas
= begs
+ 2 * nsegs
;
81 offsets
= deltas
+ 2 * nsegs
;
82 idarray
= offsets
+ 2 * nsegs
;
83 for (i
= 0; i
< nsegs
; i
++) {
84 beg
= U16(begs
, 2 * i
);
85 end
= U16(ends
, 2 * i
);
86 delta
= U16(deltas
, 2 * i
);
87 offset
= U16(offsets
, 2 * i
);
89 for (j
= beg
; j
<= end
; j
++)
90 glyph_code
[U16(offsets
+ i
* 2,
91 offset
+ (j
- beg
) * 2)] = j
;
93 for (j
= beg
; j
<= end
; j
++)
94 glyph_code
[(j
+ delta
) & 0xffff] = j
;
99 /* parse otf cmap header */
100 static void otf_cmap(void *otf
, void *cmap
)
102 void *recs
= cmap
+ CMAPLEN
; /* cmap records */
103 void *rec
; /* a cmap record */
104 void *tab
; /* a cmap subtable */
107 int nrecs
= U16(cmap
, 2);
109 for (i
= 0; i
< nrecs
; i
++) {
110 rec
= recs
+ i
* CMAPRECLEN
;
113 tab
= cmap
+ U32(rec
, 4);
115 if (plat
== 3 && enc
== 1 && fmt
== 4)
120 static void otf_post(void *otf
, void *post
)
122 void *post2
; /* version 2.0 header */
123 void *index
; /* glyph name indices */
124 void *names
; /* glyph names */
127 if (U32(post
, 0) != 0x00020000)
130 glyph_n
= U16(post2
, 0);
132 names
= index
+ 2 * glyph_n
;
133 for (i
= 0; i
< glyph_n
; i
++) {
134 idx
= U16(index
, 2 * i
);
136 strcpy(glyph_name
[i
], macset
[idx
]);
138 memcpy(glyph_name
[i
], names
+ cname
+ 1,
140 glyph_name
[i
][U8(names
, cname
)] = '\0';
141 cname
+= U8(names
, cname
) + 1;
146 static void otf_glyf(void *otf
, void *glyf
)
148 void *maxp
= otf_table(otf
, "maxp");
149 void *head
= otf_table(otf
, "head");
150 void *loca
= otf_table(otf
, "loca");
153 int n
= U16(maxp
, 4);
154 int fmt
= U16(head
, 50);
156 for (i
= 0; i
< n
; i
++) {
158 gdat
= glyf
+ U32(loca
, 4 * i
);
159 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
161 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
162 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
164 if (gdat
< gdat_next
)
165 for (j
= 0; j
< 4; j
++)
166 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
170 static void otf_hmtx(void *otf
, void *hmtx
)
172 void *hhea
= otf_table(otf
, "hhea");
176 for (i
= 0; i
< n
; i
++)
177 glyph_wid
[i
] = U16(hmtx
, i
* 4);
178 for (i
= n
; i
< glyph_n
; i
++)
179 glyph_wid
[i
] = glyph_wid
[n
- 1];
182 static void otf_kern(void *otf
, void *kern
)
184 int n
; /* number of kern subtables */
185 void *tab
; /* a kern subtable */
192 for (i
= 0; i
< n
; i
++) {
196 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
197 npairs
= U16(tab
, 6);
198 for (j
= 0; j
< npairs
; j
++) {
199 c1
= U16(tab
, 14 + 6 * j
);
200 c2
= U16(tab
, 14 + 6 * j
+ 2);
201 val
= S16(tab
, 14 + 6 * j
+ 4);
202 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
209 static int coverage(void *cov
, int *out
)
211 int fmt
= U16(cov
, 0);
217 for (i
= 0; i
< n
; i
++)
218 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
221 for (i
= 0; i
< n
; i
++) {
222 beg
= U16(cov
, 4 + 6 * i
);
223 end
= U16(cov
, 4 + 6 * i
+ 2);
224 for (j
= beg
; j
<= end
; j
++)
231 static int classdef(void *tab
, int *gl
, int *cls
)
233 int fmt
= U16(tab
, 0);
240 for (i
= 0; i
< ngl
; i
++) {
242 cls
[i
] = U16(tab
, 6 + 2 * i
);
247 for (i
= 0; i
< n
; i
++) {
248 beg
= U16(tab
, 4 + 6 * i
);
249 end
= U16(tab
, 4 + 6 * i
+ 2);
250 for (j
= beg
; j
<= end
; j
++) {
252 cls
[ngl
] = U16(tab
, 4 + 6 * i
+ 4);
260 static int valuerecord_len(int fmt
)
264 for (i
= 0; i
< 8; i
++)
270 static void valuerecord_print(int fmt
, void *rec
)
275 for (i
= 0; i
< 8; i
++) {
276 if (fmt
& (1 << i
)) {
277 vals
[i
] = uwid(S16(rec
, off
));
282 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
285 static int valuerecord_small(int fmt
, void *rec
)
289 for (i
= 0; i
< 8; i
++) {
290 if (fmt
& (1 << i
)) {
291 if (abs(uwid(S16(rec
, off
))) >= MAX(1, kmin
))
299 static void otf_gpostype1(void *otf
, char *feat
, char *sub
)
301 int fmt
= U16(sub
, 0);
302 int vfmt
= U16(sub
, 4);
305 int vlen
= valuerecord_len(vfmt
);
307 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
309 for (i
= 0; i
< ncov
; i
++) {
310 printf("gpos %s %s", feat
, glyph_name
[cov
[i
]]);
311 valuerecord_print(vfmt
, sub
+ 6);
317 for (i
= 0; i
< nvals
; i
++) {
318 printf("gpos %s %s", feat
, glyph_name
[cov
[i
]]);
319 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
325 static void otf_gpostype2(void *otf
, char *feat
, char *sub
)
327 int fmt
= U16(sub
, 0);
328 int vfmt1
= U16(sub
, 4);
329 int vfmt2
= U16(sub
, 6);
330 int fmtoff1
, fmtoff2
;
331 int vrlen
; /* valuerecord1 and valuerecord2 length */
333 vrlen
= valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
336 int nc1
= U16(sub
, 8);
337 coverage(sub
+ U16(sub
, 2), cov
);
338 for (i
= 0; i
< nc1
; i
++) {
339 void *c2
= sub
+ U16(sub
, 10 + 2 * i
);
340 int nc2
= U16(c2
, 0);
341 for (j
= 0; j
< nc2
; j
++) {
342 int second
= U16(c2
+ 2 + (2 + vrlen
) * j
, 0);
343 fmtoff1
= 2 + (2 + vrlen
) * j
+ 2;
344 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt2
);
345 if (valuerecord_small(vfmt1
, c2
+ fmtoff1
) &&
346 valuerecord_small(vfmt2
, c2
+ fmtoff2
))
348 printf("gpos %s 2", feat
);
349 printf(" %s", glyph_name
[cov
[i
]]);
350 valuerecord_print(vfmt1
, c2
+ fmtoff1
);
351 printf(" %s", glyph_name
[second
]);
352 valuerecord_print(vfmt2
, c2
+ fmtoff2
);
358 int gl1
[NGLYPHS
], gl2
[NGLYPHS
];
359 int cls1
[NGLYPHS
], cls2
[NGLYPHS
];
360 int ngl1
= classdef(sub
+ U16(sub
, 8), gl1
, cls1
);
361 int ngl2
= classdef(sub
+ U16(sub
, 10), gl2
, cls2
);
362 int ncls1
= U16(sub
, 12);
363 int ncls2
= U16(sub
, 14);
364 for (i
= 0; i
< ngl1
; i
++) {
365 for (j
= 0; j
< ngl2
; j
++) {
366 if (cls1
[i
] >= ncls1
|| cls2
[j
] >= ncls2
)
368 fmtoff1
= 16 + (cls1
[i
] * ncls2
+ cls2
[j
]) * vrlen
;
369 fmtoff2
= fmtoff1
+ valuerecord_len(vfmt1
);
370 if (valuerecord_small(vfmt1
, sub
+ fmtoff1
) &&
371 valuerecord_small(vfmt2
, sub
+ fmtoff2
))
373 printf("gpos %s 2", feat
);
374 printf(" %s", glyph_name
[gl1
[i
]]);
375 valuerecord_print(vfmt1
, sub
+ fmtoff1
);
376 printf(" %s", glyph_name
[gl2
[j
]]);
377 valuerecord_print(vfmt2
, sub
+ fmtoff2
);
384 static void otf_gpostype3(void *otf
, char *feat
, char *sub
)
386 int fmt
= U16(sub
, 0);
389 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
393 for (i
= 0; i
< n
; i
++) {
394 int prev
= U16(sub
, 6 + 4 * i
);
395 int next
= U16(sub
, 6 + 4 * i
+ 2);
396 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
398 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
399 uwid(S16(sub
, prev
+ 4)));
403 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
404 uwid(S16(sub
, next
+ 4)));
411 static void otf_gposfeatrec(void *otf
, void *gpos
, void *featrec
)
413 void *feats
= gpos
+ U16(gpos
, 6);
414 void *lookups
= gpos
+ U16(gpos
, 8);
415 void *feat
, *lookup
, *tab
;
416 int nlookups
, type
, flag
, ntabs
;
419 memcpy(tag
, featrec
, 4);
420 feat
= feats
+ U16(featrec
, 4);
421 nlookups
= U16(feat
, 2);
422 for (i
= 0; i
< nlookups
; i
++) {
423 lookup
= lookups
+ U16(lookups
, 2 + 2 * U16(feat
, 4 + 2 * i
));
424 type
= U16(lookup
, 0);
425 flag
= U16(lookup
, 2);
426 ntabs
= U16(lookup
, 4);
427 for (j
= 0; j
< ntabs
; j
++) {
428 tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
430 otf_gpostype1(otf
, tag
, tab
);
432 otf_gpostype2(otf
, tag
, tab
);
434 otf_gpostype3(otf
, tag
, tab
);
439 static void otf_gposlang(void *otf
, void *gpos
, void *lang
)
441 void *feats
= gpos
+ U16(gpos
, 6);
442 int featidx
= U16(lang
, 2);
443 int nfeat
= U16(lang
, 4);
445 if (featidx
!= 0xffff)
446 otf_gposfeatrec(otf
, gpos
, feats
+ 2 + 6 * featidx
);
447 for (i
= 0; i
< nfeat
; i
++)
448 otf_gposfeatrec(otf
, gpos
,
449 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
));
452 static void otf_gpos(void *otf
, void *gpos
)
454 void *scripts
= gpos
+ U16(gpos
, 4);
455 int nscripts
, nlangs
;
459 nscripts
= U16(scripts
, 0);
460 for (i
= 0; i
< nscripts
; i
++) {
461 grec
= scripts
+ 2 + 6 * i
;
462 script
= scripts
+ U16(grec
, 4);
464 otf_gposlang(otf
, gpos
, script
+ U16(script
, 0));
465 nlangs
= U16(script
, 2);
466 for (j
= 0; j
< nlangs
; j
++)
467 otf_gposlang(otf
, gpos
, script
+
468 U16(script
, 4 + 6 * j
+ 4));
472 static void otf_gsubtype1(void *otf
, char *feat
, char *sub
)
475 int fmt
= U16(sub
, 0);
479 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
481 for (i
= 0; i
< ncov
; i
++)
482 printf("gsub %s 2 -%s +%s\n",
483 feat
, glyph_name
[cov
[i
]],
484 glyph_name
[cov
[i
] + S16(sub
, 4)]);
488 for (i
= 0; i
< n
; i
++)
489 printf("gsub %s 2 -%s +%s\n",
490 feat
, glyph_name
[cov
[i
]],
491 glyph_name
[U16(sub
, 6 + 2 * i
)]);
495 static void otf_gsubtype3(void *otf
, char *feat
, char *sub
)
498 int fmt
= U16(sub
, 0);
502 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
504 for (i
= 0; i
< n
; i
++) {
505 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
506 int nalt
= U16(alt
, 0);
507 for (j
= 0; j
< nalt
; j
++)
508 printf("gsub %s 2 -%s +%s\n",
509 feat
, glyph_name
[cov
[i
]],
510 glyph_name
[U16(alt
, 2 + 2 * j
)]);
514 static void otf_gsubtype4(void *otf
, char *feat
, char *sub
)
516 int fmt
= U16(sub
, 0);
518 int ncov
, n
, i
, j
, k
;
521 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
523 for (i
= 0; i
< n
; i
++) {
524 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
525 int nset
= U16(set
, 0);
526 for (j
= 0; j
< nset
; j
++) {
527 void *lig
= set
+ U16(set
, 2 + 2 * j
);
528 int nlig
= U16(lig
, 2);
529 printf("gsub %s %d -%s",
530 feat
, nlig
+ 1, glyph_name
[cov
[i
]]);
531 for (k
= 0; k
< nlig
- 1; k
++)
532 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
533 printf(" +%s\n", glyph_name
[U16(lig
, 0)]);
538 static void otf_gsubfeatrec(void *otf
, void *gsub
, void *featrec
)
540 void *feats
= gsub
+ U16(gsub
, 6);
541 void *lookups
= gsub
+ U16(gsub
, 8);
542 void *feat
, *lookup
, *tab
;
543 int nlookups
, type
, flag
, ntabs
;
546 memcpy(tag
, featrec
, 4);
547 feat
= feats
+ U16(featrec
, 4);
548 nlookups
= U16(feat
, 2);
549 for (i
= 0; i
< nlookups
; i
++) {
550 lookup
= lookups
+ U16(lookups
, 2 + 2 * U16(feat
, 4 + 2 * i
));
551 type
= U16(lookup
, 0);
552 flag
= U16(lookup
, 2);
553 ntabs
= U16(lookup
, 4);
554 for (j
= 0; j
< ntabs
; j
++) {
555 tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
557 otf_gsubtype1(otf
, tag
, tab
);
559 otf_gsubtype3(otf
, tag
, tab
);
561 otf_gsubtype4(otf
, tag
, tab
);
566 static void otf_gsublang(void *otf
, void *gsub
, void *lang
)
568 void *feats
= gsub
+ U16(gsub
, 6);
569 int featidx
= U16(lang
, 2);
570 int nfeat
= U16(lang
, 4);
572 if (featidx
!= 0xffff)
573 otf_gsubfeatrec(otf
, gsub
, feats
+ 2 + 6 * featidx
);
574 for (i
= 0; i
< nfeat
; i
++)
575 otf_gsubfeatrec(otf
, gsub
,
576 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
));
579 static void otf_gsub(void *otf
, void *gsub
)
581 void *scripts
= gsub
+ U16(gsub
, 4);
582 int nscripts
, nlangs
;
585 nscripts
= U16(scripts
, 0);
586 for (i
= 0; i
< nscripts
; i
++) {
587 script
= scripts
+ U16(scripts
+ 2 + 6 * i
, 4);
588 nlangs
= U16(script
, 2);
590 otf_gsublang(otf
, gsub
, script
+ U16(script
, 0));
591 for (j
= 0; j
< nlangs
; j
++)
592 otf_gsublang(otf
, gsub
, script
+
593 U16(script
, 4 + 6 * j
+ 4));
597 int xread(int fd
, char *buf
, int len
)
601 int ret
= read(fd
, buf
+ nr
, len
- nr
);
602 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
611 static char buf
[BUFLEN
];
616 if (xread(0, buf
, sizeof(buf
)) <= 0)
618 upm
= U16(otf_table(buf
, "head"), 18);
619 otf_cmap(buf
, otf_table(buf
, "cmap"));
620 otf_post(buf
, otf_table(buf
, "post"));
621 if (otf_table(buf
, "glyf"))
622 otf_glyf(buf
, otf_table(buf
, "glyf"));
623 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
624 for (i
= 0; i
< glyph_n
; i
++) {
625 trfn_char(glyph_name
[i
], -1,
626 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
628 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
629 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
631 if (otf_table(buf
, "kern"))
632 otf_kern(buf
, otf_table(buf
, "kern"));
636 void otf_feat(int r
, int k
)
640 if (otf_table(buf
, "GSUB"))
641 otf_gsub(buf
, otf_table(buf
, "GSUB"));
642 if (otf_table(buf
, "GPOS"))
643 otf_gpos(buf
, otf_table(buf
, "GPOS"));
646 static char *macset
[] = {
647 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
648 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
649 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
650 "comma", "hyphen", "period", "slash", "zero",
651 "one", "two", "three", "four", "five",
652 "six", "seven", "eight", "nine", "colon",
653 "semicolon", "less", "equal", "greater", "question",
654 "at", "A", "B", "C", "D",
655 "E", "F", "G", "H", "I",
656 "J", "K", "L", "M", "N",
657 "O", "P", "Q", "R", "S",
658 "T", "U", "V", "W", "X",
659 "Y", "Z", "bracketleft", "backslash", "bracketright",
660 "asciicircum", "underscore", "grave", "a", "b",
661 "c", "d", "e", "f", "g",
662 "h", "i", "j", "k", "l",
663 "m", "n", "o", "p", "q",
664 "r", "s", "t", "u", "v",
665 "w", "x", "y", "z", "braceleft",
666 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
667 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
668 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
669 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
670 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
671 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
672 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
673 "dagger", "degree", "cent", "sterling", "section",
674 "bullet", "paragraph", "germandbls", "registered", "copyright",
675 "trademark", "acute", "dieresis", "notequal", "AE",
676 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
677 "yen", "mu", "partialdiff", "summation", "product",
678 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
679 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
680 "radical", "florin", "approxequal", "Delta", "guillemotleft",
681 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
682 "Otilde", "OE", "oe", "endash", "emdash",
683 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
684 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
685 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
686 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
687 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
688 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
689 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
690 "dotlessi", "circumflex", "tilde", "macron", "breve",
691 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
692 "caron", "Lslash", "lslash", "Scaron", "scaron",
693 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
694 "Yacute", "yacute", "Thorn", "thorn", "minus",
695 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
696 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
697 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
698 "Ccaron", "ccaron", "dcroat",