2 * fnttofon. Combine several fnt files in one fon file
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"
47 INT16 dfInternalLeading;
48 INT16 dfExternalLeading;
56 BYTE dfPitchAndFamily;
94 #define NE_FFLAGS_SINGLEDATA 0x0001
95 #define NE_FFLAGS_MULTIPLEDATA 0x0002
96 #define NE_FFLAGS_WIN32 0x0010
97 #define NE_FFLAGS_FRAMEBUF 0x0100
98 #define NE_FFLAGS_CONSOLE 0x0200
99 #define NE_FFLAGS_GUI 0x0300
100 #define NE_FFLAGS_SELFLOAD 0x0800
101 #define NE_FFLAGS_LINKERROR 0x2000
102 #define NE_FFLAGS_CALLWEP 0x4000
103 #define NE_FFLAGS_LIBMODULE 0x8000
105 #define NE_OSFLAGS_WINDOWS 0x02
107 #define NE_RSCTYPE_FONTDIR 0x8007
108 #define NE_RSCTYPE_FONT 0x8008
109 #define NE_RSCTYPE_SCALABLE_FONTPATH 0x80cc
111 #define NE_SEGFLAGS_DATA 0x0001
112 #define NE_SEGFLAGS_ALLOCATED 0x0002
113 #define NE_SEGFLAGS_LOADED 0x0004
114 #define NE_SEGFLAGS_ITERATED 0x0008
115 #define NE_SEGFLAGS_MOVEABLE 0x0010
116 #define NE_SEGFLAGS_SHAREABLE 0x0020
117 #define NE_SEGFLAGS_PRELOAD 0x0040
118 #define NE_SEGFLAGS_EXECUTEONLY 0x0080
119 #define NE_SEGFLAGS_READONLY 0x0080
120 #define NE_SEGFLAGS_RELOC_DATA 0x0100
121 #define NE_SEGFLAGS_SELFLOAD 0x0800
122 #define NE_SEGFLAGS_DISCARDABLE 0x1000
123 #define NE_SEGFLAGS_32BIT 0x2000
129 char dfCopyright[60];
134 static const BYTE MZ_hdr[] = {'M', 'Z', 0x0d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
135 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
138 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
139 'i', 's', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
140 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
141 'm', 'o', 'd', 'e', 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
144 static const char *output_file;
146 static void cleanup_files(void)
148 if (output_file) unlink( output_file );
151 static void exit_on_signal( int sig )
153 exit(1); /* this will call the atexit functions */
156 static void usage(char **argv)
158 fprintf(stderr, "%s fntfiles output.fon\n", argv[0]);
163 #define __attribute__(X)
166 int main(int argc, char **argv)
174 short pt, ver, dpi[2], align, num_files;
175 int resource_table_len, non_resident_name_len, resident_name_len;
176 unsigned short resource_table_off, resident_name_off, module_ref_off, non_resident_name_off, fontdir_off, font_off;
177 char resident_name[200] = "";
179 char non_resident_name[200] = "";
180 int *file_lens, nread;
181 unsigned short first_res = 0x0050, pad, res;
182 struct _fnt_header *fnt_header;
184 IMAGE_OS2_HEADER NE_hdr;
193 num_files = argc - 2;
194 file_lens = malloc(num_files * sizeof(int));
195 for(i = 0; i < num_files; i++) {
196 fp = fopen(argv[i+1], "rb");
198 fprintf(stderr, "error: unable to open %s for reading: %s\n", argv[i+1], strerror(errno));
202 fread(&ver, sizeof(short), 1, fp);
203 if(ver != 0x200 && ver != 0x300) {
204 fprintf(stderr, "error: invalid fnt file %s ver %d\n", argv[i+1], ver);
207 fread(file_lens + i, sizeof(int), 1, fp);
208 fseek(fp, 0x44, SEEK_SET);
209 fread(&pt, sizeof(short), 1, fp);
210 fread(dpi, sizeof(short), 2, fp);
211 fseek(fp, 0x69, SEEK_SET);
212 fread(&off, sizeof(long), 1, fp);
213 fseek(fp, off, SEEK_SET);
215 while((c = fgetc(fp)) != 0 && c != EOF)
218 fprintf(stderr, "%s %d pts %dx%d dpi\n", name, pt, dpi[0], dpi[1]);
220 /* fontdir entries for version 3 fonts are the same as for version 2 */
221 fontdir_len += 0x74 + strlen(name) + 1;
223 sprintf(non_resident_name, "FONTRES 100,%d,%d : %s %d", dpi[0], dpi[1], name, pt);
224 strcpy(resident_name, name);
226 sprintf(non_resident_name + strlen(non_resident_name), ",%d", pt);
230 strcat(non_resident_name, " (VGA res)");
232 strcat(non_resident_name, " (8514 res)");
233 non_resident_name_len = strlen(non_resident_name) + 4;
235 /* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
236 resource_table_len = sizeof(align) + sizeof("FONTDIR") +
237 sizeof(NE_TYPEINFO) + sizeof(NE_NAMEINFO) +
238 sizeof(NE_TYPEINFO) + sizeof(NE_NAMEINFO) * num_files +
240 resource_table_off = sizeof(NE_hdr);
241 resident_name_off = resource_table_off + resource_table_len;
242 resident_name_len = strlen(resident_name) + 4;
243 module_ref_off = resident_name_off + resident_name_len;
244 non_resident_name_off = sizeof(MZ_hdr) + module_ref_off + sizeof(align);
246 memset(&NE_hdr, 0, sizeof(NE_hdr));
247 NE_hdr.ne_magic = 0x454e;
250 NE_hdr.ne_flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI;
251 NE_hdr.ne_cbnrestab = non_resident_name_len;
252 NE_hdr.ne_segtab = sizeof(NE_hdr);
253 NE_hdr.ne_rsrctab = sizeof(NE_hdr);
254 NE_hdr.ne_restab = resident_name_off;
255 NE_hdr.ne_modtab = module_ref_off;
256 NE_hdr.ne_imptab = module_ref_off;
257 NE_hdr.ne_enttab = NE_hdr.ne_modtab;
258 NE_hdr.ne_nrestab = non_resident_name_off;
260 NE_hdr.ne_exetyp = NE_OSFLAGS_WINDOWS;
261 NE_hdr.ne_expver = 0x400;
263 fontdir_off = (non_resident_name_off + non_resident_name_len + 15) & ~0xf;
264 font_off = (fontdir_off + fontdir_len + 15) & ~0x0f;
266 atexit( cleanup_files );
267 signal( SIGTERM, exit_on_signal );
268 signal( SIGINT, exit_on_signal );
270 signal( SIGHUP, exit_on_signal );
273 output_file = argv[argc - 1];
274 ofp = fopen(output_file, "wb");
276 fwrite(MZ_hdr, sizeof(MZ_hdr), 1, ofp);
277 fwrite(&NE_hdr, sizeof(NE_hdr), 1, ofp);
280 fwrite(&align, sizeof(align), 1, ofp);
282 rc_type.type_id = NE_RSCTYPE_FONTDIR;
284 rc_type.resloader = 0;
285 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
287 rc_name.offset = fontdir_off >> 4;
288 rc_name.length = (fontdir_len + 15) >> 4;
289 rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD;
290 rc_name.id = resident_name_off - sizeof("FONTDIR") - NE_hdr.ne_rsrctab;
293 fwrite(&rc_name, sizeof(rc_name), 1, ofp);
295 rc_type.type_id = NE_RSCTYPE_FONT;
296 rc_type.count = num_files;
297 rc_type.resloader = 0;
298 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
300 for(res = first_res | 0x8000, i = 0; i < num_files; i++, res++) {
301 int len = (file_lens[i] + 15) & ~0xf;
303 rc_name.offset = font_off >> 4;
304 rc_name.length = len >> 4;
305 rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_SHAREABLE | NE_SEGFLAGS_DISCARDABLE;
309 fwrite(&rc_name, sizeof(rc_name), 1, ofp);
314 /* empty type info */
315 memset(&rc_type, 0, sizeof(rc_type));
316 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
318 fputc(strlen("FONTDIR"), ofp);
319 fwrite("FONTDIR", strlen("FONTDIR"), 1, ofp);
320 fputc(strlen(resident_name), ofp);
321 fwrite(resident_name, strlen(resident_name), 1, ofp);
323 fputc(0x00, ofp); fputc(0x00, ofp);
325 fputc(0x00, ofp); fputc(0x00, ofp);
327 fputc(strlen(non_resident_name), ofp);
328 fwrite(non_resident_name, strlen(non_resident_name), 1, ofp);
329 fputc(0x00, ofp); /* terminator */
331 /* empty ne_modtab and ne_imptab */
335 pad = ftell(ofp) & 0xf;
338 for(i = 0; i < pad; i++)
341 /* FONTDIR resource */
342 fwrite(&num_files, sizeof(num_files), 1, ofp);
344 for(res = first_res, i = 0; i < num_files; i++, res++) {
345 fp = fopen(argv[i+1], "rb");
347 fwrite(&res, sizeof(res), 1, ofp);
348 fread(buf, 0x72, 1, fp);
350 fnt_header = (struct _fnt_header *)buf;
351 fseek(fp, fnt_header->fi.dfFace, SEEK_SET);
352 fnt_header->fi.dfBitsOffset = 0;
353 fwrite(buf, 0x72, 1, ofp);
356 while((c = fgetc(fp)) != 0 && c != EOF)
359 fwrite(name, strlen(name) + 1, 1, ofp);
363 pad = ftell(ofp) & 0xf;
366 for(i = 0; i < pad; i++)
369 for(res = first_res, i = 0; i < num_files; i++, res++) {
370 fp = fopen(argv[i+1], "rb");
373 nread = read(fileno(fp), buf, sizeof(buf));
375 fwrite(buf, nread, 1, ofp);
378 pad = file_lens[i] & 0xf;
381 for(j = 0; j < pad; j++)