2 * sfnt2fon. Bitmap-only ttf to Windows font file converter
4 * Copyright 2004 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #ifdef HAVE_FT2BUILD_H
34 #include FT_FREETYPE_H
35 #include FT_SFNT_NAMES_H
36 #include FT_TRUETYPE_TABLES_H
37 #include FT_TRUETYPE_TAGS_H
54 INT16 dfInternalLeading
;
55 INT16 dfExternalLeading
;
63 BYTE dfPitchAndFamily
;
106 CHAR caretSlopeNumerator
;
107 CHAR caretSlopeDenominator
;
118 ULONG indexSubTableArrayOffset
;
119 ULONG indexTableSize
;
120 ULONG numberOfIndexSubTables
;
122 sbitLineMetrics_t hori
;
123 sbitLineMetrics_t vert
;
124 USHORT startGlyphIndex
;
125 USHORT endGlyphIndex
;
138 static FT_Version_t FT_Version
;
142 unsigned char *output_buffer
= NULL
;
143 size_t output_buffer_pos
= 0;
144 size_t output_buffer_size
= 0;
146 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
147 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
148 GET_BE_WORD(&((WORD *)(ptr))[0]) ))
153 CHAR_TABLE_ENTRY dfCharTable
[258];
157 static const BYTE MZ_hdr
[] =
159 'M', 'Z', 0x0d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
160 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
163 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
164 'i', 's', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
165 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
166 'm', 'o', 'd', 'e', 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
169 static const WCHAR encoding_1250
[128] =
171 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
172 0x0088, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
173 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
174 0x0098, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
175 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
176 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
177 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
178 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
179 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
180 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
181 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
182 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
183 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
184 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
185 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
186 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
189 static const WCHAR encoding_1251
[128] =
191 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
192 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
193 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
194 0x0098, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
195 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
196 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
197 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
198 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
199 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
200 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
201 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
202 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
203 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
204 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
205 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
206 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f
209 static const WCHAR encoding_1252
[128] =
211 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
212 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
213 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
214 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,
215 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
216 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
217 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
218 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
219 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
220 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
221 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
222 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
223 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
224 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
225 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
226 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
229 static const WCHAR encoding_1253
[128] =
231 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
232 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
233 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
234 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
235 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
236 0x00a8, 0x00a9, 0xf8f9, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
237 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7,
238 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
239 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
240 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
241 0x03a0, 0x03a1, 0xf8fa, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
242 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
243 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
244 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
245 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
246 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xf8fb
249 static const WCHAR encoding_1254
[128] =
251 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
252 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
253 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
254 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
255 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
256 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
257 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
258 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
259 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
260 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
261 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
262 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
263 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
264 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
265 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
266 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff
269 static const WCHAR encoding_1255
[128] =
271 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
272 0x02c6, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
273 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
274 0x02dc, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
275 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7,
276 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
277 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
278 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
279 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
280 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
281 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3,
282 0x05f4, 0xf88d, 0xf88e, 0xf88f, 0xf890, 0xf891, 0xf892, 0xf893,
283 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
284 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
285 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
286 0x05e8, 0x05e9, 0x05ea, 0xf894, 0xf895, 0x200e, 0x200f, 0xf896
289 static const WCHAR encoding_1256
[128] =
291 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
292 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
293 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
294 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
295 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
296 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
297 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
298 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
299 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
300 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
301 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7,
302 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
303 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7,
304 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
305 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7,
306 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2
309 static const WCHAR encoding_1257
[128] =
311 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
312 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x00a8, 0x02c7, 0x00b8,
313 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
314 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x00af, 0x02db, 0x009f,
315 0x00a0, 0xf8fc, 0x00a2, 0x00a3, 0x00a4, 0xf8fd, 0x00a6, 0x00a7,
316 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
317 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
318 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
319 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112,
320 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
321 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7,
322 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
323 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113,
324 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
325 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7,
326 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9
329 static const WCHAR encoding_874
[128] =
331 0x20ac, 0x0081, 0x0082, 0x0083, 0x0084, 0x2026, 0x0086, 0x0087,
332 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
333 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
334 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
335 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
336 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
337 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
338 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
339 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
340 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
341 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
342 0x0e38, 0x0e39, 0x0e3a, 0xf8c1, 0xf8c2, 0xf8c3, 0xf8c4, 0x0e3f,
343 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
344 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
345 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
346 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf8c5, 0xf8c6, 0xf8c7, 0xf8c8
349 static const struct { int codepage
; const WCHAR
*table
; } encodings
[] =
351 { 874, encoding_874
},
352 { 1250, encoding_1250
},
353 { 1251, encoding_1251
},
354 { 1252, encoding_1252
},
355 { 1253, encoding_1253
},
356 { 1254, encoding_1254
},
357 { 1255, encoding_1255
},
358 { 1256, encoding_1256
},
359 { 1257, encoding_1257
},
360 { 0, encoding_1252
}, /* default encoding */
363 static int option_defchar
= ' ';
364 static int option_dpi
= 96;
365 static int option_fnt_mode
= 0;
366 static int option_quiet
= 0;
368 static const char *output_name
;
370 static FT_Library ft_library
;
372 static const char *argv0
;
374 static void usage(void)
376 fprintf(stderr
, "%s [options] input.ttf ppem,enc,avg_width ...\n", argv0
);
377 fprintf(stderr
, "Options:\n");
378 fprintf(stderr
, " -h Display help\n" );
379 fprintf(stderr
, " -d char Set the font default char\n" );
380 fprintf(stderr
, " -o file Set output file name\n" );
381 fprintf(stderr
, " -q Quiet mode\n" );
382 fprintf(stderr
, " -r dpi Set resolution in DPI (default: 96)\n" );
383 fprintf(stderr
, " -s Single .fnt file mode\n" );
386 /* atexit handler to cleanup files */
387 static void cleanup(void)
389 if (output_name
) unlink( output_name
);
392 static void exit_on_signal( int sig
)
394 exit(1); /* this will call the atexit functions */
397 static void error(const char *s
, ...) __attribute__((format (printf
, 1, 2)));
399 static void error(const char *s
, ...)
403 fprintf(stderr
, "Error: ");
404 vfprintf(stderr
, s
, ap
);
409 static const char *get_face_name( const struct fontinfo
*info
)
411 return (const char *)info
->data
+ info
->hdr
.fi
.dfFace
- info
->hdr
.fi
.dfBitsOffset
;
414 static int lookup_charset(int enc
)
416 /* FIXME: make winelib app and use TranslateCharsetInfo */
421 return RUSSIAN_CHARSET
;
425 return GREEK_CHARSET
;
427 return TURKISH_CHARSET
;
429 return HEBREW_CHARSET
;
431 return ARABIC_CHARSET
;
433 return BALTIC_CHARSET
;
435 return VIETNAMESE_CHARSET
;
455 return SHIFTJIS_CHARSET
;
457 return GB2312_CHARSET
;
459 return HANGUL_CHARSET
;
461 return CHINESEBIG5_CHARSET
;
463 fprintf(stderr
, "Unknown encoding %d - using OEM_CHARSET\n", enc
);
468 static void get_char_table(int enc
, WCHAR tableW
[0x100])
472 for (i
= 0; i
< 128; i
++) tableW
[i
] = i
;
474 for (i
= 0; encodings
[i
].codepage
; i
++) if (encodings
[i
].codepage
== enc
) break;
475 memcpy( tableW
+ 128, encodings
[i
].table
, 128 * sizeof(WCHAR
) );
477 /* Korean has the Won sign in place of '\\' */
478 if (enc
== 949) tableW
['\\'] = 0x20a9;
481 static struct fontinfo
*fill_fontinfo( const char *face_name
, int ppem
, int enc
, int dpi
,
482 unsigned char def_char
, int avg_width
)
485 int ascent
= 0, il
, el
, width_bytes
= 0, space_size
, max_width
= 0;
486 BYTE left_byte
, right_byte
, byte
;
488 int i
, x
, y
, x_off
, x_end
, first_char
;
491 FT_SfntName sfntname
;
495 bitmapSizeTable_t
*size_table
;
497 struct fontinfo
*info
;
501 if (FT_New_Face(ft_library
, face_name
, 0, &face
)) error( "Cannot open face %s\n", face_name
);
502 if (FT_Set_Pixel_Sizes(face
, ppem
, ppem
)) error( "cannot set face size to %u\n", ppem
);
504 assert( face
->size
->metrics
.y_ppem
== ppem
);
506 get_char_table( enc
, table
);
509 if (FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, NULL
, &needed
))
510 fprintf(stderr
,"Can't find EBLC table\n");
513 eblc
= xmalloc(needed
);
514 FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, (FT_Byte
*)eblc
, &needed
);
516 num_sizes
= GET_BE_DWORD(&eblc
->numSizes
);
518 size_table
= (bitmapSizeTable_t
*)(eblc
+ 1);
519 for(i
= 0; i
< num_sizes
; i
++)
521 if( (signed char)size_table
->hori
.ascender
- (signed char)size_table
->hori
.descender
== ppem
)
523 ascent
= size_table
->hori
.ascender
;
532 /* Versions of fontforge prior to early 2006 have incorrect
533 ascender values in the eblc table, so we won't find the
534 correct bitmapSizeTable. In this case use the height of
535 the Aring glyph instead. */
538 if(FT_Load_Char(face
, 0xc5, FT_LOAD_DEFAULT
))
539 error("Can't find Aring\n");
540 ascent
= face
->glyph
->metrics
.horiBearingY
>> 6;
543 start
= sizeof(FNT_HEADER
);
545 if(FT_Load_Char(face
, 'M', FT_LOAD_DEFAULT
))
546 error("Can't find M\n");
547 il
= ascent
- (face
->glyph
->metrics
.height
>> 6);
549 /* Hack: Courier has no internal leading, nor do any Chinese or Japanese fonts */
550 if(!strcmp(face
->family_name
, "Courier") || enc
== 936 || enc
== 950 || enc
== 932)
552 else if (!strcmp(face
->family_name
, "Fixedsys"))
555 /* Japanese System font has an external leading */
556 if (!strcmp(face
->family_name
, "System") && enc
== 932)
561 first_char
= FT_Get_First_Char(face
, &gi
);
562 if(first_char
< 0x20) /* Ignore glyphs below 0x20 */
563 first_char
= 0x20; /* FT_Get_Next_Char for some reason returns too high
564 number in this case */
566 info
= calloc( 1, sizeof(*info
) );
568 info
->hdr
.fi
.dfFirstChar
= first_char
;
569 info
->hdr
.fi
.dfLastChar
= 0xff;
570 start
+= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
+ 3 ) * sizeof(*info
->dfCharTable
);
572 num_names
= FT_Get_Sfnt_Name_Count(face
);
573 for(i
= 0; i
<num_names
; i
++) {
574 FT_Get_Sfnt_Name(face
, i
, &sfntname
);
575 if(sfntname
.platform_id
== 1 && sfntname
.encoding_id
== 0 &&
576 sfntname
.language_id
== 0 && sfntname
.name_id
== 0) {
577 size_t len
= min( sfntname
.string_len
, sizeof(info
->hdr
.dfCopyright
)-1 );
578 memcpy(info
->hdr
.dfCopyright
, sfntname
.string
, len
);
579 info
->hdr
.dfCopyright
[len
] = 0;
583 os2
= FT_Get_Sfnt_Table(face
, ft_sfnt_os2
);
584 for(i
= first_char
; i
< 0x100; i
++) {
585 gi
= FT_Get_Char_Index(face
, table
[i
]);
586 if(gi
== 0 && !option_quiet
)
587 fprintf(stderr
, "warning: %s %u: missing glyph for char %04x\n",
588 face
->family_name
, ppem
, table
[i
]);
589 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
590 fprintf(stderr
, "error loading char %d - bad news!\n", i
);
593 info
->dfCharTable
[i
].width
= face
->glyph
->metrics
.horiAdvance
>> 6;
594 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
595 width_bytes
+= ((face
->glyph
->metrics
.horiAdvance
>> 6) + 7) >> 3;
596 if(max_width
< (face
->glyph
->metrics
.horiAdvance
>> 6))
597 max_width
= face
->glyph
->metrics
.horiAdvance
>> 6;
600 space_size
= (ppem
+ 3) / 4;
601 info
->dfCharTable
[i
].width
= space_size
;
602 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
603 width_bytes
+= (space_size
+ 7) >> 3;
605 info
->dfCharTable
[++i
].width
= 0;
606 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
608 info
->hdr
.fi
.dfType
= 0;
609 info
->hdr
.fi
.dfPoints
= ((ppem
- il
- el
) * 72 + dpi
/2) / dpi
;
610 info
->hdr
.fi
.dfVertRes
= dpi
;
611 info
->hdr
.fi
.dfHorizRes
= dpi
;
612 info
->hdr
.fi
.dfAscent
= ascent
;
613 info
->hdr
.fi
.dfInternalLeading
= il
;
614 info
->hdr
.fi
.dfExternalLeading
= el
;
615 info
->hdr
.fi
.dfItalic
= (face
->style_flags
& FT_STYLE_FLAG_ITALIC
) ? 1 : 0;
616 info
->hdr
.fi
.dfUnderline
= 0;
617 info
->hdr
.fi
.dfStrikeOut
= 0;
618 info
->hdr
.fi
.dfWeight
= os2
->usWeightClass
;
619 info
->hdr
.fi
.dfCharSet
= lookup_charset(enc
);
620 info
->hdr
.fi
.dfPixWidth
= (face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) ? avg_width
: 0;
621 info
->hdr
.fi
.dfPixHeight
= ppem
;
622 info
->hdr
.fi
.dfPitchAndFamily
= FT_IS_FIXED_WIDTH(face
) ? 0 : TMPF_FIXED_PITCH
;
623 switch(os2
->panose
[PAN_FAMILYTYPE_INDEX
]) {
624 case PAN_FAMILY_SCRIPT
:
625 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SCRIPT
;
627 case PAN_FAMILY_DECORATIVE
:
628 case PAN_FAMILY_PICTORIAL
:
629 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DECORATIVE
;
631 case PAN_FAMILY_TEXT_DISPLAY
:
632 if(info
->hdr
.fi
.dfPitchAndFamily
== 0) /* fixed */
633 info
->hdr
.fi
.dfPitchAndFamily
= FF_MODERN
;
635 switch(os2
->panose
[PAN_SERIFSTYLE_INDEX
]) {
636 case PAN_SERIF_NORMAL_SANS
:
637 case PAN_SERIF_OBTUSE_SANS
:
638 case PAN_SERIF_PERP_SANS
:
639 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SWISS
;
642 info
->hdr
.fi
.dfPitchAndFamily
|= FF_ROMAN
;
647 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DONTCARE
;
650 info
->hdr
.fi
.dfAvgWidth
= avg_width
;
651 info
->hdr
.fi
.dfMaxWidth
= (enc
== 932) ? avg_width
* 2 : max_width
;
652 info
->hdr
.fi
.dfDefaultChar
= def_char
- info
->hdr
.fi
.dfFirstChar
;
653 info
->hdr
.fi
.dfBreakChar
= ' ' - info
->hdr
.fi
.dfFirstChar
;
654 info
->hdr
.fi
.dfWidthBytes
= (width_bytes
+ 1) & ~1;
656 info
->hdr
.fi
.dfFace
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
;
657 info
->hdr
.fi
.dfBitsOffset
= start
;
658 info
->hdr
.fi
.dfFlags
= 0x10; /* DFF_1COLOR */
659 info
->hdr
.fi
.dfFlags
|= FT_IS_FIXED_WIDTH(face
) ? 1 : 2; /* DFF_FIXED : DFF_PROPORTIONAL */
661 info
->hdr
.dfVersion
= 0x300;
662 info
->hdr
.dfSize
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
+ strlen(face
->family_name
) + 1;
664 info
->data
= calloc( info
->hdr
.dfSize
- start
, 1 );
667 for(i
= first_char
; i
< 0x100; i
++) {
668 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
671 assert(info
->dfCharTable
[i
].width
== face
->glyph
->metrics
.horiAdvance
>> 6);
673 for(x
= 0; x
< ((info
->dfCharTable
[i
].width
+ 7) / 8); x
++) {
674 for(y
= 0; y
< ppem
; y
++) {
675 if(y
< ascent
- face
->glyph
->bitmap_top
||
676 y
>= (int)face
->glyph
->bitmap
.rows
+ ascent
- face
->glyph
->bitmap_top
) {
677 info
->data
[data_pos
++] = 0;
680 x_off
= face
->glyph
->bitmap_left
/ 8;
681 x_end
= (face
->glyph
->bitmap_left
+ face
->glyph
->bitmap
.width
- 1) / 8;
682 if(x
< x_off
|| x
> x_end
) {
683 info
->data
[data_pos
++] = 0;
689 left_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
- 1];
691 /* On the last non-trivial output byte (x == x_end) have we got one or two input bytes */
692 if(x
== x_end
&& (face
->glyph
->bitmap_left
% 8 != 0) && ((face
->glyph
->bitmap
.width
% 8 == 0) || (x
!= (((face
->glyph
->bitmap
.width
) & ~0x7) + face
->glyph
->bitmap_left
) / 8)))
695 right_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
];
697 byte
= (left_byte
<< (8 - (face
->glyph
->bitmap_left
& 7))) & 0xff;
698 byte
|= ((right_byte
>> (face
->glyph
->bitmap_left
& 7)) & 0xff);
699 info
->data
[data_pos
++] = byte
;
703 data_pos
+= ((space_size
+ 7) / 8) * ppem
;
704 if (width_bytes
& 1) data_pos
+= ppem
;
706 memcpy( info
->data
+ data_pos
, face
->family_name
, strlen( face
->family_name
));
707 data_pos
+= strlen( face
->family_name
) + 1;
708 assert( start
+ data_pos
== info
->hdr
.dfSize
);
710 FT_Done_Face( face
);
714 static void put_fontdir( const struct fontinfo
*info
)
716 const char *name
= get_face_name( info
);
718 put_word( info
->hdr
.dfVersion
);
719 put_dword( info
->hdr
.dfSize
);
720 put_data( info
->hdr
.dfCopyright
, sizeof(info
->hdr
.dfCopyright
) );
721 put_word( info
->hdr
.fi
.dfType
);
722 put_word( info
->hdr
.fi
.dfPoints
);
723 put_word( info
->hdr
.fi
.dfVertRes
);
724 put_word( info
->hdr
.fi
.dfHorizRes
);
725 put_word( info
->hdr
.fi
.dfAscent
);
726 put_word( info
->hdr
.fi
.dfInternalLeading
);
727 put_word( info
->hdr
.fi
.dfExternalLeading
);
728 put_byte( info
->hdr
.fi
.dfItalic
);
729 put_byte( info
->hdr
.fi
.dfUnderline
);
730 put_byte( info
->hdr
.fi
.dfStrikeOut
);
731 put_word( info
->hdr
.fi
.dfWeight
);
732 put_byte( info
->hdr
.fi
.dfCharSet
);
733 put_word( info
->hdr
.fi
.dfPixWidth
);
734 put_word( info
->hdr
.fi
.dfPixHeight
);
735 put_byte( info
->hdr
.fi
.dfPitchAndFamily
);
736 put_word( info
->hdr
.fi
.dfAvgWidth
);
737 put_word( info
->hdr
.fi
.dfMaxWidth
);
738 put_byte( info
->hdr
.fi
.dfFirstChar
);
739 put_byte( info
->hdr
.fi
.dfLastChar
);
740 put_byte( info
->hdr
.fi
.dfDefaultChar
);
741 put_byte( info
->hdr
.fi
.dfBreakChar
);
742 put_word( info
->hdr
.fi
.dfWidthBytes
);
743 put_dword( info
->hdr
.fi
.dfDevice
);
744 put_dword( info
->hdr
.fi
.dfFace
);
745 put_dword( 0 ); /* dfReserved */
746 put_byte( 0 ); /* szDeviceName */
747 put_data( name
, strlen(name
) + 1 ); /* szFaceName */
750 static void put_font( const struct fontinfo
*info
)
754 put_word( info
->hdr
.dfVersion
);
755 put_dword( info
->hdr
.dfSize
);
756 put_data( info
->hdr
.dfCopyright
, sizeof(info
->hdr
.dfCopyright
) );
757 put_word( info
->hdr
.fi
.dfType
);
758 put_word( info
->hdr
.fi
.dfPoints
);
759 put_word( info
->hdr
.fi
.dfVertRes
);
760 put_word( info
->hdr
.fi
.dfHorizRes
);
761 put_word( info
->hdr
.fi
.dfAscent
);
762 put_word( info
->hdr
.fi
.dfInternalLeading
);
763 put_word( info
->hdr
.fi
.dfExternalLeading
);
764 put_byte( info
->hdr
.fi
.dfItalic
);
765 put_byte( info
->hdr
.fi
.dfUnderline
);
766 put_byte( info
->hdr
.fi
.dfStrikeOut
);
767 put_word( info
->hdr
.fi
.dfWeight
);
768 put_byte( info
->hdr
.fi
.dfCharSet
);
769 put_word( info
->hdr
.fi
.dfPixWidth
);
770 put_word( info
->hdr
.fi
.dfPixHeight
);
771 put_byte( info
->hdr
.fi
.dfPitchAndFamily
);
772 put_word( info
->hdr
.fi
.dfAvgWidth
);
773 put_word( info
->hdr
.fi
.dfMaxWidth
);
774 put_byte( info
->hdr
.fi
.dfFirstChar
);
775 put_byte( info
->hdr
.fi
.dfLastChar
);
776 put_byte( info
->hdr
.fi
.dfDefaultChar
);
777 put_byte( info
->hdr
.fi
.dfBreakChar
);
778 put_word( info
->hdr
.fi
.dfWidthBytes
);
779 put_dword( info
->hdr
.fi
.dfDevice
);
780 put_dword( info
->hdr
.fi
.dfFace
);
781 put_dword( info
->hdr
.fi
.dfBitsPointer
);
782 put_dword( info
->hdr
.fi
.dfBitsOffset
);
783 put_byte( info
->hdr
.fi
.dfReserved
);
784 put_dword( info
->hdr
.fi
.dfFlags
);
785 put_word( info
->hdr
.fi
.dfAspace
);
786 put_word( info
->hdr
.fi
.dfBspace
);
787 put_word( info
->hdr
.fi
.dfCspace
);
788 put_dword( info
->hdr
.fi
.dfColorPointer
);
789 put_dword( info
->hdr
.fi
.dfReserved1
[0] );
790 put_dword( info
->hdr
.fi
.dfReserved1
[1] );
791 put_dword( info
->hdr
.fi
.dfReserved1
[2] );
792 put_dword( info
->hdr
.fi
.dfReserved1
[3] );
793 num_chars
= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
) + 3;
794 for (i
= 0; i
< num_chars
; i
++)
796 put_word( info
->dfCharTable
[info
->hdr
.fi
.dfFirstChar
+ i
].width
);
797 put_dword( info
->dfCharTable
[info
->hdr
.fi
.dfFirstChar
+ i
].offset
);
799 put_data( info
->data
, info
->hdr
.dfSize
- info
->hdr
.fi
.dfBitsOffset
);
802 static void option_callback( int optc
, char *optarg
)
807 option_defchar
= atoi( optarg
);
810 output_name
= xstrdup( optarg
);
816 option_dpi
= atoi( optarg
);
825 fprintf( stderr
, "%s: %s\n\n", argv0
, optarg
);
832 int main(int argc
, char **argv
)
835 const int typeinfo_size
= 4 * sizeof(WORD
);
836 const int nameinfo_size
= 6 * sizeof(WORD
);
837 int resource_table_len
, non_resident_name_len
, resident_name_len
;
838 unsigned short resource_table_off
, resident_name_off
, module_ref_off
, non_resident_name_off
, fontdir_off
, font_off
;
839 char resident_name
[200];
841 char non_resident_name
[200];
842 unsigned short first_res
= 0x0050, res
;
843 struct fontinfo
**info
;
844 const char *input_file
;
845 struct strarray args
;
848 args
= parse_options( argc
, argv
, "d:ho:qr:s", NULL
, 0, option_callback
);
855 input_file
= args
.str
[0];
857 if(FT_Init_FreeType(&ft_library
))
858 error("ft init failure\n");
860 FT_Version
.major
=FT_Version
.minor
=FT_Version
.patch
=-1;
861 FT_Library_Version(ft_library
,&FT_Version
.major
,&FT_Version
.minor
,&FT_Version
.patch
);
863 num_files
= args
.count
- 1;
864 if (option_fnt_mode
&& num_files
> 1)
865 error( "can only specify one font in .fnt mode\n" );
867 info
= xmalloc( num_files
* sizeof(*info
) );
868 for (i
= 0; i
< num_files
; i
++)
870 int ppem
, enc
, avg_width
;
873 if (sscanf( args
.str
[i
+ 1], "%d,%d,%d", &ppem
, &enc
, &avg_width
) != 3)
878 if (!(info
[i
] = fill_fontinfo( input_file
, ppem
, enc
, option_dpi
, option_defchar
, avg_width
)))
881 name
= get_face_name( info
[i
] );
882 fontdir_len
+= 0x74 + strlen(name
) + 1;
884 sprintf(non_resident_name
, "FONTRES 100,%d,%d : %s %d",
885 info
[i
]->hdr
.fi
.dfVertRes
, info
[i
]->hdr
.fi
.dfHorizRes
,
886 name
, info
[i
]->hdr
.fi
.dfPoints
);
887 strcpy(resident_name
, name
);
889 sprintf(non_resident_name
+ strlen(non_resident_name
), ",%d", info
[i
]->hdr
.fi
.dfPoints
);
893 if (option_dpi
<= 108)
894 strcat(non_resident_name
, " (VGA res)");
896 strcat(non_resident_name
, " (8514 res)");
897 non_resident_name_len
= strlen(non_resident_name
) + 4;
899 /* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
900 resource_table_len
= sizeof(WORD
) /* align */ + sizeof("FONTDIR") +
901 typeinfo_size
+ nameinfo_size
+
902 typeinfo_size
+ nameinfo_size
* num_files
+
904 resource_table_off
= sizeof(IMAGE_OS2_HEADER
);
905 resident_name_off
= resource_table_off
+ resource_table_len
;
906 resident_name_len
= strlen(resident_name
) + 4;
907 module_ref_off
= resident_name_off
+ resident_name_len
;
908 non_resident_name_off
= sizeof(MZ_hdr
) + module_ref_off
+ sizeof(WORD
) /* align */;
910 fontdir_off
= (non_resident_name_off
+ non_resident_name_len
+ 15) & ~0xf;
911 font_off
= (fontdir_off
+ fontdir_len
+ 15) & ~0x0f;
914 init_signals( exit_on_signal
);
916 if (!output_name
) /* build a default output name */
917 output_name
= strmake( "%s%s", get_basename_noext( input_file
),
918 option_fnt_mode
? ".fnt" : ".fon" );
920 init_output_buffer();
927 put_data(MZ_hdr
, sizeof(MZ_hdr
));
930 put_word( 0x454e ); /* ne_magic */
931 put_byte( 5 ); /* ne_ver */
932 put_byte( 1 ); /* ne_rev */
933 put_word( module_ref_off
); /* ne_enttab */
934 put_word( 0 ); /* ne_cbenttab */
935 put_dword( 0 ); /* ne_crc */
936 put_word( 0x8300 ); /* ne_flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI */
937 put_word( 0 ); /* ne_autodata */
938 put_word( 0 ); /* ne_heap */
939 put_word( 0 ); /* ne_stack */
940 put_dword( 0 ); /* ne_csip */
941 put_dword( 0 ); /* ne_sssp */
942 put_word( 0 ); /* ne_cseg */
943 put_word( 0 ); /* ne_cmod */
944 put_word( non_resident_name_len
); /* ne_cbnrestab */
945 put_word( sizeof(IMAGE_OS2_HEADER
) ); /* ne_segtab */
946 put_word( sizeof(IMAGE_OS2_HEADER
) ); /* ne_rsrctab */
947 put_word( resident_name_off
); /* ne_restab */
948 put_word( module_ref_off
); /* ne_modtab */
949 put_word( module_ref_off
); /* ne_imptab */
950 put_dword( non_resident_name_off
); /* ne_nrestab */
951 put_word( 0 ); /* ne_cmovent */
952 put_word( 4 ); /* ne_align */
953 put_word( 0 ); /* ne_cres */
954 put_byte( 2 ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */
955 put_byte( 0 ); /* ne_flagsothers */
956 put_word( 0 ); /* ne_pretthunks */
957 put_word( 0 ); /* ne_psegrefbytes */
958 put_word( 0 ); /* ne_swaparea */
959 put_word( 0x400 ); /* ne_expver */
961 put_word( 4 ); /* align */
965 put_word( 0x8007 ); /* type_id = NE_RSCTYPE_FONTDIR */
966 put_word( 1 ); /* count */
967 put_dword( 0 ); /* resloader */
969 put_word( fontdir_off
>> 4 ); /* offset */
970 put_word( (fontdir_len
+ 15) >> 4 ); /* length */
971 put_word( 0x0050 ); /* flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD */
972 put_word( resident_name_off
- sizeof("FONTDIR") - sizeof(IMAGE_OS2_HEADER
) ); /* id */
973 put_word( 0 ); /* handle */
974 put_word( 0 ); /* usage */
976 put_word( 0x8008 ); /* type_id = NE_RSCTYPE_FONT */
977 put_word( num_files
); /* count */
978 put_dword( 0 ); /* resloader */
980 for(res
= first_res
| 0x8000, i
= 0; i
< num_files
; i
++, res
++) {
981 int len
= (info
[i
]->hdr
.dfSize
+ 15) & ~0xf;
983 put_word( font_off
>> 4 ); /* offset */
984 put_word( len
>> 4 ); /* length */
985 put_word( 0x1030 ); /* flags = NE_SEGFLAGS_MOVEABLE|NE_SEGFLAGS_SHAREABLE|NE_SEGFLAGS_DISCARDABLE */
986 put_word( res
); /* id */
987 put_word( 0 ); /* handle */
988 put_word( 0 ); /* usage */
992 put_word( 0 ); /* type_id */
993 put_word( 0 ); /* count */
994 put_dword( 0 ); /* resloader */
996 put_byte( strlen("FONTDIR") );
997 put_data( "FONTDIR", strlen("FONTDIR") );
998 put_byte( strlen(resident_name
) );
999 put_data( resident_name
, strlen(resident_name
) );
1005 put_byte( strlen(non_resident_name
) );
1006 put_data( non_resident_name
, strlen(non_resident_name
) );
1009 /* empty ne_modtab and ne_imptab */
1014 /* FONTDIR resource */
1015 put_word( num_files
);
1017 for (i
= 0; i
< num_files
; i
++)
1019 put_word( first_res
+ i
);
1020 put_fontdir( info
[i
] );
1024 for(i
= 0; i
< num_files
; i
++)
1026 put_font( info
[i
] );
1031 flush_output_buffer( output_name
);
1036 #else /* HAVE_FREETYPE */
1038 int main(int argc
, char **argv
)
1040 fprintf( stderr
, "%s needs to be built with FreeType support\n", argv
[0] );
1044 #endif /* HAVE_FREETYPE */