blob: 88c93ade213bea5dc0550b6913e12bf7fdfbbcad [file] [log] [blame]
Huw Davies00acb5f2004-08-17 22:33:14 +00001/*
2 * fnttofon. Combine several fnt files in one fon file
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000021#include "config.h"
Alexandre Julliard49b7fdc2005-08-03 21:25:10 +000022#include "wine/port.h"
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000023
Huw Davies00acb5f2004-08-17 22:33:14 +000024#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000027#ifdef HAVE_UNISTD_H
28# include <unistd.h>
29#endif
30#include <fcntl.h>
31#ifdef HAVE_IO_H
32# include <io.h>
33#endif
Huw Davies00acb5f2004-08-17 22:33:14 +000034
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000035#include "wine/winbase16.h"
36#include "wine/wingdi16.h"
37
38#include "pshpack1.h"
39struct _fnt_header
40{
41 short dfVersion;
42 long dfSize;
43 char dfCopyright[60];
44 FONTINFO16 fi;
45};
46#include "poppack.h"
47
48static const BYTE MZ_hdr[] = {'M', 'Z', 0x0d, 0x01, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
Huw Davies00acb5f2004-08-17 22:33:14 +000049 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
52 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 'T', 'h',
53 'i', 's', ' ', 'P', 'r', 'o', 'g', 'r', 'a', 'm', ' ', 'c', 'a', 'n', 'n', 'o',
54 't', ' ', 'b', 'e', ' ', 'r', 'u', 'n', ' ', 'i', 'n', ' ', 'D', 'O', 'S', ' ',
55 'm', 'o', 'd', 'e', 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
56};
57
Huw Davies00acb5f2004-08-17 22:33:14 +000058static void usage(char **argv)
59{
60 fprintf(stderr, "%s fntfiles output.fon\n", argv[0]);
61 return;
62}
63
Vincent Béron2e5da5f2005-12-07 12:44:17 +010064#ifndef __GNUC__
65#define __attribute__(X)
66#endif
67
68static void error(const char *s, ...) __attribute__((format (printf, 1, 2)));
69
70static void error(const char *s, ...)
71{
72 va_list ap;
73 va_start(ap, s);
74 fprintf(stderr, "Error: ");
75 vfprintf(stderr, s, ap);
76 fprintf(stderr, "\n");
77 va_end(ap);
78 exit(1);
79}
80
Huw Davies00acb5f2004-08-17 22:33:14 +000081int main(int argc, char **argv)
82{
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000083 int i, j;
Huw Davies00acb5f2004-08-17 22:33:14 +000084 FILE *fp, *ofp;
85 long off;
86 char name[200];
87 int c;
88 char *cp;
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000089 short pt, ver, dpi[2], align, num_files;
Huw Davies00acb5f2004-08-17 22:33:14 +000090 int resource_table_len, non_resident_name_len, resident_name_len;
91 unsigned short resource_table_off, resident_name_off, module_ref_off, non_resident_name_off, fontdir_off, font_off;
92 char resident_name[200] = "";
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000093 int fontdir_len = 2;
Huw Davies00acb5f2004-08-17 22:33:14 +000094 char non_resident_name[200] = "";
95 int *file_lens, nread;
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000096 unsigned short first_res = 0x0050, pad, res;
97 struct _fnt_header *fnt_header;
Huw Davies00acb5f2004-08-17 22:33:14 +000098 char buf[0x1000];
Dmitry Timoshkovdace4662005-05-20 09:41:49 +000099 IMAGE_OS2_HEADER NE_hdr;
100 NE_TYPEINFO rc_type;
101 NE_NAMEINFO rc_name;
Huw Davies00acb5f2004-08-17 22:33:14 +0000102
103 if(argc < 3) {
104 usage(argv);
105 exit(1);
106 }
107
108 num_files = argc - 2;
109 file_lens = malloc(num_files * sizeof(int));
110 for(i = 0; i < num_files; i++) {
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000111 fp = fopen(argv[i+1], "rb");
Huw Davies00acb5f2004-08-17 22:33:14 +0000112 if(!fp) {
113 fprintf(stderr, "Can't open %s\n", argv[i+1]);
114 usage(argv);
115 exit(1);
116 }
117 fread(&ver, sizeof(short), 1, fp);
118 if(ver != 0x200 && ver != 0x300) {
Vincent Béron2e5da5f2005-12-07 12:44:17 +0100119 error("invalid fnt file %s ver %d", argv[i+1], ver);
Huw Davies00acb5f2004-08-17 22:33:14 +0000120 }
121 fread(file_lens + i, sizeof(int), 1, fp);
122 fseek(fp, 0x44, SEEK_SET);
123 fread(&pt, sizeof(short), 1, fp);
124 fread(dpi, sizeof(short), 2, fp);
125 fseek(fp, 0x69, SEEK_SET);
126 fread(&off, sizeof(long), 1, fp);
127 fseek(fp, off, SEEK_SET);
128 cp = name;
129 while((c = fgetc(fp)) != 0 && c != EOF)
130 *cp++ = c;
131 *cp = '\0';
132 fprintf(stderr, "%s %d pts %dx%d dpi\n", name, pt, dpi[0], dpi[1]);
133 fclose(fp);
Dmitry Timoshkovac2096d2005-05-23 09:51:12 +0000134 /* fontdir entries for version 3 fonts are the same as for version 2 */
135 fontdir_len += 0x74 + strlen(name) + 1;
Huw Davies00acb5f2004-08-17 22:33:14 +0000136 if(i == 0) {
137 sprintf(non_resident_name, "FONTRES 100,%d,%d : %s %d", dpi[0], dpi[1], name, pt);
138 strcpy(resident_name, name);
139 } else {
140 sprintf(non_resident_name + strlen(non_resident_name), ",%d", pt);
141 }
142 }
143 if(dpi[0] <= 108)
144 strcat(non_resident_name, " (VGA res)");
145 else
146 strcat(non_resident_name, " (8514 res)");
147 non_resident_name_len = strlen(non_resident_name) + 4;
148
149 /* shift count + fontdir entry + num_files of font + nul type + \007FONTDIR */
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000150 resource_table_len = sizeof(align) + sizeof("FONTDIR") +
151 sizeof(NE_TYPEINFO) + sizeof(NE_NAMEINFO) +
152 sizeof(NE_TYPEINFO) + sizeof(NE_NAMEINFO) * num_files +
153 sizeof(NE_TYPEINFO);
154 resource_table_off = sizeof(NE_hdr);
Huw Davies00acb5f2004-08-17 22:33:14 +0000155 resident_name_off = resource_table_off + resource_table_len;
Huw Davies00acb5f2004-08-17 22:33:14 +0000156 resident_name_len = strlen(resident_name) + 4;
157 module_ref_off = resident_name_off + resident_name_len;
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000158 non_resident_name_off = sizeof(MZ_hdr) + module_ref_off + sizeof(align);
159
160 memset(&NE_hdr, 0, sizeof(NE_hdr));
161 NE_hdr.ne_magic = 0x454e;
162 NE_hdr.ne_ver = 5;
163 NE_hdr.ne_rev = 1;
164 NE_hdr.ne_flags = NE_FFLAGS_LIBMODULE | NE_FFLAGS_GUI;
165 NE_hdr.ne_cbnrestab = non_resident_name_len;
166 NE_hdr.ne_segtab = sizeof(NE_hdr);
167 NE_hdr.ne_rsrctab = sizeof(NE_hdr);
168 NE_hdr.ne_restab = resident_name_off;
169 NE_hdr.ne_modtab = module_ref_off;
170 NE_hdr.ne_imptab = module_ref_off;
171 NE_hdr.ne_enttab = NE_hdr.ne_modtab;
172 NE_hdr.ne_nrestab = non_resident_name_off;
173 NE_hdr.ne_align = 4;
174 NE_hdr.ne_exetyp = NE_OSFLAGS_WINDOWS;
175 NE_hdr.ne_expver = 0x400;
Huw Davies00acb5f2004-08-17 22:33:14 +0000176
177 fontdir_off = (non_resident_name_off + non_resident_name_len + 15) & ~0xf;
178 font_off = (fontdir_off + fontdir_len + 15) & ~0x0f;
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000179
180 ofp = fopen(argv[argc - 1], "wb");
181
Huw Davies00acb5f2004-08-17 22:33:14 +0000182 fwrite(MZ_hdr, sizeof(MZ_hdr), 1, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000183 fwrite(&NE_hdr, sizeof(NE_hdr), 1, ofp);
184
185 align = 4;
186 fwrite(&align, sizeof(align), 1, ofp);
187
188 rc_type.type_id = NE_RSCTYPE_FONTDIR;
189 rc_type.count = 1;
190 rc_type.resloader = 0;
191 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
192
193 rc_name.offset = fontdir_off >> 4;
194 rc_name.length = (fontdir_len + 15) >> 4;
195 rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_PRELOAD;
196 rc_name.id = resident_name_off - sizeof("FONTDIR") - NE_hdr.ne_rsrctab;
197 rc_name.handle = 0;
198 rc_name.usage = 0;
199 fwrite(&rc_name, sizeof(rc_name), 1, ofp);
200
201 rc_type.type_id = NE_RSCTYPE_FONT;
202 rc_type.count = num_files;
203 rc_type.resloader = 0;
204 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
205
Huw Davies00acb5f2004-08-17 22:33:14 +0000206 for(res = first_res | 0x8000, i = 0; i < num_files; i++, res++) {
207 int len = (file_lens[i] + 15) & ~0xf;
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000208
209 rc_name.offset = font_off >> 4;
210 rc_name.length = len >> 4;
211 rc_name.flags = NE_SEGFLAGS_MOVEABLE | NE_SEGFLAGS_SHAREABLE | NE_SEGFLAGS_DISCARDABLE;
212 rc_name.id = res;
213 rc_name.handle = 0;
214 rc_name.usage = 0;
215 fwrite(&rc_name, sizeof(rc_name), 1, ofp);
216
Huw Davies00acb5f2004-08-17 22:33:14 +0000217 font_off += len;
Huw Davies00acb5f2004-08-17 22:33:14 +0000218 }
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000219
220 /* empty type info */
221 memset(&rc_type, 0, sizeof(rc_type));
222 fwrite(&rc_type, sizeof(rc_type), 1, ofp);
223
Huw Davies00acb5f2004-08-17 22:33:14 +0000224 fputc(strlen("FONTDIR"), ofp);
225 fwrite("FONTDIR", strlen("FONTDIR"), 1, ofp);
226 fputc(strlen(resident_name), ofp);
227 fwrite(resident_name, strlen(resident_name), 1, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000228
Huw Davies00acb5f2004-08-17 22:33:14 +0000229 fputc(0x00, ofp); fputc(0x00, ofp);
230 fputc(0x00, ofp);
231 fputc(0x00, ofp); fputc(0x00, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000232
Huw Davies00acb5f2004-08-17 22:33:14 +0000233 fputc(strlen(non_resident_name), ofp);
234 fwrite(non_resident_name, strlen(non_resident_name), 1, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000235 fputc(0x00, ofp); /* terminator */
236
237 /* empty ne_modtab and ne_imptab */
Huw Davies00acb5f2004-08-17 22:33:14 +0000238 fputc(0x00, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000239 fputc(0x00, ofp);
240
241 pad = ftell(ofp) & 0xf;
Huw Davies00acb5f2004-08-17 22:33:14 +0000242 if(pad != 0)
243 pad = 0x10 - pad;
244 for(i = 0; i < pad; i++)
245 fputc(0x00, ofp);
246
247 /* FONTDIR resource */
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000248 fwrite(&num_files, sizeof(num_files), 1, ofp);
Huw Davies00acb5f2004-08-17 22:33:14 +0000249
250 for(res = first_res, i = 0; i < num_files; i++, res++) {
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000251 fp = fopen(argv[i+1], "rb");
252
253 fwrite(&res, sizeof(res), 1, ofp);
254 fread(buf, 0x72, 1, fp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000255
256 fnt_header = (struct _fnt_header *)buf;
257 fseek(fp, fnt_header->fi.dfFace, SEEK_SET);
Dmitry Timoshkovac2096d2005-05-23 09:51:12 +0000258 fnt_header->fi.dfBitsOffset = 0;
259 fwrite(buf, 0x72, 1, ofp);
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000260
Huw Davies00acb5f2004-08-17 22:33:14 +0000261 cp = name;
262 while((c = fgetc(fp)) != 0 && c != EOF)
263 *cp++ = c;
264 *cp = '\0';
265 fwrite(name, strlen(name) + 1, 1, ofp);
266 fclose(fp);
267 }
Dmitry Timoshkovac2096d2005-05-23 09:51:12 +0000268
269 pad = ftell(ofp) & 0xf;
Huw Davies00acb5f2004-08-17 22:33:14 +0000270 if(pad != 0)
271 pad = 0x10 - pad;
272 for(i = 0; i < pad; i++)
273 fputc(0x00, ofp);
274
275 for(res = first_res, i = 0; i < num_files; i++, res++) {
Dmitry Timoshkovdace4662005-05-20 09:41:49 +0000276 fp = fopen(argv[i+1], "rb");
277
Huw Davies00acb5f2004-08-17 22:33:14 +0000278 while(1) {
279 nread = read(fileno(fp), buf, sizeof(buf));
280 if(!nread) break;
281 fwrite(buf, nread, 1, ofp);
282 }
283 fclose(fp);
284 pad = file_lens[i] & 0xf;
285 if(pad != 0)
286 pad = 0x10 - pad;
287 for(j = 0; j < pad; j++)
288 fputc(0x00, ofp);
289 }
290 fclose(ofp);
291
292 return 0;
293}