Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/tools/sfnt2fon/sfnt2fon.c
4389 views
1
/*
2
* sfnt2fon. Bitmap-only ttf to Windows font file converter
3
*
4
* Copyright 2004 Huw Davies
5
*
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.
10
*
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.
15
*
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
19
*/
20
21
#include "config.h"
22
23
#include <assert.h>
24
#include <ctype.h>
25
#include <errno.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
29
#ifdef HAVE_FREETYPE
30
31
#ifdef HAVE_FT2BUILD_H
32
#include <ft2build.h>
33
#endif
34
#include FT_FREETYPE_H
35
#include FT_SFNT_NAMES_H
36
#include FT_TRUETYPE_TABLES_H
37
#include FT_TRUETYPE_TAGS_H
38
39
#include "windef.h"
40
#include "winbase.h"
41
#include "wingdi.h"
42
#include "basetsd.h"
43
#include "../tools.h"
44
45
#pragma pack(push,1)
46
47
typedef struct
48
{
49
INT16 dfType;
50
INT16 dfPoints;
51
INT16 dfVertRes;
52
INT16 dfHorizRes;
53
INT16 dfAscent;
54
INT16 dfInternalLeading;
55
INT16 dfExternalLeading;
56
BYTE dfItalic;
57
BYTE dfUnderline;
58
BYTE dfStrikeOut;
59
INT16 dfWeight;
60
BYTE dfCharSet;
61
INT16 dfPixWidth;
62
INT16 dfPixHeight;
63
BYTE dfPitchAndFamily;
64
INT16 dfAvgWidth;
65
INT16 dfMaxWidth;
66
BYTE dfFirstChar;
67
BYTE dfLastChar;
68
BYTE dfDefaultChar;
69
BYTE dfBreakChar;
70
INT16 dfWidthBytes;
71
LONG dfDevice;
72
LONG dfFace;
73
LONG dfBitsPointer;
74
LONG dfBitsOffset;
75
BYTE dfReserved;
76
LONG dfFlags;
77
INT16 dfAspace;
78
INT16 dfBspace;
79
INT16 dfCspace;
80
LONG dfColorPointer;
81
LONG dfReserved1[4];
82
} FONTINFO16;
83
84
typedef struct
85
{
86
WORD dfVersion;
87
DWORD dfSize;
88
char dfCopyright[60];
89
FONTINFO16 fi;
90
} FNT_HEADER;
91
92
typedef struct {
93
WORD width;
94
DWORD offset;
95
} CHAR_TABLE_ENTRY;
96
97
typedef struct {
98
DWORD version;
99
ULONG numSizes;
100
} eblcHeader_t;
101
102
typedef struct {
103
CHAR ascender;
104
CHAR descender;
105
BYTE widthMax;
106
CHAR caretSlopeNumerator;
107
CHAR caretSlopeDenominator;
108
CHAR caretOffset;
109
CHAR minOriginSB;
110
CHAR minAdvanceSB;
111
CHAR maxBeforeBL;
112
CHAR maxAfterBL;
113
CHAR pad1;
114
CHAR pad2;
115
} sbitLineMetrics_t;
116
117
typedef struct {
118
ULONG indexSubTableArrayOffset;
119
ULONG indexTableSize;
120
ULONG numberOfIndexSubTables;
121
ULONG colorRef;
122
sbitLineMetrics_t hori;
123
sbitLineMetrics_t vert;
124
USHORT startGlyphIndex;
125
USHORT endGlyphIndex;
126
BYTE ppemX;
127
BYTE ppemY;
128
BYTE bitDepth;
129
CHAR flags;
130
} bitmapSizeTable_t;
131
132
typedef struct
133
{
134
FT_Int major;
135
FT_Int minor;
136
FT_Int patch;
137
} FT_Version_t;
138
static FT_Version_t FT_Version;
139
140
#pragma pack(pop)
141
142
unsigned char *output_buffer = NULL;
143
size_t output_buffer_pos = 0;
144
size_t output_buffer_size = 0;
145
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]) ))
149
150
struct fontinfo
151
{
152
FNT_HEADER hdr;
153
CHAR_TABLE_ENTRY dfCharTable[258];
154
BYTE *data;
155
};
156
157
static const BYTE MZ_hdr[] =
158
{
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
167
};
168
169
static const WCHAR encoding_1250[128] =
170
{
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
187
};
188
189
static const WCHAR encoding_1251[128] =
190
{
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
207
};
208
209
static const WCHAR encoding_1252[128] =
210
{
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
227
};
228
229
static const WCHAR encoding_1253[128] =
230
{
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
247
};
248
249
static const WCHAR encoding_1254[128] =
250
{
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
267
};
268
269
static const WCHAR encoding_1255[128] =
270
{
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
287
};
288
289
static const WCHAR encoding_1256[128] =
290
{
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
307
};
308
309
static const WCHAR encoding_1257[128] =
310
{
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
327
};
328
329
static const WCHAR encoding_874[128] =
330
{
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
347
};
348
349
static const struct { int codepage; const WCHAR *table; } encodings[] =
350
{
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 */
361
};
362
363
static int option_defchar = ' ';
364
static int option_dpi = 96;
365
static int option_fnt_mode = 0;
366
static int option_quiet = 0;
367
368
static const char *output_name;
369
370
static FT_Library ft_library;
371
372
static const char *argv0;
373
374
static void usage(void)
375
{
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" );
384
}
385
386
/* atexit handler to cleanup files */
387
static void cleanup(void)
388
{
389
if (output_name) unlink( output_name );
390
}
391
392
static void exit_on_signal( int sig )
393
{
394
exit(1); /* this will call the atexit functions */
395
}
396
397
static void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
398
399
static void error(const char *s, ...)
400
{
401
va_list ap;
402
va_start(ap, s);
403
fprintf(stderr, "Error: ");
404
vfprintf(stderr, s, ap);
405
va_end(ap);
406
exit(1);
407
}
408
409
static const char *get_face_name( const struct fontinfo *info )
410
{
411
return (const char *)info->data + info->hdr.fi.dfFace - info->hdr.fi.dfBitsOffset;
412
}
413
414
static int lookup_charset(int enc)
415
{
416
/* FIXME: make winelib app and use TranslateCharsetInfo */
417
switch(enc) {
418
case 1250:
419
return EE_CHARSET;
420
case 1251:
421
return RUSSIAN_CHARSET;
422
case 1252:
423
return ANSI_CHARSET;
424
case 1253:
425
return GREEK_CHARSET;
426
case 1254:
427
return TURKISH_CHARSET;
428
case 1255:
429
return HEBREW_CHARSET;
430
case 1256:
431
return ARABIC_CHARSET;
432
case 1257:
433
return BALTIC_CHARSET;
434
case 1258:
435
return VIETNAMESE_CHARSET;
436
case 437:
437
case 737:
438
case 775:
439
case 850:
440
case 852:
441
case 855:
442
case 857:
443
case 860:
444
case 861:
445
case 862:
446
case 863:
447
case 864:
448
case 865:
449
case 866:
450
case 869:
451
return OEM_CHARSET;
452
case 874:
453
return THAI_CHARSET;
454
case 932:
455
return SHIFTJIS_CHARSET;
456
case 936:
457
return GB2312_CHARSET;
458
case 949:
459
return HANGUL_CHARSET;
460
case 950:
461
return CHINESEBIG5_CHARSET;
462
}
463
fprintf(stderr, "Unknown encoding %d - using OEM_CHARSET\n", enc);
464
465
return OEM_CHARSET;
466
}
467
468
static void get_char_table(int enc, WCHAR tableW[0x100])
469
{
470
unsigned int i;
471
472
for (i = 0; i < 128; i++) tableW[i] = i;
473
474
for (i = 0; encodings[i].codepage; i++) if (encodings[i].codepage == enc) break;
475
memcpy( tableW + 128, encodings[i].table, 128 * sizeof(WCHAR) );
476
477
/* Korean has the Won sign in place of '\\' */
478
if (enc == 949) tableW['\\'] = 0x20a9;
479
}
480
481
static struct fontinfo *fill_fontinfo( const char *face_name, int ppem, int enc, int dpi,
482
unsigned char def_char, int avg_width )
483
{
484
FT_Face face;
485
int ascent = 0, il, el, width_bytes = 0, space_size, max_width = 0;
486
BYTE left_byte, right_byte, byte;
487
DWORD start;
488
int i, x, y, x_off, x_end, first_char;
489
FT_UInt gi;
490
int num_names;
491
FT_SfntName sfntname;
492
TT_OS2 *os2;
493
FT_ULong needed;
494
eblcHeader_t *eblc;
495
bitmapSizeTable_t *size_table;
496
int num_sizes;
497
struct fontinfo *info;
498
size_t data_pos;
499
WCHAR table[0x100];
500
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 );
503
504
assert( face->size->metrics.y_ppem == ppem );
505
506
get_char_table( enc, table );
507
508
needed = 0;
509
if (FT_Load_Sfnt_Table(face, TTAG_EBLC, 0, NULL, &needed))
510
fprintf(stderr,"Can't find EBLC table\n");
511
else
512
{
513
eblc = xmalloc(needed);
514
FT_Load_Sfnt_Table(face, TTAG_EBLC, 0, (FT_Byte *)eblc, &needed);
515
516
num_sizes = GET_BE_DWORD(&eblc->numSizes);
517
518
size_table = (bitmapSizeTable_t *)(eblc + 1);
519
for(i = 0; i < num_sizes; i++)
520
{
521
if( (signed char)size_table->hori.ascender - (signed char)size_table->hori.descender == ppem)
522
{
523
ascent = size_table->hori.ascender;
524
break;
525
}
526
size_table++;
527
}
528
529
free(eblc);
530
}
531
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. */
536
if(ascent == 0)
537
{
538
if(FT_Load_Char(face, 0xc5, FT_LOAD_DEFAULT))
539
error("Can't find Aring\n");
540
ascent = face->glyph->metrics.horiBearingY >> 6;
541
}
542
543
start = sizeof(FNT_HEADER);
544
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);
548
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)
551
il = 0;
552
else if (!strcmp(face->family_name, "Fixedsys"))
553
il = 3;
554
555
/* Japanese System font has an external leading */
556
if (!strcmp(face->family_name, "System") && enc == 932)
557
el = 2;
558
else
559
el = 0;
560
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 */
565
566
info = calloc( 1, sizeof(*info) );
567
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);
571
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;
580
}
581
}
582
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);
591
continue;
592
}
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;
598
}
599
/* space */
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;
604
/* sentinel */
605
info->dfCharTable[++i].width = 0;
606
info->dfCharTable[i].offset = start + (width_bytes * ppem);
607
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;
626
break;
627
case PAN_FAMILY_DECORATIVE:
628
case PAN_FAMILY_PICTORIAL:
629
info->hdr.fi.dfPitchAndFamily |= FF_DECORATIVE;
630
break;
631
case PAN_FAMILY_TEXT_DISPLAY:
632
if(info->hdr.fi.dfPitchAndFamily == 0) /* fixed */
633
info->hdr.fi.dfPitchAndFamily = FF_MODERN;
634
else {
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;
640
break;
641
default:
642
info->hdr.fi.dfPitchAndFamily |= FF_ROMAN;
643
}
644
}
645
break;
646
default:
647
info->hdr.fi.dfPitchAndFamily |= FF_DONTCARE;
648
}
649
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;
655
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 */
660
661
info->hdr.dfVersion = 0x300;
662
info->hdr.dfSize = start + info->hdr.fi.dfWidthBytes * ppem + strlen(face->family_name) + 1;
663
664
info->data = calloc( info->hdr.dfSize - start, 1 );
665
data_pos = 0;
666
667
for(i = first_char; i < 0x100; i++) {
668
if(FT_Load_Char(face, table[i], FT_LOAD_DEFAULT)) {
669
continue;
670
}
671
assert(info->dfCharTable[i].width == face->glyph->metrics.horiAdvance >> 6);
672
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;
678
continue;
679
}
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;
684
continue;
685
}
686
if(x == x_off)
687
left_byte = 0;
688
else
689
left_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off - 1];
690
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)))
693
right_byte = 0;
694
else
695
right_byte = face->glyph->bitmap.buffer[(y - (ascent - face->glyph->bitmap_top)) * face->glyph->bitmap.pitch + x - x_off];
696
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;
700
}
701
}
702
}
703
data_pos += ((space_size + 7) / 8) * ppem;
704
if (width_bytes & 1) data_pos += ppem;
705
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 );
709
710
FT_Done_Face( face );
711
return info;
712
}
713
714
static void put_fontdir( const struct fontinfo *info )
715
{
716
const char *name = get_face_name( info );
717
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 */
748
}
749
750
static void put_font( const struct fontinfo *info )
751
{
752
int num_chars, i;
753
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++)
795
{
796
put_word( info->dfCharTable[info->hdr.fi.dfFirstChar + i].width );
797
put_dword( info->dfCharTable[info->hdr.fi.dfFirstChar + i].offset );
798
}
799
put_data( info->data, info->hdr.dfSize - info->hdr.fi.dfBitsOffset );
800
}
801
802
static void option_callback( int optc, char *optarg )
803
{
804
switch(optc)
805
{
806
case 'd':
807
option_defchar = atoi( optarg );
808
break;
809
case 'o':
810
output_name = xstrdup( optarg );
811
break;
812
case 'q':
813
option_quiet = 1;
814
break;
815
case 'r':
816
option_dpi = atoi( optarg );
817
break;
818
case 's':
819
option_fnt_mode = 1;
820
break;
821
case 'h':
822
usage();
823
exit(0);
824
case '?':
825
fprintf( stderr, "%s: %s\n\n", argv0, optarg );
826
usage();
827
exit(1);
828
}
829
}
830
831
832
int main(int argc, char **argv)
833
{
834
int i, num_files;
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];
840
int fontdir_len = 2;
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;
846
847
argv0 = argv[0];
848
args = parse_options( argc, argv, "d:ho:qr:s", NULL, 0, option_callback );
849
850
if (!args.count)
851
{
852
usage();
853
exit(1);
854
}
855
input_file = args.str[0];
856
857
if(FT_Init_FreeType(&ft_library))
858
error("ft init failure\n");
859
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);
862
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" );
866
867
info = xmalloc( num_files * sizeof(*info) );
868
for (i = 0; i < num_files; i++)
869
{
870
int ppem, enc, avg_width;
871
const char *name;
872
873
if (sscanf( args.str[i + 1], "%d,%d,%d", &ppem, &enc, &avg_width ) != 3)
874
{
875
usage();
876
exit(1);
877
}
878
if (!(info[i] = fill_fontinfo( input_file, ppem, enc, option_dpi, option_defchar, avg_width )))
879
exit(1);
880
881
name = get_face_name( info[i] );
882
fontdir_len += 0x74 + strlen(name) + 1;
883
if(i == 0) {
884
snprintf(non_resident_name, sizeof(non_resident_name),
885
"FONTRES 100,%d,%d : %s %d",
886
info[i]->hdr.fi.dfVertRes, info[i]->hdr.fi.dfHorizRes,
887
name, info[i]->hdr.fi.dfPoints );
888
strcpy(resident_name, name);
889
} else {
890
snprintf(non_resident_name + strlen(non_resident_name),
891
sizeof(non_resident_name) - strlen(non_resident_name),
892
",%d", info[i]->hdr.fi.dfPoints );
893
}
894
}
895
896
if (option_dpi <= 108)
897
strcat(non_resident_name, " (VGA res)");
898
else
899
strcat(non_resident_name, " (8514 res)");
900
non_resident_name_len = strlen(non_resident_name) + 4;
901
902
/* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
903
resource_table_len = sizeof(WORD) /* align */ + sizeof("FONTDIR") +
904
typeinfo_size + nameinfo_size +
905
typeinfo_size + nameinfo_size * num_files +
906
typeinfo_size;
907
resource_table_off = sizeof(IMAGE_OS2_HEADER);
908
resident_name_off = resource_table_off + resource_table_len;
909
resident_name_len = strlen(resident_name) + 4;
910
module_ref_off = resident_name_off + resident_name_len;
911
non_resident_name_off = sizeof(MZ_hdr) + module_ref_off + sizeof(WORD) /* align */;
912
913
fontdir_off = (non_resident_name_off + non_resident_name_len + 15) & ~0xf;
914
font_off = (fontdir_off + fontdir_len + 15) & ~0x0f;
915
916
atexit( cleanup );
917
init_signals( exit_on_signal );
918
919
if (!output_name) /* build a default output name */
920
output_name = strmake( "%s%s", get_basename_noext( input_file ),
921
option_fnt_mode ? ".fnt" : ".fon" );
922
923
init_output_buffer();
924
if (option_fnt_mode)
925
{
926
put_font( info[0] );
927
goto done;
928
}
929
930
put_data(MZ_hdr, sizeof(MZ_hdr));
931
932
/* NE header */
933
put_word( 0x454e ); /* ne_magic */
934
put_byte( 5 ); /* ne_ver */
935
put_byte( 1 ); /* ne_rev */
936
put_word( module_ref_off ); /* ne_enttab */
937
put_word( 0 ); /* ne_cbenttab */
938
put_dword( 0 ); /* ne_crc */
939
put_word( 0x8300 ); /* ne_flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI */
940
put_word( 0 ); /* ne_autodata */
941
put_word( 0 ); /* ne_heap */
942
put_word( 0 ); /* ne_stack */
943
put_dword( 0 ); /* ne_csip */
944
put_dword( 0 ); /* ne_sssp */
945
put_word( 0 ); /* ne_cseg */
946
put_word( 0 ); /* ne_cmod */
947
put_word( non_resident_name_len ); /* ne_cbnrestab */
948
put_word( sizeof(IMAGE_OS2_HEADER) ); /* ne_segtab */
949
put_word( sizeof(IMAGE_OS2_HEADER) ); /* ne_rsrctab */
950
put_word( resident_name_off ); /* ne_restab */
951
put_word( module_ref_off ); /* ne_modtab */
952
put_word( module_ref_off ); /* ne_imptab */
953
put_dword( non_resident_name_off ); /* ne_nrestab */
954
put_word( 0 ); /* ne_cmovent */
955
put_word( 4 ); /* ne_align */
956
put_word( 0 ); /* ne_cres */
957
put_byte( 2 ); /* ne_exetyp = NE_OSFLAGS_WINDOWS */
958
put_byte( 0 ); /* ne_flagsothers */
959
put_word( 0 ); /* ne_pretthunks */
960
put_word( 0 ); /* ne_psegrefbytes */
961
put_word( 0 ); /* ne_swaparea */
962
put_word( 0x400 ); /* ne_expver */
963
964
put_word( 4 ); /* align */
965
966
/* resources */
967
968
put_word( 0x8007 ); /* type_id = NE_RSCTYPE_FONTDIR */
969
put_word( 1 ); /* count */
970
put_dword( 0 ); /* resloader */
971
972
put_word( fontdir_off >> 4 ); /* offset */
973
put_word( (fontdir_len + 15) >> 4 ); /* length */
974
put_word( 0x0050 ); /* flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD */
975
put_word( resident_name_off - sizeof("FONTDIR") - sizeof(IMAGE_OS2_HEADER) ); /* id */
976
put_word( 0 ); /* handle */
977
put_word( 0 ); /* usage */
978
979
put_word( 0x8008 ); /* type_id = NE_RSCTYPE_FONT */
980
put_word( num_files ); /* count */
981
put_dword( 0 ); /* resloader */
982
983
for(res = first_res | 0x8000, i = 0; i < num_files; i++, res++) {
984
int len = (info[i]->hdr.dfSize + 15) & ~0xf;
985
986
put_word( font_off >> 4 ); /* offset */
987
put_word( len >> 4 ); /* length */
988
put_word( 0x1030 ); /* flags = NE_SEGFLAGS_MOVEABLE|NE_SEGFLAGS_SHAREABLE|NE_SEGFLAGS_DISCARDABLE */
989
put_word( res ); /* id */
990
put_word( 0 ); /* handle */
991
put_word( 0 ); /* usage */
992
font_off += len;
993
}
994
995
put_word( 0 ); /* type_id */
996
put_word( 0 ); /* count */
997
put_dword( 0 ); /* resloader */
998
999
put_byte( strlen("FONTDIR") );
1000
put_data( "FONTDIR", strlen("FONTDIR") );
1001
put_byte( strlen(resident_name) );
1002
put_data( resident_name, strlen(resident_name) );
1003
put_byte( 0 );
1004
put_byte( 0 );
1005
put_byte( 0 );
1006
put_byte( 0 );
1007
put_byte( 0 );
1008
put_byte( strlen(non_resident_name) );
1009
put_data( non_resident_name, strlen(non_resident_name) );
1010
put_byte( 0 );
1011
1012
/* empty ne_modtab and ne_imptab */
1013
put_byte( 0 );
1014
put_byte( 0 );
1015
align_output( 16 );
1016
1017
/* FONTDIR resource */
1018
put_word( num_files );
1019
1020
for (i = 0; i < num_files; i++)
1021
{
1022
put_word( first_res + i );
1023
put_fontdir( info[i] );
1024
}
1025
align_output( 16 );
1026
1027
for(i = 0; i < num_files; i++)
1028
{
1029
put_font( info[i] );
1030
align_output( 16 );
1031
}
1032
1033
done:
1034
flush_output_buffer( output_name );
1035
output_name = NULL;
1036
exit(0);
1037
}
1038
1039
#else /* HAVE_FREETYPE */
1040
1041
int main(int argc, char **argv)
1042
{
1043
fprintf( stderr, "%s needs to be built with FreeType support\n", argv[0] );
1044
exit(1);
1045
}
1046
1047
#endif /* HAVE_FREETYPE */
1048
1049