8 #define NGLYPHS (1 << 14)
10 #define BUFLEN (1 << 23)
11 #define OWID(w) ((w) * 1000 / (upm))
13 #define U32(buf, off) (htonl(*(u32 *) ((buf) + (off))))
14 #define U16(buf, off) (htons(*(u16 *) ((buf) + (off))))
15 #define U8(buf, off) (*(u8 *) ((buf) + (off)))
16 #define S16(buf, off) ((s16) htons(*(u16 *) ((buf) + (off))))
17 #define S32(buf, off) ((s32) htonl(*(u32 *) ((buf) + (off))))
19 #define OTFLEN 12 /* otf header length */
20 #define OTFRECLEN 16 /* otf header record length */
21 #define CMAPLEN 4 /* cmap header length */
22 #define CMAPRECLEN 8 /* cmap record length */
23 #define CMAP4LEN 8 /* format 4 cmap subtable header length */
25 typedef unsigned int u32
;
26 typedef unsigned short u16
;
27 typedef unsigned char u8
;
31 static char glyph_name
[NGLYPHS
][GNLEN
];
32 static int glyph_code
[NGLYPHS
];
33 static int glyph_bbox
[NGLYPHS
][4];
34 static int glyph_wid
[NGLYPHS
];
36 static int upm
; /* units per em */
38 static char *macset
[];
40 /* find the otf table with the given name */
41 static void *otf_table(void *otf
, char *name
)
43 void *recs
= otf
+ OTFLEN
; /* otf table records */
44 void *rec
; /* beginning of a table record */
45 int nrecs
= U16(otf
, 4);
47 for (i
= 0; i
< nrecs
; i
++) {
48 rec
= recs
+ i
* OTFRECLEN
;
49 if (!strncmp(rec
, name
, 4))
50 return otf
+ U32(rec
, 8);
55 /* parse otf cmap format 4 subtable */
56 static void otf_cmap4(void *otf
, void *cmap4
)
59 void *ends
, *begs
, *deltas
, *offsets
;
61 int beg
, end
, delta
, offset
;
63 nsegs
= U16(cmap4
, 6) / 2;
65 begs
= ends
+ 2 * nsegs
+ 2;
66 deltas
= begs
+ 2 * nsegs
;
67 offsets
= deltas
+ 2 * nsegs
;
68 idarray
= offsets
+ 2 * nsegs
;
69 for (i
= 0; i
< nsegs
; i
++) {
70 beg
= U16(begs
, 2 * i
);
71 end
= U16(ends
, 2 * i
);
72 delta
= U16(deltas
, 2 * i
);
73 offset
= U16(offsets
, 2 * i
);
75 for (j
= beg
; j
<= end
; j
++)
76 glyph_code
[U16(offsets
+ i
* 2,
77 offset
+ (j
- beg
) * 2)] = j
;
79 for (j
= beg
; j
<= end
; j
++)
80 glyph_code
[(j
+ delta
) & 0xffff] = j
;
85 /* parse otf cmap header */
86 static void otf_cmap(void *otf
, void *cmap
)
88 void *recs
= cmap
+ CMAPLEN
; /* cmap records */
89 void *rec
; /* a cmap record */
90 void *tab
; /* a cmap subtable */
93 int nrecs
= U16(cmap
, 2);
95 for (i
= 0; i
< nrecs
; i
++) {
96 rec
= recs
+ i
* CMAPRECLEN
;
99 tab
= cmap
+ U32(rec
, 4);
101 if (plat
== 3 && enc
== 1 && fmt
== 4)
106 static void otf_post(void *otf
, void *post
)
108 void *post2
; /* version 2.0 header */
109 void *index
; /* glyph name indices */
110 void *names
; /* glyph names */
113 if (U32(post
, 0) != 0x00020000)
116 glyph_n
= U16(post2
, 0);
118 names
= index
+ 2 * glyph_n
;
119 for (i
= 0; i
< glyph_n
; i
++) {
120 idx
= U16(index
, 2 * i
);
122 strcpy(glyph_name
[i
], macset
[idx
]);
124 memcpy(glyph_name
[i
], names
+ cname
+ 1,
126 glyph_name
[i
][U8(names
, cname
)] = '\0';
127 cname
+= U8(names
, cname
) + 1;
132 static void otf_glyf(void *otf
, void *glyf
)
134 void *maxp
= otf_table(otf
, "maxp");
135 void *head
= otf_table(otf
, "head");
136 void *loca
= otf_table(otf
, "loca");
139 int n
= U16(maxp
, 4);
140 int fmt
= U16(head
, 50);
142 for (i
= 0; i
< n
; i
++) {
144 gdat
= glyf
+ U32(loca
, 4 * i
);
145 gdat_next
= glyf
+ U32(loca
, 4 * (i
+ 1));
147 gdat
= glyf
+ U16(loca
, 2 * i
) * 2;
148 gdat_next
= glyf
+ U16(loca
, 2 * (i
+ 1)) * 2;
150 if (gdat
< gdat_next
)
151 for (j
= 0; j
< 4; j
++)
152 glyph_bbox
[i
][j
] = S16(gdat
, 2 + 2 * j
);
156 static void otf_hmtx(void *otf
, void *hmtx
)
158 void *hhea
= otf_table(otf
, "hhea");
162 for (i
= 0; i
< n
; i
++)
163 glyph_wid
[i
] = U16(hmtx
, i
* 4);
164 for (i
= n
; i
< glyph_n
; i
++)
165 glyph_wid
[i
] = glyph_wid
[n
- 1];
168 static void otf_kern(void *otf
, void *kern
)
170 int n
; /* number of kern subtables */
171 void *tab
; /* a kern subtable */
178 for (i
= 0; i
< n
; i
++) {
182 if ((cov
>> 8) == 0 && (cov
& 1)) { /* format 0 */
183 npairs
= U16(tab
, 6);
184 for (j
= 0; j
< npairs
; j
++) {
185 c1
= U16(tab
, 14 + 6 * j
);
186 c2
= U16(tab
, 14 + 6 * j
+ 2);
187 val
= S16(tab
, 14 + 6 * j
+ 4);
188 trfn_kern(glyph_name
[c1
], glyph_name
[c2
],
195 int xread(int fd
, char *buf
, int len
)
199 int ret
= read(fd
, buf
+ nr
, len
- nr
);
200 if (ret
== -1 && (errno
== EAGAIN
|| errno
== EINTR
))
209 static char buf
[BUFLEN
];
214 if (xread(0, buf
, sizeof(buf
)) <= 0)
216 upm
= U16(otf_table(buf
, "head"), 18);
217 otf_cmap(buf
, otf_table(buf
, "cmap"));
218 otf_post(buf
, otf_table(buf
, "post"));
219 if (otf_table(buf
, "glyf"))
220 otf_glyf(buf
, otf_table(buf
, "glyf"));
221 otf_hmtx(buf
, otf_table(buf
, "hmtx"));
222 for (i
= 0; i
< glyph_n
; i
++) {
223 trfn_char(glyph_name
[i
], -1,
224 glyph_code
[i
] != 0xffff ? glyph_code
[i
] : 0,
226 OWID(glyph_bbox
[i
][0]), OWID(glyph_bbox
[i
][1]),
227 OWID(glyph_bbox
[i
][2]), OWID(glyph_bbox
[i
][3]));
229 otf_kern(buf
, otf_table(buf
, "kern"));
233 static char *macset
[] = {
234 ".notdef", ".null", "nonmarkingreturn", "space", "exclam",
235 "quotedbl", "numbersign", "dollar", "percent", "ampersand",
236 "quotesingle", "parenleft", "parenright", "asterisk", "plus",
237 "comma", "hyphen", "period", "slash", "zero",
238 "one", "two", "three", "four", "five",
239 "six", "seven", "eight", "nine", "colon",
240 "semicolon", "less", "equal", "greater", "question",
241 "at", "A", "B", "C", "D",
242 "E", "F", "G", "H", "I",
243 "J", "K", "L", "M", "N",
244 "O", "P", "Q", "R", "S",
245 "T", "U", "V", "W", "X",
246 "Y", "Z", "bracketleft", "backslash", "bracketright",
247 "asciicircum", "underscore", "grave", "a", "b",
248 "c", "d", "e", "f", "g",
249 "h", "i", "j", "k", "l",
250 "m", "n", "o", "p", "q",
251 "r", "s", "t", "u", "v",
252 "w", "x", "y", "z", "braceleft",
253 "bar", "braceright", "asciitilde", "Adieresis", "Aring",
254 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
255 "aacute", "agrave", "acircumflex", "adieresis", "atilde",
256 "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
257 "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
258 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
259 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
260 "dagger", "degree", "cent", "sterling", "section",
261 "bullet", "paragraph", "germandbls", "registered", "copyright",
262 "trademark", "acute", "dieresis", "notequal", "AE",
263 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
264 "yen", "mu", "partialdiff", "summation", "product",
265 "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
266 "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
267 "radical", "florin", "approxequal", "Delta", "guillemotleft",
268 "guillemotright", "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
269 "Otilde", "OE", "oe", "endash", "emdash",
270 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
271 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
272 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
273 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
274 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
275 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
276 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
277 "dotlessi", "circumflex", "tilde", "macron", "breve",
278 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
279 "caron", "Lslash", "lslash", "Scaron", "scaron",
280 "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
281 "Yacute", "yacute", "Thorn", "thorn", "minus",
282 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
283 "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
284 "Idotaccent", "Scedilla", "scedilla", "Cacute", "cacute",
285 "Ccaron", "ccaron", "dcroat",