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
32 #ifdef HAVE_FT2BUILD_H
35 #include FT_FREETYPE_H
36 #include FT_SFNT_NAMES_H
37 #include FT_TRUETYPE_TABLES_H
38 #include FT_TRUETYPE_TAGS_H
55 INT16 dfInternalLeading
;
56 INT16 dfExternalLeading
;
64 BYTE dfPitchAndFamily
;
110 #define NE_FFLAGS_SINGLEDATA 0x0001
111 #define NE_FFLAGS_MULTIPLEDATA 0x0002
112 #define NE_FFLAGS_WIN32 0x0010
113 #define NE_FFLAGS_FRAMEBUF 0x0100
114 #define NE_FFLAGS_CONSOLE 0x0200
115 #define NE_FFLAGS_GUI 0x0300
116 #define NE_FFLAGS_SELFLOAD 0x0800
117 #define NE_FFLAGS_LINKERROR 0x2000
118 #define NE_FFLAGS_CALLWEP 0x4000
119 #define NE_FFLAGS_LIBMODULE 0x8000
121 #define NE_OSFLAGS_WINDOWS 0x02
123 #define NE_RSCTYPE_FONTDIR 0x8007
124 #define NE_RSCTYPE_FONT 0x8008
125 #define NE_RSCTYPE_SCALABLE_FONTPATH 0x80cc
127 #define NE_SEGFLAGS_DATA 0x0001
128 #define NE_SEGFLAGS_ALLOCATED 0x0002
129 #define NE_SEGFLAGS_LOADED 0x0004
130 #define NE_SEGFLAGS_ITERATED 0x0008
131 #define NE_SEGFLAGS_MOVEABLE 0x0010
132 #define NE_SEGFLAGS_SHAREABLE 0x0020
133 #define NE_SEGFLAGS_PRELOAD 0x0040
134 #define NE_SEGFLAGS_EXECUTEONLY 0x0080
135 #define NE_SEGFLAGS_READONLY 0x0080
136 #define NE_SEGFLAGS_RELOC_DATA 0x0100
137 #define NE_SEGFLAGS_SELFLOAD 0x0800
138 #define NE_SEGFLAGS_DISCARDABLE 0x1000
139 #define NE_SEGFLAGS_32BIT 0x2000
155 CHAR caretSlopeNumerator
;
156 CHAR caretSlopeDenominator
;
167 ULONG indexSubTableArrayOffset
;
168 ULONG indexTableSize
;
169 ULONG numberOfIndexSubTables
;
171 sbitLineMetrics_t hori
;
172 sbitLineMetrics_t vert
;
173 USHORT startGlyphIndex
;
174 USHORT endGlyphIndex
;
187 static FT_Version_t FT_Version
;
191 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
192 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
193 GET_BE_WORD(&((WORD *)(ptr))[0]) ))
194 #ifdef WORDS_BIGENDIAN
195 static WORD
byteswap_word(WORD x
)
197 return ( ( (x
& 0xff) << 8) |
198 ( (x
& 0xff00) >> 8) );
200 static DWORD
byteswap_dword(DWORD x
)
202 return ( ( (x
& 0xff) << 24) |
203 ( (x
& 0xff00) << 8) |
204 ( (x
& 0xff0000) >> 8) |
205 ( (x
& 0xff000000) >> 24) );
207 # define PUT_LE_WORD(x) byteswap_word(x)
208 # define PUT_LE_DWORD(x) byteswap_dword(x)
210 # define PUT_LE_WORD(x) (x)
211 # define PUT_LE_DWORD(x) (x)
217 CHAR_TABLE_ENTRY dfCharTable
[258];
221 static const BYTE MZ_hdr
[] =
223 'M', 'Z', 0x0d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
224 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
227 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
228 'i', 's', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
229 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
230 'm', 'o', 'd', 'e', 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
233 static const WCHAR encoding_1250
[128] =
235 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
236 0x0088, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
237 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
238 0x0098, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
239 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
240 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
241 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
242 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
243 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
244 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
245 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
246 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
247 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
248 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
249 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
250 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
253 static const WCHAR encoding_1251
[128] =
255 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
256 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
257 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
258 0x0098, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
259 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
260 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
261 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
262 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
263 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
264 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
265 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
266 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
267 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
268 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
269 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
270 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f
273 static const WCHAR encoding_1252
[128] =
275 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
276 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
277 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
278 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,
279 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
280 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
281 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
282 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
283 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
284 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
285 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
286 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
287 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
288 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
289 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
290 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
293 static const WCHAR encoding_1253
[128] =
295 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
296 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
297 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
298 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
299 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
300 0x00a8, 0x00a9, 0xf8f9, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
301 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7,
302 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
303 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
304 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
305 0x03a0, 0x03a1, 0xf8fa, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
306 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
307 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
308 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
309 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
310 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xf8fb
313 static const WCHAR encoding_1254
[128] =
315 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
316 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
317 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
318 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
319 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
320 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
321 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
322 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
323 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
324 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
325 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
326 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
327 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
328 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
329 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
330 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff
333 static const WCHAR encoding_1255
[128] =
335 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
336 0x02c6, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
337 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
338 0x02dc, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
339 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7,
340 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
341 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
342 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
343 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
344 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
345 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3,
346 0x05f4, 0xf88d, 0xf88e, 0xf88f, 0xf890, 0xf891, 0xf892, 0xf893,
347 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
348 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
349 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
350 0x05e8, 0x05e9, 0x05ea, 0xf894, 0xf895, 0x200e, 0x200f, 0xf896
353 static const WCHAR encoding_1256
[128] =
355 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
356 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
357 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
358 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
359 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
360 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
361 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
362 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
363 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
364 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
365 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7,
366 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
367 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7,
368 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
369 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7,
370 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2
373 static const WCHAR encoding_1257
[128] =
375 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
376 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x00a8, 0x02c7, 0x00b8,
377 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
378 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x00af, 0x02db, 0x009f,
379 0x00a0, 0xf8fc, 0x00a2, 0x00a3, 0x00a4, 0xf8fd, 0x00a6, 0x00a7,
380 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
381 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
382 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
383 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112,
384 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
385 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7,
386 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
387 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113,
388 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
389 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7,
390 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9
393 static const WCHAR encoding_874
[128] =
395 0x20ac, 0x0081, 0x0082, 0x0083, 0x0084, 0x2026, 0x0086, 0x0087,
396 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
397 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
398 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
399 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
400 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
401 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
402 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
403 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
404 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
405 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
406 0x0e38, 0x0e39, 0x0e3a, 0xf8c1, 0xf8c2, 0xf8c3, 0xf8c4, 0x0e3f,
407 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
408 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
409 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
410 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf8c5, 0xf8c6, 0xf8c7, 0xf8c8
413 static const struct { int codepage
; const WCHAR
*table
; } encodings
[] =
415 { 874, encoding_874
},
416 { 1250, encoding_1250
},
417 { 1251, encoding_1251
},
418 { 1252, encoding_1252
},
419 { 1253, encoding_1253
},
420 { 1254, encoding_1254
},
421 { 1255, encoding_1255
},
422 { 1256, encoding_1256
},
423 { 1257, encoding_1257
},
424 { 0, encoding_1252
}, /* default encoding */
427 static char *option_output
;
428 static int option_defchar
= ' ';
429 static int option_dpi
= 96;
430 static int option_fnt_mode
= 0;
431 static int option_quiet
= 0;
433 static const char *output_name
;
435 static FT_Library ft_library
;
437 static const char *argv0
;
439 static void usage(void)
441 fprintf(stderr
, "%s [options] input.ttf ppem,enc,avg_width ...\n", argv0
);
442 fprintf(stderr
, "Options:\n");
443 fprintf(stderr
, " -h Display help\n" );
444 fprintf(stderr
, " -d char Set the font default char\n" );
445 fprintf(stderr
, " -o file Set output file name\n" );
446 fprintf(stderr
, " -q Quiet mode\n" );
447 fprintf(stderr
, " -r dpi Set resolution in DPI (default: 96)\n" );
448 fprintf(stderr
, " -s Single .fnt file mode\n" );
451 /* atexit handler to cleanup files */
452 static void cleanup(void)
454 if (output_name
) unlink( output_name
);
457 static void exit_on_signal( int sig
)
459 exit(1); /* this will call the atexit functions */
462 static void error(const char *s
, ...) __attribute__((format (printf
, 1, 2)));
464 static void error(const char *s
, ...)
468 fprintf(stderr
, "Error: ");
469 vfprintf(stderr
, s
, ap
);
474 static const char *get_face_name( const struct fontinfo
*info
)
476 return (const char *)info
->data
+ info
->hdr
.fi
.dfFace
- info
->hdr
.fi
.dfBitsOffset
;
479 static int lookup_charset(int enc
)
481 /* FIXME: make winelib app and use TranslateCharsetInfo */
486 return RUSSIAN_CHARSET
;
490 return GREEK_CHARSET
;
492 return TURKISH_CHARSET
;
494 return HEBREW_CHARSET
;
496 return ARABIC_CHARSET
;
498 return BALTIC_CHARSET
;
500 return VIETNAMESE_CHARSET
;
520 return SHIFTJIS_CHARSET
;
522 return GB2312_CHARSET
;
524 return HANGUL_CHARSET
;
526 return CHINESEBIG5_CHARSET
;
528 fprintf(stderr
, "Unknown encoding %d - using OEM_CHARSET\n", enc
);
533 static void get_char_table(int enc
, WCHAR tableW
[0x100])
537 for (i
= 0; i
< 128; i
++) tableW
[i
] = i
;
539 for (i
= 0; encodings
[i
].codepage
; i
++) if (encodings
[i
].codepage
== enc
) break;
540 memcpy( tableW
+ 128, encodings
[i
].table
, 128 * sizeof(WCHAR
) );
542 /* Korean has the Won sign in place of '\\' */
543 if (enc
== 949) tableW
['\\'] = 0x20a9;
546 static struct fontinfo
*fill_fontinfo( const char *face_name
, int ppem
, int enc
, int dpi
,
547 unsigned char def_char
, int avg_width
)
550 int ascent
= 0, il
, el
, width_bytes
= 0, space_size
, max_width
= 0;
551 BYTE left_byte
, right_byte
, byte
;
553 int i
, x
, y
, x_off
, x_end
, first_char
;
556 FT_SfntName sfntname
;
560 bitmapSizeTable_t
*size_table
;
562 struct fontinfo
*info
;
566 if (FT_New_Face(ft_library
, face_name
, 0, &face
)) error( "Cannot open face %s\n", face_name
);
567 if (FT_Set_Pixel_Sizes(face
, ppem
, ppem
)) error( "cannot set face size to %u\n", ppem
);
569 assert( face
->size
->metrics
.y_ppem
== ppem
);
571 get_char_table( enc
, table
);
574 if (FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, NULL
, &needed
))
575 fprintf(stderr
,"Can't find EBLC table\n");
578 eblc
= xmalloc(needed
);
579 FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, (FT_Byte
*)eblc
, &needed
);
581 num_sizes
= GET_BE_DWORD(&eblc
->numSizes
);
583 size_table
= (bitmapSizeTable_t
*)(eblc
+ 1);
584 for(i
= 0; i
< num_sizes
; i
++)
586 if( (signed char)size_table
->hori
.ascender
- (signed char)size_table
->hori
.descender
== ppem
)
588 ascent
= size_table
->hori
.ascender
;
597 /* Versions of fontforge prior to early 2006 have incorrect
598 ascender values in the eblc table, so we won't find the
599 correct bitmapSizeTable. In this case use the height of
600 the Aring glyph instead. */
603 if(FT_Load_Char(face
, 0xc5, FT_LOAD_DEFAULT
))
604 error("Can't find Aring\n");
605 ascent
= face
->glyph
->metrics
.horiBearingY
>> 6;
608 start
= sizeof(FNT_HEADER
);
610 if(FT_Load_Char(face
, 'M', FT_LOAD_DEFAULT
))
611 error("Can't find M\n");
612 il
= ascent
- (face
->glyph
->metrics
.height
>> 6);
614 /* Hack: Courier has no internal leading, nor do any Chinese or Japanese fonts */
615 if(!strcmp(face
->family_name
, "Courier") || enc
== 936 || enc
== 950 || enc
== 932)
617 else if (!strcmp(face
->family_name
, "Fixedsys"))
620 /* Japanese System font has an external leading */
621 if (!strcmp(face
->family_name
, "System") && enc
== 932)
626 first_char
= FT_Get_First_Char(face
, &gi
);
627 if(first_char
< 0x20) /* Ignore glyphs below 0x20 */
628 first_char
= 0x20; /* FT_Get_Next_Char for some reason returns too high
629 number in this case */
631 info
= calloc( 1, sizeof(*info
) );
633 info
->hdr
.fi
.dfFirstChar
= first_char
;
634 info
->hdr
.fi
.dfLastChar
= 0xff;
635 start
+= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
+ 3 ) * sizeof(*info
->dfCharTable
);
637 num_names
= FT_Get_Sfnt_Name_Count(face
);
638 for(i
= 0; i
<num_names
; i
++) {
639 FT_Get_Sfnt_Name(face
, i
, &sfntname
);
640 if(sfntname
.platform_id
== 1 && sfntname
.encoding_id
== 0 &&
641 sfntname
.language_id
== 0 && sfntname
.name_id
== 0) {
642 size_t len
= min( sfntname
.string_len
, sizeof(info
->hdr
.dfCopyright
)-1 );
643 memcpy(info
->hdr
.dfCopyright
, sfntname
.string
, len
);
644 info
->hdr
.dfCopyright
[len
] = 0;
648 os2
= FT_Get_Sfnt_Table(face
, ft_sfnt_os2
);
649 for(i
= first_char
; i
< 0x100; i
++) {
650 gi
= FT_Get_Char_Index(face
, table
[i
]);
651 if(gi
== 0 && !option_quiet
)
652 fprintf(stderr
, "warning: %s %u: missing glyph for char %04x\n",
653 face
->family_name
, ppem
, table
[i
]);
654 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
655 fprintf(stderr
, "error loading char %d - bad news!\n", i
);
658 info
->dfCharTable
[i
].width
= face
->glyph
->metrics
.horiAdvance
>> 6;
659 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
660 width_bytes
+= ((face
->glyph
->metrics
.horiAdvance
>> 6) + 7) >> 3;
661 if(max_width
< (face
->glyph
->metrics
.horiAdvance
>> 6))
662 max_width
= face
->glyph
->metrics
.horiAdvance
>> 6;
665 space_size
= (ppem
+ 3) / 4;
666 info
->dfCharTable
[i
].width
= space_size
;
667 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
668 width_bytes
+= (space_size
+ 7) >> 3;
670 info
->dfCharTable
[++i
].width
= 0;
671 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
673 info
->hdr
.fi
.dfType
= 0;
674 info
->hdr
.fi
.dfPoints
= ((ppem
- il
- el
) * 72 + dpi
/2) / dpi
;
675 info
->hdr
.fi
.dfVertRes
= dpi
;
676 info
->hdr
.fi
.dfHorizRes
= dpi
;
677 info
->hdr
.fi
.dfAscent
= ascent
;
678 info
->hdr
.fi
.dfInternalLeading
= il
;
679 info
->hdr
.fi
.dfExternalLeading
= el
;
680 info
->hdr
.fi
.dfItalic
= (face
->style_flags
& FT_STYLE_FLAG_ITALIC
) ? 1 : 0;
681 info
->hdr
.fi
.dfUnderline
= 0;
682 info
->hdr
.fi
.dfStrikeOut
= 0;
683 info
->hdr
.fi
.dfWeight
= os2
->usWeightClass
;
684 info
->hdr
.fi
.dfCharSet
= lookup_charset(enc
);
685 info
->hdr
.fi
.dfPixWidth
= (face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) ? avg_width
: 0;
686 info
->hdr
.fi
.dfPixHeight
= ppem
;
687 info
->hdr
.fi
.dfPitchAndFamily
= FT_IS_FIXED_WIDTH(face
) ? 0 : TMPF_FIXED_PITCH
;
688 switch(os2
->panose
[PAN_FAMILYTYPE_INDEX
]) {
689 case PAN_FAMILY_SCRIPT
:
690 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SCRIPT
;
692 case PAN_FAMILY_DECORATIVE
:
693 case PAN_FAMILY_PICTORIAL
:
694 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DECORATIVE
;
696 case PAN_FAMILY_TEXT_DISPLAY
:
697 if(info
->hdr
.fi
.dfPitchAndFamily
== 0) /* fixed */
698 info
->hdr
.fi
.dfPitchAndFamily
= FF_MODERN
;
700 switch(os2
->panose
[PAN_SERIFSTYLE_INDEX
]) {
701 case PAN_SERIF_NORMAL_SANS
:
702 case PAN_SERIF_OBTUSE_SANS
:
703 case PAN_SERIF_PERP_SANS
:
704 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SWISS
;
707 info
->hdr
.fi
.dfPitchAndFamily
|= FF_ROMAN
;
712 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DONTCARE
;
715 info
->hdr
.fi
.dfAvgWidth
= avg_width
;
716 info
->hdr
.fi
.dfMaxWidth
= (enc
== 932) ? avg_width
* 2 : max_width
;
717 info
->hdr
.fi
.dfDefaultChar
= def_char
- info
->hdr
.fi
.dfFirstChar
;
718 info
->hdr
.fi
.dfBreakChar
= ' ' - info
->hdr
.fi
.dfFirstChar
;
719 info
->hdr
.fi
.dfWidthBytes
= (width_bytes
+ 1) & ~1;
721 info
->hdr
.fi
.dfFace
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
;
722 info
->hdr
.fi
.dfBitsOffset
= start
;
723 info
->hdr
.fi
.dfFlags
= 0x10; /* DFF_1COLOR */
724 info
->hdr
.fi
.dfFlags
|= FT_IS_FIXED_WIDTH(face
) ? 1 : 2; /* DFF_FIXED : DFF_PROPORTIONAL */
726 info
->hdr
.dfVersion
= 0x300;
727 info
->hdr
.dfSize
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
+ strlen(face
->family_name
) + 1;
729 info
->data
= calloc( info
->hdr
.dfSize
- start
, 1 );
732 for(i
= first_char
; i
< 0x100; i
++) {
733 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
736 assert(info
->dfCharTable
[i
].width
== face
->glyph
->metrics
.horiAdvance
>> 6);
738 for(x
= 0; x
< ((info
->dfCharTable
[i
].width
+ 7) / 8); x
++) {
739 for(y
= 0; y
< ppem
; y
++) {
740 if(y
< ascent
- face
->glyph
->bitmap_top
||
741 y
>= (int)face
->glyph
->bitmap
.rows
+ ascent
- face
->glyph
->bitmap_top
) {
742 info
->data
[data_pos
++] = 0;
745 x_off
= face
->glyph
->bitmap_left
/ 8;
746 x_end
= (face
->glyph
->bitmap_left
+ face
->glyph
->bitmap
.width
- 1) / 8;
747 if(x
< x_off
|| x
> x_end
) {
748 info
->data
[data_pos
++] = 0;
754 left_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
- 1];
756 /* On the last non-trivial output byte (x == x_end) have we got one or two input bytes */
757 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)))
760 right_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
];
762 byte
= (left_byte
<< (8 - (face
->glyph
->bitmap_left
& 7))) & 0xff;
763 byte
|= ((right_byte
>> (face
->glyph
->bitmap_left
& 7)) & 0xff);
764 info
->data
[data_pos
++] = byte
;
768 data_pos
+= ((space_size
+ 7) / 8) * ppem
;
769 if (width_bytes
& 1) data_pos
+= ppem
;
771 memcpy( info
->data
+ data_pos
, face
->family_name
, strlen( face
->family_name
));
772 data_pos
+= strlen( face
->family_name
) + 1;
773 assert( start
+ data_pos
== info
->hdr
.dfSize
);
775 FT_Done_Face( face
);
779 static void adjust_fontinfo( FONTINFO16
* fi
)
781 fi
->dfType
= PUT_LE_WORD(fi
->dfType
);
782 fi
->dfPoints
= PUT_LE_WORD(fi
->dfPoints
);
783 fi
->dfVertRes
= PUT_LE_WORD(fi
->dfVertRes
);
784 fi
->dfHorizRes
= PUT_LE_WORD(fi
->dfHorizRes
);
785 fi
->dfAscent
= PUT_LE_WORD(fi
->dfAscent
);
786 fi
->dfInternalLeading
= PUT_LE_WORD(fi
->dfInternalLeading
);
787 fi
->dfExternalLeading
= PUT_LE_WORD(fi
->dfExternalLeading
);
788 fi
->dfWeight
= PUT_LE_WORD(fi
->dfWeight
);
789 fi
->dfPixWidth
= PUT_LE_WORD(fi
->dfPixWidth
);
790 fi
->dfPixHeight
= PUT_LE_WORD(fi
->dfPixHeight
);
791 fi
->dfAvgWidth
= PUT_LE_WORD(fi
->dfAvgWidth
);
792 fi
->dfMaxWidth
= PUT_LE_WORD(fi
->dfMaxWidth
);
793 fi
->dfWidthBytes
= PUT_LE_WORD(fi
->dfWidthBytes
);
794 fi
->dfAspace
= PUT_LE_WORD(fi
->dfAspace
);
795 fi
->dfBspace
= PUT_LE_WORD(fi
->dfBspace
);
796 fi
->dfCspace
= PUT_LE_WORD(fi
->dfCspace
);
797 fi
->dfDevice
= PUT_LE_DWORD(fi
->dfDevice
);
798 fi
->dfFace
= PUT_LE_DWORD(fi
->dfFace
);
799 fi
->dfBitsPointer
= PUT_LE_DWORD(fi
->dfBitsPointer
);
800 fi
->dfBitsOffset
= PUT_LE_DWORD(fi
->dfBitsOffset
);
801 fi
->dfFlags
= PUT_LE_DWORD(fi
->dfFlags
);
802 fi
->dfColorPointer
= PUT_LE_DWORD(fi
->dfColorPointer
);
805 static void write_fontinfo( const struct fontinfo
*info
, FILE *fp
)
809 CHAR_TABLE_ENTRY tmp_chartable
[258];
810 memcpy(&tmp_hdr
, &info
->hdr
, sizeof(info
->hdr
));
811 tmp_hdr
.dfVersion
= PUT_LE_WORD(tmp_hdr
.dfVersion
);
812 tmp_hdr
.dfSize
= PUT_LE_DWORD(tmp_hdr
.dfSize
);
813 adjust_fontinfo(&(tmp_hdr
.fi
));
814 fwrite( &tmp_hdr
, sizeof(info
->hdr
), 1, fp
);
815 num_chars
= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
) + 3;
817 memcpy(&tmp_chartable
, info
->dfCharTable
+ info
->hdr
.fi
.dfFirstChar
, num_chars
* sizeof(CHAR_TABLE_ENTRY
));
818 for (i
=0; i
< num_chars
; ++i
) {
819 tmp_chartable
[i
].width
= PUT_LE_WORD(tmp_chartable
[i
].width
);
820 tmp_chartable
[i
].offset
= PUT_LE_DWORD(tmp_chartable
[i
].offset
);
822 fwrite( tmp_chartable
, sizeof(CHAR_TABLE_ENTRY
), num_chars
, fp
);
823 fwrite( info
->data
, info
->hdr
.dfSize
- info
->hdr
.fi
.dfBitsOffset
, 1, fp
);
826 static void option_callback( int optc
, char *optarg
)
831 option_defchar
= atoi( optarg
);
834 option_output
= xstrdup( optarg
);
840 option_dpi
= atoi( optarg
);
849 fprintf( stderr
, "%s: %s\n\n", argv0
, optarg
);
856 int main(int argc
, char **argv
)
860 short align
, num_files
;
861 int resource_table_len
, non_resident_name_len
, resident_name_len
;
862 unsigned short resource_table_off
, resident_name_off
, module_ref_off
, non_resident_name_off
, fontdir_off
, font_off
;
863 char resident_name
[200];
865 char non_resident_name
[200];
866 unsigned short first_res
= 0x0050, pad
, res
;
867 IMAGE_OS2_HEADER NE_hdr
;
870 struct fontinfo
**info
;
871 const char *input_file
;
872 struct strarray args
;
876 args
= parse_options( argc
, argv
, "d:ho:qr:s", NULL
, 0, option_callback
);
883 input_file
= args
.str
[0];
885 if(FT_Init_FreeType(&ft_library
))
886 error("ft init failure\n");
888 FT_Version
.major
=FT_Version
.minor
=FT_Version
.patch
=-1;
889 FT_Library_Version(ft_library
,&FT_Version
.major
,&FT_Version
.minor
,&FT_Version
.patch
);
891 num_files
= args
.count
- 1;
892 if (option_fnt_mode
&& num_files
> 1)
893 error( "can only specify one font in .fnt mode\n" );
895 info
= xmalloc( num_files
* sizeof(*info
) );
896 for (i
= 0; i
< num_files
; i
++)
898 int ppem
, enc
, avg_width
;
901 if (sscanf( args
.str
[i
+ 1], "%d,%d,%d", &ppem
, &enc
, &avg_width
) != 3)
906 if (!(info
[i
] = fill_fontinfo( input_file
, ppem
, enc
, option_dpi
, option_defchar
, avg_width
)))
909 name
= get_face_name( info
[i
] );
910 fontdir_len
+= 0x74 + strlen(name
) + 1;
912 sprintf(non_resident_name
, "FONTRES 100,%d,%d : %s %d",
913 info
[i
]->hdr
.fi
.dfVertRes
, info
[i
]->hdr
.fi
.dfHorizRes
,
914 name
, info
[i
]->hdr
.fi
.dfPoints
);
915 strcpy(resident_name
, name
);
917 sprintf(non_resident_name
+ strlen(non_resident_name
), ",%d", info
[i
]->hdr
.fi
.dfPoints
);
921 if (option_dpi
<= 108)
922 strcat(non_resident_name
, " (VGA res)");
924 strcat(non_resident_name
, " (8514 res)");
925 non_resident_name_len
= strlen(non_resident_name
) + 4;
927 /* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
928 resource_table_len
= sizeof(align
) + sizeof("FONTDIR") +
929 sizeof(NE_TYPEINFO
) + sizeof(NE_NAMEINFO
) +
930 sizeof(NE_TYPEINFO
) + sizeof(NE_NAMEINFO
) * num_files
+
932 resource_table_off
= sizeof(NE_hdr
);
933 resident_name_off
= resource_table_off
+ resource_table_len
;
934 resident_name_len
= strlen(resident_name
) + 4;
935 module_ref_off
= resident_name_off
+ resident_name_len
;
936 non_resident_name_off
= sizeof(MZ_hdr
) + module_ref_off
+ sizeof(align
);
938 memset(&NE_hdr
, 0, sizeof(NE_hdr
));
939 NE_hdr
.ne_magic
= PUT_LE_WORD(0x454e);
942 NE_hdr
.ne_flags
= PUT_LE_WORD(NE_FFLAGS_LIBMODULE
| NE_FFLAGS_GUI
);
943 NE_hdr
.ne_cbnrestab
= PUT_LE_WORD(non_resident_name_len
);
944 NE_hdr
.ne_segtab
= PUT_LE_WORD(sizeof(NE_hdr
));
945 NE_hdr
.ne_rsrctab
= PUT_LE_WORD(sizeof(NE_hdr
));
946 NE_hdr
.ne_restab
= PUT_LE_WORD(resident_name_off
);
947 NE_hdr
.ne_modtab
= PUT_LE_WORD(module_ref_off
);
948 NE_hdr
.ne_imptab
= PUT_LE_WORD(module_ref_off
);
949 NE_hdr
.ne_enttab
= NE_hdr
.ne_modtab
;
950 NE_hdr
.ne_nrestab
= PUT_LE_DWORD(non_resident_name_off
);
951 NE_hdr
.ne_align
= PUT_LE_WORD(4);
952 NE_hdr
.ne_exetyp
= NE_OSFLAGS_WINDOWS
;
953 NE_hdr
.ne_expver
= PUT_LE_WORD(0x400);
955 fontdir_off
= (non_resident_name_off
+ non_resident_name_len
+ 15) & ~0xf;
956 font_off
= (fontdir_off
+ fontdir_len
+ 15) & ~0x0f;
959 signal( SIGTERM
, exit_on_signal
);
960 signal( SIGINT
, exit_on_signal
);
962 signal( SIGHUP
, exit_on_signal
);
965 if (!option_output
) /* build a default output name */
966 option_output
= strmake( "%s%s", get_basename_noext( input_file
),
967 option_fnt_mode
? ".fnt" : ".fon" );
969 if (!(ofp
= fopen(option_output
, "wb")))
971 perror( option_output
);
974 output_name
= option_output
;
977 write_fontinfo( info
[0], ofp
);
981 fwrite(MZ_hdr
, sizeof(MZ_hdr
), 1, ofp
);
982 fwrite(&NE_hdr
, sizeof(NE_hdr
), 1, ofp
);
984 align
= PUT_LE_WORD(4);
985 fwrite(&align
, sizeof(align
), 1, ofp
);
987 rc_type
.type_id
= PUT_LE_WORD(NE_RSCTYPE_FONTDIR
);
988 rc_type
.count
= PUT_LE_WORD(1);
989 rc_type
.resloader
= 0;
990 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
992 rc_name
.offset
= PUT_LE_WORD(fontdir_off
>> 4);
993 rc_name
.length
= PUT_LE_WORD((fontdir_len
+ 15) >> 4);
994 rc_name
.flags
= PUT_LE_WORD(NE_SEGFLAGS_MOVEABLE
| NE_SEGFLAGS_PRELOAD
);
995 rc_name
.id
= PUT_LE_WORD(resident_name_off
- sizeof("FONTDIR") - sizeof(NE_hdr
));
998 fwrite(&rc_name
, sizeof(rc_name
), 1, ofp
);
1000 rc_type
.type_id
= PUT_LE_WORD(NE_RSCTYPE_FONT
);
1001 rc_type
.count
= PUT_LE_WORD(num_files
);
1002 rc_type
.resloader
= 0;
1003 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
1005 for(res
= first_res
| 0x8000, i
= 0; i
< num_files
; i
++, res
++) {
1006 int len
= (info
[i
]->hdr
.dfSize
+ 15) & ~0xf;
1008 rc_name
.offset
= PUT_LE_WORD(font_off
>> 4);
1009 rc_name
.length
= PUT_LE_WORD(len
>> 4);
1010 rc_name
.flags
= PUT_LE_WORD(NE_SEGFLAGS_MOVEABLE
| NE_SEGFLAGS_SHAREABLE
| NE_SEGFLAGS_DISCARDABLE
);
1011 rc_name
.id
= PUT_LE_WORD(res
);
1014 fwrite(&rc_name
, sizeof(rc_name
), 1, ofp
);
1019 /* empty type info */
1020 memset(&rc_type
, 0, sizeof(rc_type
));
1021 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
1023 fputc(strlen("FONTDIR"), ofp
);
1024 fwrite("FONTDIR", strlen("FONTDIR"), 1, ofp
);
1025 fputc(strlen(resident_name
), ofp
);
1026 fwrite(resident_name
, strlen(resident_name
), 1, ofp
);
1028 fputc(0x00, ofp
); fputc(0x00, ofp
);
1030 fputc(0x00, ofp
); fputc(0x00, ofp
);
1032 fputc(strlen(non_resident_name
), ofp
);
1033 fwrite(non_resident_name
, strlen(non_resident_name
), 1, ofp
);
1034 fputc(0x00, ofp
); /* terminator */
1036 /* empty ne_modtab and ne_imptab */
1040 pad
= ftell(ofp
) & 0xf;
1043 for(i
= 0; i
< pad
; i
++)
1046 /* FONTDIR resource */
1047 tmp16
= PUT_LE_WORD(num_files
);
1048 fwrite(&tmp16
, sizeof(tmp16
), 1, ofp
);
1050 for(res
= first_res
, i
= 0; i
< num_files
; i
++, res
++) {
1053 const char *name
= get_face_name( info
[i
] );
1054 tmp16
= PUT_LE_WORD(res
);
1055 fwrite(&tmp16
, sizeof(tmp16
), 1, ofp
);
1056 sz
= FIELD_OFFSET(FNT_HEADER
,fi
.dfBitsOffset
);
1057 memcpy(&tmp_hdr
, &info
[i
]->hdr
, sz
);
1058 tmp_hdr
.dfVersion
= PUT_LE_WORD(tmp_hdr
.dfVersion
);
1059 tmp_hdr
.dfSize
= PUT_LE_DWORD(tmp_hdr
.dfSize
);
1060 adjust_fontinfo(&(tmp_hdr
.fi
));
1061 fwrite(&tmp_hdr
, FIELD_OFFSET(FNT_HEADER
,fi
.dfBitsOffset
), 1, ofp
);
1063 fwrite(name
, strlen(name
) + 1, 1, ofp
);
1066 pad
= ftell(ofp
) & 0xf;
1069 for(i
= 0; i
< pad
; i
++)
1072 for(res
= first_res
, i
= 0; i
< num_files
; i
++, res
++) {
1073 write_fontinfo( info
[i
], ofp
);
1074 pad
= info
[i
]->hdr
.dfSize
& 0xf;
1077 for(j
= 0; j
< pad
; j
++)
1086 #else /* HAVE_FREETYPE */
1088 int main(int argc
, char **argv
)
1090 fprintf( stderr
, "%s needs to be built with FreeType support\n", argv
[0] );
1094 #endif /* HAVE_FREETYPE */