8 #define NGLYPHS (1 << 14)
10 #define BUFLEN (1 << 23)
12 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
13 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
14 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
15 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
16 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
18 #define OTFLEN 12 /* otf header length */
19 #define OTFRECLEN 16 /* otf header record length */
20 #define CMAPLEN 4 /* cmap header length */
21 #define CMAPRECLEN 8 /* cmap record length */
22 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
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 */
38 static char *macset
[];
40 static int owid(int w
)
42 return (w
< 0 ? w
* 1000 - upm
/ 2 : w
* 1000 + upm
/ 2) / upm
;
45 static int uwid(int w
)
48 return (w
< 0 ? owid(w
) - d
/ 2 : owid(w
) + d
/ 2) / d
;
51 /* find the otf table with the given name */
52 static void *otf_table(void *otf
, char *name
)
54 void *recs
= otf
+ OTFLEN
; /* otf table records */
55 void *rec
; /* beginning of a table record */
56 int nrecs
= U16(otf
, 4);
58 for (i
= 0; i
< nrecs
; i
++) {
59 rec
= recs
+ i
* OTFRECLEN
;
60 if (!strncmp(rec
, name
, 4))
61 return otf
+ U32(rec
, 8);
66 /* parse otf cmap format 4 subtable */
67 static void otf_cmap4(void *otf
, void *cmap4
)
70 void *ends
, *begs
, *deltas
, *offsets
;
72 int beg
, end
, delta
, offset
;
74 nsegs
= U16(cmap4
, 6) / 2;
76 begs
= ends
+ 2 * nsegs
+ 2;
77 deltas
= begs
+ 2 * nsegs
;
78 offsets
= deltas
+ 2 * nsegs
;
79 idarray
= offsets
+ 2 * nsegs
;
80 for (i
= 0; i
< nsegs
; i
++) {
81 beg
= U16(begs
, 2 * i
);
82 end
= U16(ends
, 2 * i
);
83 delta
= U16(deltas
, 2 * i
);
84 offset
= U16(offsets
, 2 * i
);
86 for (j
= beg
; j
<= end
; j
++)
87 glyph_code
[U16(offsets
+ i
* 2,
88 offset
+ (j
- beg
) * 2)] = j
;
90 for (j
= beg
; j
<= end
; j
++)
91 glyph_code
[(j
+ delta
) & 0xffff] = j
;
96 /* parse otf cmap header */
97 static void otf_cmap(void *otf
, void *cmap
)
99 void *recs
= cmap
+ CMAPLEN
; /* cmap records */
100 void *rec
; /* a cmap record */
101 void *tab
; /* a cmap subtable */
104 int nrecs
= U16(cmap
, 2);
106 for (i
= 0; i
< nrecs
; i
++) {
107 rec
= recs
+ i
* CMAPRECLEN
;
110 tab
= cmap
+ U32(rec
, 4);
112 if (plat
== 3 && enc
== 1 && fmt
== 4)
117 static void otf_post(void *otf
, void *post
)
119 void *post2
; /* version 2.0 header */
120 void *index
; /* glyph name indices */
121 void *names
; /* glyph names */
124 if (U32(post
, 0) != 0x00020000)
127 glyph_n
= U16(post2
, 0);
129 names
= index
+ 2 * glyph_n
;
130 for (i
= 0; i
< glyph_n
; i
++) {
131 idx
= U16(index
, 2 * i
);
133 strcpy(glyph_name
[i
], macset
[idx
]);
135 memcpy(glyph_name
[i
], names
+ cname
+ 1,
137 glyph_name
[i
][U8(names
, cname
)] = '\0';
138 cname
+= U8(names
, cname
) + 1;
143 static void otf_glyf(void *otf
, void *glyf
)
145 void *maxp
= otf_table(otf
, "maxp");
146 void *head
= otf_table(otf
, "head");
147 void *loca
= otf_table(otf
, "loca");
150 int n
= U16(maxp
, 4);
151 int fmt
= U16(head
, 50);
153 for (i
= 0; i
< n
; i
++) {
155 gdat
= glyf
+ U32(loca
, 4 * i
);
156 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
158 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
159 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
161 if (gdat
< gdat_next
)
162 for (j
= 0; j
< 4; j
++)
163 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
167 static void otf_hmtx(void *otf
, void *hmtx
)
169 void *hhea
= otf_table(otf
, "hhea");
173 for (i
= 0; i
< n
; i
++)
174 glyph_wid
[i
] = U16(hmtx
, i
* 4);
175 for (i
= n
; i
< glyph_n
; i
++)
176 glyph_wid
[i
] = glyph_wid
[n
- 1];
179 static void otf_kern(void *otf
, void *kern
)
181 int n
; /* number of kern subtables */
182 void *tab
; /* a kern subtable */
189 for (i
= 0; i
< n
; i
++) {
193 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
194 npairs
= U16(tab
, 6);
195 for (j
= 0; j
< npairs
; j
++) {
196 c1
= U16(tab
, 14 + 6 * j
);
197 c2
= U16(tab
, 14 + 6 * j
+ 2);
198 val
= S16(tab
, 14 + 6 * j
+ 4);
199 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
206 static int coverage(void *cov
, int *out
)
208 int fmt
= U16(cov
, 0);
214 for (i
= 0; i
< n
; i
++)
215 out
[ncov
++] = U16(cov
, 4 + 2 * i
);
218 for (i
= 0; i
< n
; i
++) {
219 beg
= U16(cov
, 4 + 6 * i
);
220 end
= U16(cov
, 4 + 6 * i
+ 2);
221 for (j
= beg
; j
<= end
; j
++)
228 static int valuerecord_len(int fmt
)
232 for (i
= 0; i
< 8; i
++)
238 static void valuerecord_print(int fmt
, void *rec
)
243 for (i
= 0; i
< 8; i
++) {
244 if (fmt
& (1 << i
)) {
245 vals
[i
] = uwid(S16(rec
, off
));
250 printf(":%+d%+d%+d%+d", vals
[0], vals
[1], vals
[2], vals
[3]);
253 static void otf_gpostype1(void *otf
, char *feat
, char *sub
)
255 int fmt
= U16(sub
, 0);
256 int vfmt
= U16(sub
, 4);
259 int vlen
= valuerecord_len(vfmt
);
261 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
263 for (i
= 0; i
< ncov
; i
++) {
264 printf("gpos %s %s", feat
, glyph_name
[cov
[i
]]);
265 valuerecord_print(vfmt
, sub
+ 6);
271 for (i
= 0; i
< nvals
; i
++) {
272 printf("gpos %s %s", feat
, glyph_name
[cov
[i
]]);
273 valuerecord_print(vfmt
, sub
+ 8 + i
* vlen
);
279 static void otf_gpostype2(void *otf
, char *feat
, char *sub
)
281 int fmt
= U16(sub
, 0);
282 int vfmt1
= U16(sub
, 4);
283 int vfmt2
= U16(sub
, 6);
285 int nc1
= U16(sub
, 8);
288 int ncov
, nc2
, second
;
292 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
293 c2len
= 2 + valuerecord_len(vfmt1
) + valuerecord_len(vfmt2
);
294 for (i
= 0; i
< nc1
; i
++) {
295 c2
= sub
+ U16(sub
, 10 + 2 * i
);
297 for (j
= 0; j
< nc2
; j
++) {
298 printf("gpos %s 2", feat
);
299 second
= U16(c2
+ 2 + c2len
* j
, 0);
300 printf(" %s", glyph_name
[cov
[i
]]);
301 valuerecord_print(vfmt1
, c2
+ 2 + c2len
* j
+ 2);
302 printf(" %s", glyph_name
[second
]);
303 valuerecord_print(vfmt2
, c2
+ 2 + c2len
* j
+ 2 +
304 valuerecord_len(vfmt1
));
310 static void otf_gpostype3(void *otf
, char *feat
, char *sub
)
312 int fmt
= U16(sub
, 0);
315 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
319 for (i
= 0; i
< n
; i
++) {
320 int prev
= U16(sub
, 6 + 4 * i
);
321 int next
= U16(sub
, 6 + 4 * i
+ 2);
322 printf("gcur %s %s", feat
, glyph_name
[cov
[i
]]);
324 printf(" %d %d", uwid(S16(sub
, prev
+ 2)),
325 uwid(S16(sub
, prev
+ 4)));
329 printf(" %d %d", uwid(S16(sub
, next
+ 2)),
330 uwid(S16(sub
, next
+ 4)));
337 static void otf_gposfeatrec(void *otf
, void *gpos
, void *featrec
)
339 void *feats
= gpos
+ U16(gpos
, 6);
340 void *lookups
= gpos
+ U16(gpos
, 8);
341 void *feat
, *lookup
, *tab
;
342 int nlookups
, type
, flag
, ntabs
;
345 memcpy(tag
, featrec
, 4);
346 feat
= feats
+ U16(featrec
, 4);
347 nlookups
= U16(feat
, 2);
348 for (i
= 0; i
< nlookups
; i
++) {
349 lookup
= lookups
+ U16(lookups
, 2 + 2 * U16(feat
, 4 + 2 * i
));
350 type
= U16(lookup
, 0);
351 flag
= U16(lookup
, 2);
352 ntabs
= U16(lookup
, 4);
353 for (j
= 0; j
< ntabs
; j
++) {
354 tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
356 otf_gpostype1(otf
, tag
, tab
);
358 otf_gpostype2(otf
, tag
, tab
);
360 otf_gpostype3(otf
, tag
, tab
);
365 static void otf_gposlang(void *otf
, void *gpos
, void *lang
)
367 void *feats
= gpos
+ U16(gpos
, 6);
368 int featidx
= U16(lang
, 2);
369 int nfeat
= U16(lang
, 4);
371 if (featidx
!= 0xffff)
372 otf_gposfeatrec(otf
, gpos
, feats
+ 2 + 6 * featidx
);
373 for (i
= 0; i
< nfeat
; i
++)
374 otf_gposfeatrec(otf
, gpos
,
375 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
));
378 static void otf_gpos(void *otf
, void *gpos
)
380 void *scripts
= gpos
+ U16(gpos
, 4);
381 int nscripts
, nlangs
;
385 nscripts
= U16(scripts
, 0);
386 for (i
= 0; i
< nscripts
; i
++) {
387 grec
= scripts
+ 2 + 6 * i
;
388 script
= scripts
+ U16(grec
, 4);
390 otf_gposlang(otf
, gpos
, script
+ U16(script
, 0));
391 nlangs
= U16(script
, 2);
392 for (j
= 0; j
< nlangs
; j
++)
393 otf_gposlang(otf
, gpos
, script
+
394 U16(script
, 4 + 6 * j
+ 4));
398 static void otf_gsubtype1(void *otf
, char *feat
, char *sub
)
401 int fmt
= U16(sub
, 0);
405 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
407 for (i
= 0; i
< ncov
; i
++)
408 printf("gsub %s 2 -%s +%s\n",
409 feat
, glyph_name
[cov
[i
]],
410 glyph_name
[cov
[i
] + S16(sub
, 4)]);
414 for (i
= 0; i
< n
; i
++)
415 printf("gsub %s 2 -%s +%s\n",
416 feat
, glyph_name
[cov
[i
]],
417 glyph_name
[U16(sub
, 6 + 2 * i
)]);
421 static void otf_gsubtype3(void *otf
, char *feat
, char *sub
)
424 int fmt
= U16(sub
, 0);
428 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
430 for (i
= 0; i
< n
; i
++) {
431 void *alt
= sub
+ U16(sub
, 6 + 2 * i
);
432 int nalt
= U16(alt
, 0);
433 for (j
= 0; j
< nalt
; j
++)
434 printf("gsub %s 2 -%s +%s\n",
435 feat
, glyph_name
[cov
[i
]],
436 glyph_name
[U16(alt
, 2 + 2 * j
)]);
440 static void otf_gsubtype4(void *otf
, char *feat
, char *sub
)
442 int fmt
= U16(sub
, 0);
444 int ncov
, n
, i
, j
, k
;
447 ncov
= coverage(sub
+ U16(sub
, 2), cov
);
449 for (i
= 0; i
< n
; i
++) {
450 void *set
= sub
+ U16(sub
, 6 + 2 * i
);
451 int nset
= U16(set
, 0);
452 for (j
= 0; j
< nset
; j
++) {
453 void *lig
= set
+ U16(set
, 2 + 2 * j
);
454 int nlig
= U16(lig
, 2);
455 printf("gsub %s %d -%s",
456 feat
, nlig
+ 1, glyph_name
[cov
[i
]]);
457 for (k
= 0; k
< nlig
- 1; k
++)
458 printf(" -%s", glyph_name
[U16(lig
, 4 + 2 * k
)]);
459 printf(" +%s\n", glyph_name
[U16(lig
, 0)]);
464 static void otf_gsubfeatrec(void *otf
, void *gsub
, void *featrec
)
466 void *feats
= gsub
+ U16(gsub
, 6);
467 void *lookups
= gsub
+ U16(gsub
, 8);
468 void *feat
, *lookup
, *tab
;
469 int nlookups
, type
, flag
, ntabs
;
472 memcpy(tag
, featrec
, 4);
473 feat
= feats
+ U16(featrec
, 4);
474 nlookups
= U16(feat
, 2);
475 for (i
= 0; i
< nlookups
; i
++) {
476 lookup
= lookups
+ U16(lookups
, 2 + 2 * U16(feat
, 4 + 2 * i
));
477 type
= U16(lookup
, 0);
478 flag
= U16(lookup
, 2);
479 ntabs
= U16(lookup
, 4);
480 for (j
= 0; j
< ntabs
; j
++) {
481 tab
= lookup
+ U16(lookup
, 6 + 2 * j
);
483 otf_gsubtype1(otf
, tag
, tab
);
485 otf_gsubtype3(otf
, tag
, tab
);
487 otf_gsubtype4(otf
, tag
, tab
);
492 static void otf_gsublang(void *otf
, void *gsub
, void *lang
)
494 void *feats
= gsub
+ U16(gsub
, 6);
495 int featidx
= U16(lang
, 2);
496 int nfeat
= U16(lang
, 4);
498 if (featidx
!= 0xffff)
499 otf_gsubfeatrec(otf
, gsub
, feats
+ 2 + 6 * featidx
);
500 for (i
= 0; i
< nfeat
; i
++)
501 otf_gsubfeatrec(otf
, gsub
,
502 feats
+ 2 + 6 * U16(lang
, 6 + 2 * i
));
505 static void otf_gsub(void *otf
, void *gsub
)
507 void *scripts
= gsub
+ U16(gsub
, 4);
508 int nscripts
, nlangs
;
511 nscripts
= U16(scripts
, 0);
512 for (i
= 0; i
< nscripts
; i
++) {
513 script
= scripts
+ U16(scripts
+ 2 + 6 * i
, 4);
514 nlangs
= U16(script
, 2);
516 otf_gsublang(otf
, gsub
, script
+ U16(script
, 0));
517 for (j
= 0; j
< nlangs
; j
++)
518 otf_gsublang(otf
, gsub
, script
+
519 U16(script
, 4 + 6 * j
+ 4));
523 int xread(int fd
, char *buf
, int len
)
527 int ret
= read(fd
, buf
+ nr
, len
- nr
);
528 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
537 static char buf
[BUFLEN
];
542 if (xread(0, buf
, sizeof(buf
)) <= 0)
544 upm
= U16(otf_table(buf
, "head"), 18);
545 otf_cmap(buf
, otf_table(buf
, "cmap"));
546 otf_post(buf
, otf_table(buf
, "post"));
547 if (otf_table(buf
, "glyf"))
548 otf_glyf(buf
, otf_table(buf
, "glyf"));
549 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
550 for (i
= 0; i
< glyph_n
; i
++) {
551 trfn_char(glyph_name
[i
], -1,
552 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
554 owid(glyph_bbox
[i
][0]), owid(glyph_bbox
[i
][1]),
555 owid(glyph_bbox
[i
][2]), owid(glyph_bbox
[i
][3]));
557 if (otf_table(buf
, "kern"))
558 otf_kern(buf
, otf_table(buf
, "kern"));
565 if (otf_table(buf
, "GSUB"))
566 otf_gsub(buf
, otf_table(buf
, "GSUB"));
567 if (otf_table(buf
, "GPOS"))
568 otf_gpos(buf
, otf_table(buf
, "GPOS"));
571 static char *macset
[] = {
572 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
573 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
574 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
575 "comma", "hyphen", "period", "slash", "zero",
576 "one", "two", "three", "four", "five",
577 "six", "seven", "eight", "nine", "colon",
578 "semicolon", "less", "equal", "greater", "question",
579 "at", "A", "B", "C", "D",
580 "E", "F", "G", "H", "I",
581 "J", "K", "L", "M", "N",
582 "O", "P", "Q", "R", "S",
583 "T", "U", "V", "W", "X",
584 "Y", "Z", "bracketleft", "backslash", "bracketright",
585 "asciicircum", "underscore", "grave", "a", "b",
586 "c", "d", "e", "f", "g",
587 "h", "i", "j", "k", "l",
588 "m", "n", "o", "p", "q",
589 "r", "s", "t", "u", "v",
590 "w", "x", "y", "z", "braceleft",
591 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
592 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
593 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
594 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
595 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
596 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
597 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
598 "dagger", "degree", "cent", "sterling", "section",
599 "bullet", "paragraph", "germandbls", "registered", "copyright",
600 "trademark", "acute", "dieresis", "notequal", "AE",
601 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
602 "yen", "mu", "partialdiff", "summation", "product",
603 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
604 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
605 "radical", "florin", "approxequal", "Delta", "guillemotleft",
606 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
607 "Otilde", "OE", "oe", "endash", "emdash",
608 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
609 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
610 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
611 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
612 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
613 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
614 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
615 "dotlessi", "circumflex", "tilde", "macron", "breve",
616 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
617 "caron", "Lslash", "lslash", "Scaron", "scaron",
618 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
619 "Yacute", "yacute", "Thorn", "thorn", "minus",
620 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
621 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
622 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
623 "Ccaron", "ccaron", "dcroat",