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
22 #include "wine/port.h"
36 #ifdef HAVE_FT2BUILD_H
39 #include FT_FREETYPE_H
40 #include FT_SFNT_NAMES_H
41 #include FT_TRUETYPE_TABLES_H
42 #include FT_TRUETYPE_TAGS_H
58 INT16 dfInternalLeading
;
59 INT16 dfExternalLeading
;
67 BYTE dfPitchAndFamily
;
113 #define NE_FFLAGS_SINGLEDATA 0x0001
114 #define NE_FFLAGS_MULTIPLEDATA 0x0002
115 #define NE_FFLAGS_WIN32 0x0010
116 #define NE_FFLAGS_FRAMEBUF 0x0100
117 #define NE_FFLAGS_CONSOLE 0x0200
118 #define NE_FFLAGS_GUI 0x0300
119 #define NE_FFLAGS_SELFLOAD 0x0800
120 #define NE_FFLAGS_LINKERROR 0x2000
121 #define NE_FFLAGS_CALLWEP 0x4000
122 #define NE_FFLAGS_LIBMODULE 0x8000
124 #define NE_OSFLAGS_WINDOWS 0x02
126 #define NE_RSCTYPE_FONTDIR 0x8007
127 #define NE_RSCTYPE_FONT 0x8008
128 #define NE_RSCTYPE_SCALABLE_FONTPATH 0x80cc
130 #define NE_SEGFLAGS_DATA 0x0001
131 #define NE_SEGFLAGS_ALLOCATED 0x0002
132 #define NE_SEGFLAGS_LOADED 0x0004
133 #define NE_SEGFLAGS_ITERATED 0x0008
134 #define NE_SEGFLAGS_MOVEABLE 0x0010
135 #define NE_SEGFLAGS_SHAREABLE 0x0020
136 #define NE_SEGFLAGS_PRELOAD 0x0040
137 #define NE_SEGFLAGS_EXECUTEONLY 0x0080
138 #define NE_SEGFLAGS_READONLY 0x0080
139 #define NE_SEGFLAGS_RELOC_DATA 0x0100
140 #define NE_SEGFLAGS_SELFLOAD 0x0800
141 #define NE_SEGFLAGS_DISCARDABLE 0x1000
142 #define NE_SEGFLAGS_32BIT 0x2000
158 CHAR caretSlopeNumerator
;
159 CHAR caretSlopeDenominator
;
170 ULONG indexSubTableArrayOffset
;
171 ULONG indexTableSize
;
172 ULONG numberOfIndexSubTables
;
174 sbitLineMetrics_t hori
;
175 sbitLineMetrics_t vert
;
176 USHORT startGlyphIndex
;
177 USHORT endGlyphIndex
;
190 static FT_Version_t FT_Version
;
194 #define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] )
195 #define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \
196 GET_BE_WORD(&((WORD *)(ptr))[0]) ))
197 #ifdef WORDS_BIGENDIAN
198 static WORD
byteswap_word(WORD x
)
200 return ( ( (x
& 0xff) << 8) |
201 ( (x
& 0xff00) >> 8) );
203 static DWORD
byteswap_dword(DWORD x
)
205 return ( ( (x
& 0xff) << 24) |
206 ( (x
& 0xff00) << 8) |
207 ( (x
& 0xff0000) >> 8) |
208 ( (x
& 0xff000000) >> 24) );
210 # define PUT_LE_WORD(x) byteswap_word(x)
211 # define PUT_LE_DWORD(x) byteswap_dword(x)
213 # define PUT_LE_WORD(x) (x)
214 # define PUT_LE_DWORD(x) (x)
220 CHAR_TABLE_ENTRY dfCharTable
[258];
224 static const BYTE MZ_hdr
[] =
226 'M', 'Z', 0x0d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
227 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
230 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
231 'i', 's', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
232 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
233 'm', 'o', 'd', 'e', 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
236 static const WCHAR encoding_1250
[128] =
238 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
239 0x0088, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
240 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
241 0x0098, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
242 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
243 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
244 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
245 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
246 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
247 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
248 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
249 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
250 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
251 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
252 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
253 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
256 static const WCHAR encoding_1251
[128] =
258 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021,
259 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
260 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
261 0x0098, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
262 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7,
263 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
264 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7,
265 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
266 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
267 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
268 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
269 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
270 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,
271 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
272 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,
273 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f
276 static const WCHAR encoding_1252
[128] =
278 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
279 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f,
280 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
281 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178,
282 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
283 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
284 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
285 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
286 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
287 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
288 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
289 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
290 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
291 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
292 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
293 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
296 static const WCHAR encoding_1253
[128] =
298 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
299 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
300 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
301 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
302 0x00a0, 0x0385, 0x0386, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
303 0x00a8, 0x00a9, 0xf8f9, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x2015,
304 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x00b5, 0x00b6, 0x00b7,
305 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
306 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
307 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
308 0x03a0, 0x03a1, 0xf8fa, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
309 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
310 0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
311 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
312 0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
313 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0xf8fb
316 static const WCHAR encoding_1254
[128] =
318 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
319 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f,
320 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
321 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178,
322 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
323 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
324 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
325 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
326 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
327 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
328 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
329 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
330 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
331 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
332 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
333 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff
336 static const WCHAR encoding_1255
[128] =
338 0x20ac, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
339 0x02c6, 0x2030, 0x008a, 0x2039, 0x008c, 0x008d, 0x008e, 0x008f,
340 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
341 0x02dc, 0x2122, 0x009a, 0x203a, 0x009c, 0x009d, 0x009e, 0x009f,
342 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20aa, 0x00a5, 0x00a6, 0x00a7,
343 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
344 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
345 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
346 0x05b0, 0x05b1, 0x05b2, 0x05b3, 0x05b4, 0x05b5, 0x05b6, 0x05b7,
347 0x05b8, 0x05b9, 0x05ba, 0x05bb, 0x05bc, 0x05bd, 0x05be, 0x05bf,
348 0x05c0, 0x05c1, 0x05c2, 0x05c3, 0x05f0, 0x05f1, 0x05f2, 0x05f3,
349 0x05f4, 0xf88d, 0xf88e, 0xf88f, 0xf890, 0xf891, 0xf892, 0xf893,
350 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7,
351 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
352 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7,
353 0x05e8, 0x05e9, 0x05ea, 0xf894, 0xf895, 0x200e, 0x200f, 0xf896
356 static const WCHAR encoding_1256
[128] =
358 0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021,
359 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
360 0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
361 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
362 0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
363 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
364 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
365 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
366 0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627,
367 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
368 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7,
369 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
370 0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7,
371 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
372 0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7,
373 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2
376 static const WCHAR encoding_1257
[128] =
378 0x20ac, 0x0081, 0x201a, 0x0083, 0x201e, 0x2026, 0x2020, 0x2021,
379 0x0088, 0x2030, 0x008a, 0x2039, 0x008c, 0x00a8, 0x02c7, 0x00b8,
380 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
381 0x0098, 0x2122, 0x009a, 0x203a, 0x009c, 0x00af, 0x02db, 0x009f,
382 0x00a0, 0xf8fc, 0x00a2, 0x00a3, 0x00a4, 0xf8fd, 0x00a6, 0x00a7,
383 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
384 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
385 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
386 0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112,
387 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
388 0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7,
389 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
390 0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113,
391 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
392 0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7,
393 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x02d9
396 static const WCHAR encoding_874
[128] =
398 0x20ac, 0x0081, 0x0082, 0x0083, 0x0084, 0x2026, 0x0086, 0x0087,
399 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
400 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
401 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
402 0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07,
403 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
404 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17,
405 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
406 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27,
407 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
408 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37,
409 0x0e38, 0x0e39, 0x0e3a, 0xf8c1, 0xf8c2, 0xf8c3, 0xf8c4, 0x0e3f,
410 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47,
411 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
412 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57,
413 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0xf8c5, 0xf8c6, 0xf8c7, 0xf8c8
416 static const struct { int codepage
; const WCHAR
*table
; } encodings
[] =
418 { 874, encoding_874
},
419 { 1250, encoding_1250
},
420 { 1251, encoding_1251
},
421 { 1252, encoding_1252
},
422 { 1253, encoding_1253
},
423 { 1254, encoding_1254
},
424 { 1255, encoding_1255
},
425 { 1256, encoding_1256
},
426 { 1257, encoding_1257
},
427 { 0, encoding_1252
}, /* default encoding */
430 static char *option_output
;
431 static int option_defchar
= ' ';
432 static int option_dpi
= 96;
433 static int option_fnt_mode
= 0;
434 static int option_quiet
= 0;
436 static const char *output_name
;
438 static FT_Library ft_library
;
440 static void usage(char **argv
)
442 fprintf(stderr
, "%s [options] input.ttf ppem,enc,avg_width ...\n", argv
[0]);
443 fprintf(stderr
, "Options:\n");
444 fprintf(stderr
, " -h Display help\n" );
445 fprintf(stderr
, " -d char Set the font default char\n" );
446 fprintf(stderr
, " -o file Set output file name\n" );
447 fprintf(stderr
, " -q Quiet mode\n" );
448 fprintf(stderr
, " -r dpi Set resolution in DPI (default: 96)\n" );
449 fprintf(stderr
, " -s Single .fnt file mode\n" );
453 #define __attribute__(X)
456 /* atexit handler to cleanup files */
457 static void cleanup(void)
459 if (output_name
) unlink( output_name
);
462 static void exit_on_signal( int sig
)
464 exit(1); /* this will call the atexit functions */
467 static void error(const char *s
, ...) __attribute__((format (printf
, 1, 2)));
469 static void error(const char *s
, ...)
473 fprintf(stderr
, "Error: ");
474 vfprintf(stderr
, s
, ap
);
479 static const char *get_face_name( const struct fontinfo
*info
)
481 return (const char *)info
->data
+ info
->hdr
.fi
.dfFace
- info
->hdr
.fi
.dfBitsOffset
;
484 static int lookup_charset(int enc
)
486 /* FIXME: make winelib app and use TranslateCharsetInfo */
491 return RUSSIAN_CHARSET
;
495 return GREEK_CHARSET
;
497 return TURKISH_CHARSET
;
499 return HEBREW_CHARSET
;
501 return ARABIC_CHARSET
;
503 return BALTIC_CHARSET
;
505 return VIETNAMESE_CHARSET
;
525 return SHIFTJIS_CHARSET
;
527 return GB2312_CHARSET
;
529 return HANGUL_CHARSET
;
531 return CHINESEBIG5_CHARSET
;
533 fprintf(stderr
, "Unknown encoding %d - using OEM_CHARSET\n", enc
);
538 static void get_char_table(int enc
, WCHAR tableW
[0x100])
542 for (i
= 0; i
< 128; i
++) tableW
[i
] = i
;
544 for (i
= 0; encodings
[i
].codepage
; i
++) if (encodings
[i
].codepage
== enc
) break;
545 memcpy( tableW
+ 128, encodings
[i
].table
, 128 * sizeof(WCHAR
) );
547 /* Korean has the Won sign in place of '\\' */
548 if (enc
== 949) tableW
['\\'] = 0x20a9;
551 static struct fontinfo
*fill_fontinfo( const char *face_name
, int ppem
, int enc
, int dpi
,
552 unsigned char def_char
, int avg_width
)
555 int ascent
= 0, il
, el
, width_bytes
= 0, space_size
, max_width
= 0;
556 BYTE left_byte
, right_byte
, byte
;
558 int i
, x
, y
, x_off
, x_end
, first_char
;
561 FT_SfntName sfntname
;
565 bitmapSizeTable_t
*size_table
;
567 struct fontinfo
*info
;
571 if (FT_New_Face(ft_library
, face_name
, 0, &face
)) error( "Cannot open face %s\n", face_name
);
572 if (FT_Set_Pixel_Sizes(face
, ppem
, ppem
)) error( "cannot set face size to %u\n", ppem
);
574 assert( face
->size
->metrics
.y_ppem
== ppem
);
576 get_char_table( enc
, table
);
579 if (FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, NULL
, &needed
))
580 fprintf(stderr
,"Can't find EBLC table\n");
583 eblc
= malloc(needed
);
584 FT_Load_Sfnt_Table(face
, TTAG_EBLC
, 0, (FT_Byte
*)eblc
, &needed
);
586 num_sizes
= GET_BE_DWORD(&eblc
->numSizes
);
588 size_table
= (bitmapSizeTable_t
*)(eblc
+ 1);
589 for(i
= 0; i
< num_sizes
; i
++)
591 if( (signed char)size_table
->hori
.ascender
- (signed char)size_table
->hori
.descender
== ppem
)
593 ascent
= size_table
->hori
.ascender
;
602 /* Versions of fontforge prior to early 2006 have incorrect
603 ascender values in the eblc table, so we won't find the
604 correct bitmapSizeTable. In this case use the height of
605 the Aring glyph instead. */
608 if(FT_Load_Char(face
, 0xc5, FT_LOAD_DEFAULT
))
609 error("Can't find Aring\n");
610 ascent
= face
->glyph
->metrics
.horiBearingY
>> 6;
613 start
= sizeof(FNT_HEADER
);
615 if(FT_Load_Char(face
, 'M', FT_LOAD_DEFAULT
))
616 error("Can't find M\n");
617 il
= ascent
- (face
->glyph
->metrics
.height
>> 6);
619 /* Hack: Courier has no internal leading, nor do any Chinese or Japanese fonts */
620 if(!strcmp(face
->family_name
, "Courier") || enc
== 936 || enc
== 950 || enc
== 932)
622 else if (!strcmp(face
->family_name
, "Fixedsys"))
625 /* Japanese System font has an external leading */
626 if (!strcmp(face
->family_name
, "System") && enc
== 932)
631 first_char
= FT_Get_First_Char(face
, &gi
);
632 if(first_char
< 0x20) /* Ignore glyphs below 0x20 */
633 first_char
= 0x20; /* FT_Get_Next_Char for some reason returns too high
634 number in this case */
636 info
= calloc( 1, sizeof(*info
) );
638 info
->hdr
.fi
.dfFirstChar
= first_char
;
639 info
->hdr
.fi
.dfLastChar
= 0xff;
640 start
+= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
+ 3 ) * sizeof(*info
->dfCharTable
);
642 num_names
= FT_Get_Sfnt_Name_Count(face
);
643 for(i
= 0; i
<num_names
; i
++) {
644 FT_Get_Sfnt_Name(face
, i
, &sfntname
);
645 if(sfntname
.platform_id
== 1 && sfntname
.encoding_id
== 0 &&
646 sfntname
.language_id
== 0 && sfntname
.name_id
== 0) {
647 size_t len
= min( sfntname
.string_len
, sizeof(info
->hdr
.dfCopyright
)-1 );
648 memcpy(info
->hdr
.dfCopyright
, sfntname
.string
, len
);
649 info
->hdr
.dfCopyright
[len
] = 0;
653 os2
= FT_Get_Sfnt_Table(face
, ft_sfnt_os2
);
654 for(i
= first_char
; i
< 0x100; i
++) {
655 gi
= FT_Get_Char_Index(face
, table
[i
]);
656 if(gi
== 0 && !option_quiet
)
657 fprintf(stderr
, "warning: %s %u: missing glyph for char %04x\n",
658 face
->family_name
, ppem
, table
[i
]);
659 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
660 fprintf(stderr
, "error loading char %d - bad news!\n", i
);
663 info
->dfCharTable
[i
].width
= face
->glyph
->metrics
.horiAdvance
>> 6;
664 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
665 width_bytes
+= ((face
->glyph
->metrics
.horiAdvance
>> 6) + 7) >> 3;
666 if(max_width
< (face
->glyph
->metrics
.horiAdvance
>> 6))
667 max_width
= face
->glyph
->metrics
.horiAdvance
>> 6;
670 space_size
= (ppem
+ 3) / 4;
671 info
->dfCharTable
[i
].width
= space_size
;
672 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
673 width_bytes
+= (space_size
+ 7) >> 3;
675 info
->dfCharTable
[++i
].width
= 0;
676 info
->dfCharTable
[i
].offset
= start
+ (width_bytes
* ppem
);
678 info
->hdr
.fi
.dfType
= 0;
679 info
->hdr
.fi
.dfPoints
= ((ppem
- il
- el
) * 72 + dpi
/2) / dpi
;
680 info
->hdr
.fi
.dfVertRes
= dpi
;
681 info
->hdr
.fi
.dfHorizRes
= dpi
;
682 info
->hdr
.fi
.dfAscent
= ascent
;
683 info
->hdr
.fi
.dfInternalLeading
= il
;
684 info
->hdr
.fi
.dfExternalLeading
= el
;
685 info
->hdr
.fi
.dfItalic
= (face
->style_flags
& FT_STYLE_FLAG_ITALIC
) ? 1 : 0;
686 info
->hdr
.fi
.dfUnderline
= 0;
687 info
->hdr
.fi
.dfStrikeOut
= 0;
688 info
->hdr
.fi
.dfWeight
= os2
->usWeightClass
;
689 info
->hdr
.fi
.dfCharSet
= lookup_charset(enc
);
690 info
->hdr
.fi
.dfPixWidth
= (face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) ? avg_width
: 0;
691 info
->hdr
.fi
.dfPixHeight
= ppem
;
692 info
->hdr
.fi
.dfPitchAndFamily
= FT_IS_FIXED_WIDTH(face
) ? 0 : TMPF_FIXED_PITCH
;
693 switch(os2
->panose
[PAN_FAMILYTYPE_INDEX
]) {
694 case PAN_FAMILY_SCRIPT
:
695 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SCRIPT
;
697 case PAN_FAMILY_DECORATIVE
:
698 case PAN_FAMILY_PICTORIAL
:
699 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DECORATIVE
;
701 case PAN_FAMILY_TEXT_DISPLAY
:
702 if(info
->hdr
.fi
.dfPitchAndFamily
== 0) /* fixed */
703 info
->hdr
.fi
.dfPitchAndFamily
= FF_MODERN
;
705 switch(os2
->panose
[PAN_SERIFSTYLE_INDEX
]) {
706 case PAN_SERIF_NORMAL_SANS
:
707 case PAN_SERIF_OBTUSE_SANS
:
708 case PAN_SERIF_PERP_SANS
:
709 info
->hdr
.fi
.dfPitchAndFamily
|= FF_SWISS
;
712 info
->hdr
.fi
.dfPitchAndFamily
|= FF_ROMAN
;
717 info
->hdr
.fi
.dfPitchAndFamily
|= FF_DONTCARE
;
720 info
->hdr
.fi
.dfAvgWidth
= avg_width
;
721 info
->hdr
.fi
.dfMaxWidth
= (enc
== 932) ? avg_width
* 2 : max_width
;
722 info
->hdr
.fi
.dfDefaultChar
= def_char
- info
->hdr
.fi
.dfFirstChar
;
723 info
->hdr
.fi
.dfBreakChar
= ' ' - info
->hdr
.fi
.dfFirstChar
;
724 info
->hdr
.fi
.dfWidthBytes
= (width_bytes
+ 1) & ~1;
726 info
->hdr
.fi
.dfFace
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
;
727 info
->hdr
.fi
.dfBitsOffset
= start
;
728 info
->hdr
.fi
.dfFlags
= 0x10; /* DFF_1COLOR */
729 info
->hdr
.fi
.dfFlags
|= FT_IS_FIXED_WIDTH(face
) ? 1 : 2; /* DFF_FIXED : DFF_PROPORTIONAL */
731 info
->hdr
.dfVersion
= 0x300;
732 info
->hdr
.dfSize
= start
+ info
->hdr
.fi
.dfWidthBytes
* ppem
+ strlen(face
->family_name
) + 1;
734 info
->data
= calloc( info
->hdr
.dfSize
- start
, 1 );
737 for(i
= first_char
; i
< 0x100; i
++) {
738 if(FT_Load_Char(face
, table
[i
], FT_LOAD_DEFAULT
)) {
741 assert(info
->dfCharTable
[i
].width
== face
->glyph
->metrics
.horiAdvance
>> 6);
743 for(x
= 0; x
< ((info
->dfCharTable
[i
].width
+ 7) / 8); x
++) {
744 for(y
= 0; y
< ppem
; y
++) {
745 if(y
< ascent
- face
->glyph
->bitmap_top
||
746 y
>= face
->glyph
->bitmap
.rows
+ ascent
- face
->glyph
->bitmap_top
) {
747 info
->data
[data_pos
++] = 0;
750 x_off
= face
->glyph
->bitmap_left
/ 8;
751 x_end
= (face
->glyph
->bitmap_left
+ face
->glyph
->bitmap
.width
- 1) / 8;
752 if(x
< x_off
|| x
> x_end
) {
753 info
->data
[data_pos
++] = 0;
759 left_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
- 1];
761 /* On the last non-trivial output byte (x == x_end) have we got one or two input bytes */
762 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)))
765 right_byte
= face
->glyph
->bitmap
.buffer
[(y
- (ascent
- face
->glyph
->bitmap_top
)) * face
->glyph
->bitmap
.pitch
+ x
- x_off
];
767 byte
= (left_byte
<< (8 - (face
->glyph
->bitmap_left
& 7))) & 0xff;
768 byte
|= ((right_byte
>> (face
->glyph
->bitmap_left
& 7)) & 0xff);
769 info
->data
[data_pos
++] = byte
;
773 data_pos
+= ((space_size
+ 7) / 8) * ppem
;
774 if (width_bytes
& 1) data_pos
+= ppem
;
776 memcpy( info
->data
+ data_pos
, face
->family_name
, strlen( face
->family_name
));
777 data_pos
+= strlen( face
->family_name
) + 1;
778 assert( start
+ data_pos
== info
->hdr
.dfSize
);
780 FT_Done_Face( face
);
784 static void adjust_fontinfo( FONTINFO16
* fi
)
786 fi
->dfType
= PUT_LE_WORD(fi
->dfType
);
787 fi
->dfPoints
= PUT_LE_WORD(fi
->dfPoints
);
788 fi
->dfVertRes
= PUT_LE_WORD(fi
->dfVertRes
);
789 fi
->dfHorizRes
= PUT_LE_WORD(fi
->dfHorizRes
);
790 fi
->dfAscent
= PUT_LE_WORD(fi
->dfAscent
);
791 fi
->dfInternalLeading
= PUT_LE_WORD(fi
->dfInternalLeading
);
792 fi
->dfExternalLeading
= PUT_LE_WORD(fi
->dfExternalLeading
);
793 fi
->dfWeight
= PUT_LE_WORD(fi
->dfWeight
);
794 fi
->dfPixWidth
= PUT_LE_WORD(fi
->dfPixWidth
);
795 fi
->dfPixHeight
= PUT_LE_WORD(fi
->dfPixHeight
);
796 fi
->dfAvgWidth
= PUT_LE_WORD(fi
->dfAvgWidth
);
797 fi
->dfMaxWidth
= PUT_LE_WORD(fi
->dfMaxWidth
);
798 fi
->dfWidthBytes
= PUT_LE_WORD(fi
->dfWidthBytes
);
799 fi
->dfAspace
= PUT_LE_WORD(fi
->dfAspace
);
800 fi
->dfBspace
= PUT_LE_WORD(fi
->dfBspace
);
801 fi
->dfCspace
= PUT_LE_WORD(fi
->dfCspace
);
802 fi
->dfDevice
= PUT_LE_DWORD(fi
->dfDevice
);
803 fi
->dfFace
= PUT_LE_DWORD(fi
->dfFace
);
804 fi
->dfBitsPointer
= PUT_LE_DWORD(fi
->dfBitsPointer
);
805 fi
->dfBitsOffset
= PUT_LE_DWORD(fi
->dfBitsOffset
);
806 fi
->dfFlags
= PUT_LE_DWORD(fi
->dfFlags
);
807 fi
->dfColorPointer
= PUT_LE_DWORD(fi
->dfColorPointer
);
810 static void write_fontinfo( const struct fontinfo
*info
, FILE *fp
)
814 CHAR_TABLE_ENTRY tmp_chartable
[258];
815 memcpy(&tmp_hdr
, &info
->hdr
, sizeof(info
->hdr
));
816 tmp_hdr
.dfVersion
= PUT_LE_WORD(tmp_hdr
.dfVersion
);
817 tmp_hdr
.dfSize
= PUT_LE_DWORD(tmp_hdr
.dfSize
);
818 adjust_fontinfo(&(tmp_hdr
.fi
));
819 fwrite( &tmp_hdr
, sizeof(info
->hdr
), 1, fp
);
820 num_chars
= ((unsigned char)info
->hdr
.fi
.dfLastChar
- (unsigned char)info
->hdr
.fi
.dfFirstChar
) + 3;
822 memcpy(&tmp_chartable
, info
->dfCharTable
+ info
->hdr
.fi
.dfFirstChar
, num_chars
* sizeof(CHAR_TABLE_ENTRY
));
823 for (i
=0; i
< num_chars
; ++i
) {
824 tmp_chartable
[i
].width
= PUT_LE_WORD(tmp_chartable
[i
].width
);
825 tmp_chartable
[i
].offset
= PUT_LE_DWORD(tmp_chartable
[i
].offset
);
827 fwrite( tmp_chartable
, sizeof(CHAR_TABLE_ENTRY
), num_chars
, fp
);
828 fwrite( info
->data
, info
->hdr
.dfSize
- info
->hdr
.fi
.dfBitsOffset
, 1, fp
);
831 /* parse options from the argv array and remove all the recognized ones */
832 static char **parse_options( int argc
, char **argv
)
836 while ((optc
= getopt_long( argc
, argv
, "d:ho:qr:s", NULL
, NULL
)) != -1)
841 option_defchar
= atoi( optarg
);
844 option_output
= strdup( optarg
);
850 option_dpi
= atoi( optarg
);
863 return &argv
[optind
];
866 int main(int argc
, char **argv
)
870 short align
, num_files
;
871 int resource_table_len
, non_resident_name_len
, resident_name_len
;
872 unsigned short resource_table_off
, resident_name_off
, module_ref_off
, non_resident_name_off
, fontdir_off
, font_off
;
873 char resident_name
[200];
875 char non_resident_name
[200];
876 unsigned short first_res
= 0x0050, pad
, res
;
877 IMAGE_OS2_HEADER NE_hdr
;
880 struct fontinfo
**info
;
885 args
= parse_options( argc
, argv
);
887 input_file
= *args
++;
888 if (!input_file
|| !*args
)
894 if(FT_Init_FreeType(&ft_library
))
895 error("ft init failure\n");
897 FT_Version
.major
=FT_Version
.minor
=FT_Version
.patch
=-1;
898 FT_Library_Version(ft_library
,&FT_Version
.major
,&FT_Version
.minor
,&FT_Version
.patch
);
901 while (args
[num_files
]) num_files
++;
903 if (option_fnt_mode
&& num_files
> 1)
904 error( "can only specify one font in .fnt mode\n" );
906 info
= malloc( num_files
* sizeof(*info
) );
907 for (i
= 0; i
< num_files
; i
++)
909 int ppem
, enc
, avg_width
;
912 if (sscanf( args
[i
], "%d,%d,%d", &ppem
, &enc
, &avg_width
) != 3)
917 if (!(info
[i
] = fill_fontinfo( input_file
, ppem
, enc
, option_dpi
, option_defchar
, avg_width
)))
920 name
= get_face_name( info
[i
] );
921 fontdir_len
+= 0x74 + strlen(name
) + 1;
923 sprintf(non_resident_name
, "FONTRES 100,%d,%d : %s %d",
924 info
[i
]->hdr
.fi
.dfVertRes
, info
[i
]->hdr
.fi
.dfHorizRes
,
925 name
, info
[i
]->hdr
.fi
.dfPoints
);
926 strcpy(resident_name
, name
);
928 sprintf(non_resident_name
+ strlen(non_resident_name
), ",%d", info
[i
]->hdr
.fi
.dfPoints
);
932 if (option_dpi
<= 108)
933 strcat(non_resident_name
, " (VGA res)");
935 strcat(non_resident_name
, " (8514 res)");
936 non_resident_name_len
= strlen(non_resident_name
) + 4;
938 /* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
939 resource_table_len
= sizeof(align
) + sizeof("FONTDIR") +
940 sizeof(NE_TYPEINFO
) + sizeof(NE_NAMEINFO
) +
941 sizeof(NE_TYPEINFO
) + sizeof(NE_NAMEINFO
) * num_files
+
943 resource_table_off
= sizeof(NE_hdr
);
944 resident_name_off
= resource_table_off
+ resource_table_len
;
945 resident_name_len
= strlen(resident_name
) + 4;
946 module_ref_off
= resident_name_off
+ resident_name_len
;
947 non_resident_name_off
= sizeof(MZ_hdr
) + module_ref_off
+ sizeof(align
);
949 memset(&NE_hdr
, 0, sizeof(NE_hdr
));
950 NE_hdr
.ne_magic
= PUT_LE_WORD(0x454e);
953 NE_hdr
.ne_flags
= PUT_LE_WORD(NE_FFLAGS_LIBMODULE
| NE_FFLAGS_GUI
);
954 NE_hdr
.ne_cbnrestab
= PUT_LE_WORD(non_resident_name_len
);
955 NE_hdr
.ne_segtab
= PUT_LE_WORD(sizeof(NE_hdr
));
956 NE_hdr
.ne_rsrctab
= PUT_LE_WORD(sizeof(NE_hdr
));
957 NE_hdr
.ne_restab
= PUT_LE_WORD(resident_name_off
);
958 NE_hdr
.ne_modtab
= PUT_LE_WORD(module_ref_off
);
959 NE_hdr
.ne_imptab
= PUT_LE_WORD(module_ref_off
);
960 NE_hdr
.ne_enttab
= NE_hdr
.ne_modtab
;
961 NE_hdr
.ne_nrestab
= PUT_LE_DWORD(non_resident_name_off
);
962 NE_hdr
.ne_align
= PUT_LE_WORD(4);
963 NE_hdr
.ne_exetyp
= NE_OSFLAGS_WINDOWS
;
964 NE_hdr
.ne_expver
= PUT_LE_WORD(0x400);
966 fontdir_off
= (non_resident_name_off
+ non_resident_name_len
+ 15) & ~0xf;
967 font_off
= (fontdir_off
+ fontdir_len
+ 15) & ~0x0f;
970 signal( SIGTERM
, exit_on_signal
);
971 signal( SIGINT
, exit_on_signal
);
973 signal( SIGHUP
, exit_on_signal
);
976 if (!option_output
) /* build a default output name */
978 char *p
= strrchr( input_file
, '/' );
981 option_output
= malloc( strlen(p
) + sizeof(".fon") );
982 strcpy( option_output
, p
);
983 p
= strrchr( option_output
, '.' );
984 if (!p
) p
= option_output
+ strlen(option_output
);
985 strcpy( p
, option_fnt_mode
? ".fnt" : ".fon" );
988 if (!(ofp
= fopen(option_output
, "wb")))
990 perror( option_output
);
993 output_name
= option_output
;
996 write_fontinfo( info
[0], ofp
);
1000 fwrite(MZ_hdr
, sizeof(MZ_hdr
), 1, ofp
);
1001 fwrite(&NE_hdr
, sizeof(NE_hdr
), 1, ofp
);
1003 align
= PUT_LE_WORD(4);
1004 fwrite(&align
, sizeof(align
), 1, ofp
);
1006 rc_type
.type_id
= PUT_LE_WORD(NE_RSCTYPE_FONTDIR
);
1007 rc_type
.count
= PUT_LE_WORD(1);
1008 rc_type
.resloader
= 0;
1009 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
1011 rc_name
.offset
= PUT_LE_WORD(fontdir_off
>> 4);
1012 rc_name
.length
= PUT_LE_WORD((fontdir_len
+ 15) >> 4);
1013 rc_name
.flags
= PUT_LE_WORD(NE_SEGFLAGS_MOVEABLE
| NE_SEGFLAGS_PRELOAD
);
1014 rc_name
.id
= PUT_LE_WORD(resident_name_off
- sizeof("FONTDIR") - sizeof(NE_hdr
));
1017 fwrite(&rc_name
, sizeof(rc_name
), 1, ofp
);
1019 rc_type
.type_id
= PUT_LE_WORD(NE_RSCTYPE_FONT
);
1020 rc_type
.count
= PUT_LE_WORD(num_files
);
1021 rc_type
.resloader
= 0;
1022 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
1024 for(res
= first_res
| 0x8000, i
= 0; i
< num_files
; i
++, res
++) {
1025 int len
= (info
[i
]->hdr
.dfSize
+ 15) & ~0xf;
1027 rc_name
.offset
= PUT_LE_WORD(font_off
>> 4);
1028 rc_name
.length
= PUT_LE_WORD(len
>> 4);
1029 rc_name
.flags
= PUT_LE_WORD(NE_SEGFLAGS_MOVEABLE
| NE_SEGFLAGS_SHAREABLE
| NE_SEGFLAGS_DISCARDABLE
);
1030 rc_name
.id
= PUT_LE_WORD(res
);
1033 fwrite(&rc_name
, sizeof(rc_name
), 1, ofp
);
1038 /* empty type info */
1039 memset(&rc_type
, 0, sizeof(rc_type
));
1040 fwrite(&rc_type
, sizeof(rc_type
), 1, ofp
);
1042 fputc(strlen("FONTDIR"), ofp
);
1043 fwrite("FONTDIR", strlen("FONTDIR"), 1, ofp
);
1044 fputc(strlen(resident_name
), ofp
);
1045 fwrite(resident_name
, strlen(resident_name
), 1, ofp
);
1047 fputc(0x00, ofp
); fputc(0x00, ofp
);
1049 fputc(0x00, ofp
); fputc(0x00, ofp
);
1051 fputc(strlen(non_resident_name
), ofp
);
1052 fwrite(non_resident_name
, strlen(non_resident_name
), 1, ofp
);
1053 fputc(0x00, ofp
); /* terminator */
1055 /* empty ne_modtab and ne_imptab */
1059 pad
= ftell(ofp
) & 0xf;
1062 for(i
= 0; i
< pad
; i
++)
1065 /* FONTDIR resource */
1066 tmp16
= PUT_LE_WORD(num_files
);
1067 fwrite(&tmp16
, sizeof(tmp16
), 1, ofp
);
1069 for(res
= first_res
, i
= 0; i
< num_files
; i
++, res
++) {
1072 const char *name
= get_face_name( info
[i
] );
1073 tmp16
= PUT_LE_WORD(res
);
1074 fwrite(&tmp16
, sizeof(tmp16
), 1, ofp
);
1075 sz
= FIELD_OFFSET(FNT_HEADER
,fi
.dfBitsOffset
);
1076 memcpy(&tmp_hdr
, &info
[i
]->hdr
, sz
);
1077 tmp_hdr
.dfVersion
= PUT_LE_WORD(tmp_hdr
.dfVersion
);
1078 tmp_hdr
.dfSize
= PUT_LE_DWORD(tmp_hdr
.dfSize
);
1079 adjust_fontinfo(&(tmp_hdr
.fi
));
1080 fwrite(&tmp_hdr
, FIELD_OFFSET(FNT_HEADER
,fi
.dfBitsOffset
), 1, ofp
);
1082 fwrite(name
, strlen(name
) + 1, 1, ofp
);
1085 pad
= ftell(ofp
) & 0xf;
1088 for(i
= 0; i
< pad
; i
++)
1091 for(res
= first_res
, i
= 0; i
< num_files
; i
++, res
++) {
1092 write_fontinfo( info
[i
], ofp
);
1093 pad
= info
[i
]->hdr
.dfSize
& 0xf;
1096 for(j
= 0; j
< pad
; j
++)
1105 #else /* HAVE_FREETYPE */
1107 int main(int argc
, char **argv
)
1109 fprintf( stderr
, "%s needs to be built with FreeType support\n", argv
[0] );
1113 #endif /* HAVE_FREETYPE */