1 /*
2 * Copyright 2001 Ian Pilcher
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "config.h"
20
21 #include <sys/types.h>
22 #ifdef HAVE_DIRENT_H
23 # include <dirent.h>
24 #endif
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <ctype.h>
29
30
31 /*
32 * The array of glyph information
33 */
34
35 typedef struct
36 {
37 int UV;
38 int index; /* in PSDRV_AGLGlyphNames */
39 const char *name;
40 const char *comment;
41
42 } GLYPHINFO;
43
44 static GLYPHINFO glyphs[1500];
45 static int num_glyphs = 0;
46
47
48 /*
49 * Functions to search and sort the array
50 */
51
52 static int cmp_by_UV(const void *a, const void *b)
53 {
54 return ((const GLYPHINFO *)a)->UV - ((const GLYPHINFO *)b)->UV;
55 }
56
57 static int cmp_by_name(const void *a, const void *b)
58 {
59 return strcmp(((const GLYPHINFO *)a)->name, ((const GLYPHINFO *)b)->name);
60 }
61
62 static inline void sort_by_UV(void)
63 {
64 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_UV);
65 }
66
67 static inline void sort_by_name(void)
68 {
69 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_name);
70 }
71
72 static inline GLYPHINFO *search_by_name(const char *name)
73 {
74 GLYPHINFO gi;
75
76 gi.name = name;
77
78 return (GLYPHINFO *)bsearch(&gi, glyphs, num_glyphs, sizeof(GLYPHINFO),
79 cmp_by_name);
80 }
81
82
83 /*
84 * Use the 'optimal' combination of tabs and spaces to position the cursor
85 */
86
87 static inline void fcpto(FILE *f, int newpos, int curpos)
88 {
89 int newtpos = newpos & ~7;
90 int curtpos = curpos & ~7;
91
92 while (curtpos < newtpos)
93 {
94 fputc('\t', f);
95 curtpos += 8;
96 curpos = curtpos;
97 }
98
99 while (curpos < newpos)
100 {
101 fputc(' ', f);
102 ++curpos;
103 }
104 }
105
106 /*
107 * Make main() look "purty"
108 */
109
110 static inline void triple_space(FILE *f)
111 {
112 fputc('\n', f); fputc('\n', f);
113 }
114
115
116 /*
117 * Read the Adobe Glyph List from 'glyphlist.txt'
118 */
119
120 static void read_agl(void)
121 {
122 FILE *f = fopen("glyphlist.txt", "r");
123 char linebuf[256], namebuf[128], commbuf[128];
124
125 if (f == NULL)
126 {
127 fprintf(stderr, "Error opening glyphlist.txt\n");
128 exit(__LINE__);
129 }
130
131 while (fgets(linebuf, sizeof(linebuf), f) != NULL)
132 {
133 unsigned int UV;
134
135 if (linebuf[0] == '#')
136 continue;
137
138 sscanf(linebuf, "%X;%[^;];%[^\n]", &UV, namebuf, commbuf);
139
140 glyphs[num_glyphs].UV = (int)UV;
141 glyphs[num_glyphs].name = strdup(namebuf);
142 glyphs[num_glyphs].comment = strdup(commbuf);
143
144 if (glyphs[num_glyphs].name == NULL ||
145 glyphs[num_glyphs].comment == NULL)
146 {
147 fprintf(stderr, "Memory allocation failure\n");
148 exit(__LINE__);
149 }
150
151 ++num_glyphs;
152 }
153
154 fclose(f);
155
156 if (num_glyphs != 1051)
157 {
158 fprintf(stderr, "Read %i glyphs\n", num_glyphs);
159 exit(__LINE__);
160 }
161 }
162
163
164 /*
165 * Read glyph names from all AFM files in current directory
166 */
167
168 static void read_afms(FILE *f_c, FILE *f_h)
169 {
170 DIR *d = opendir(".");
171 struct dirent *de;
172
173 fputs( "/*\n"
174 " * Built-in font metrics\n"
175 " */\n"
176 "\n"
177 "const AFM *const PSDRV_BuiltinAFMs[] =\n"
178 "{\n", f_c);
179
180
181 if (d == NULL)
182 {
183 fprintf(stderr, "Error opening current directory\n");
184 exit(__LINE__);
185 }
186
187 while ((de = readdir(d)) != NULL)
188 {
189 FILE *f;
190 char *cp, linebuf[256], font_family[128];
191 int i, num_metrics;
192
193 cp = strrchr(de->d_name, '.'); /* Does it end in */
194 if (cp == NULL || strcasecmp(cp, ".afm") != 0) /* .afm or .AFM? */
195 continue;
196
197 f = fopen(de->d_name, "r");
198 if (f == NULL)
199 {
200 fprintf(stderr, "Error opening %s\n", de->d_name);
201 exit(__LINE__);
202 }
203
204 while (1)
205 {
206 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
207 {
208 fprintf(stderr, "FontName not found in %s\n", de->d_name);
209 exit(__LINE__);
210 }
211
212 if (strncmp(linebuf, "FontName ", 9) == 0)
213 break;
214 }
215
216 sscanf(linebuf, "FontName %[^\r\n]", font_family);
217
218 for (i = 0; font_family[i] != '\0'; ++i)
219 if (font_family[i] == '-')
220 font_family[i] = '_';
221
222 fprintf(f_h, "extern const AFM PSDRV_%s;\n", font_family);
223 fprintf(f_c, " &PSDRV_%s,\n", font_family);
224
225 while (1)
226 {
227 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
228 {
229 fprintf(stderr, "FamilyName not found in %s\n", de->d_name);
230 exit(__LINE__);
231 }
232
233 if (strncmp(linebuf, "FamilyName ", 11) == 0)
234 break;
235 }
236
237 sscanf(linebuf, "FamilyName %[^\r\n]", font_family);
238
239 while (1)
240 {
241 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
242 {
243 fprintf(stderr, "StartCharMetrics not found in %s\n",
244 de->d_name);
245 exit(__LINE__);
246 }
247
248 if (strncmp(linebuf, "StartCharMetrics ", 17) == 0)
249 break;
250 }
251
252 sscanf(linebuf, "StartCharMetrics %i", &num_metrics);
253
254 for (i = 0; i < num_metrics; ++i)
255 {
256 char namebuf[128];
257
258 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
259 {
260 fprintf(stderr, "Unexpected EOF after %i glyphs in %s\n", i,
261 de->d_name);
262 exit(__LINE__);
263 }
264
265 cp = strchr(linebuf, 'N');
266 if (cp == NULL || strlen(cp) < 3)
267 {
268 fprintf(stderr, "Parse error after %i glyphs in %s\n", i,
269 de->d_name);
270 exit(__LINE__);
271 }
272
273 sscanf(cp, "N %s", namebuf);
274 if (search_by_name(namebuf) != NULL)
275 continue;
276
277 sprintf(linebuf, "FONT FAMILY;%s", font_family);
278
279 glyphs[num_glyphs].UV = -1;
280 glyphs[num_glyphs].name = strdup(namebuf);
281 glyphs[num_glyphs].comment = strdup(linebuf);
282
283 if (glyphs[num_glyphs].name == NULL ||
284 glyphs[num_glyphs].comment == NULL)
285 {
286 fprintf(stderr, "Memory allocation failure\n");
287 exit(__LINE__);
288 }
289
290 ++num_glyphs;
291
292 sort_by_name();
293 }
294
295 fclose(f);
296 }
297
298 closedir(d);
299
300 fputs(" NULL\n};\n", f_c);
301 }
302
303
304 /*
305 * Write opening comments, etc.
306 */
307
308 static void write_header(FILE *f)
309 {
310 int i;
311
312 fputc('/', f);
313 for (i = 0; i < 79; ++i)
314 fputc('*', f);
315 fputs("\n"
316 " *\n"
317 " *\tFont and glyph data for the Wine PostScript driver\n"
318 " *\n"
319 " *\tCopyright 2001 Ian Pilcher\n"
320 " *\n"
321 " *\n"
322 " *\tThis data is derived from the Adobe Glyph list at\n"
323 " *\n"
324 " *\t "
325 "http://partners.adobe.com/asn/developer/type/glyphlist.txt\n"
326 " *\n"
327 " *\tand the Adobe Font Metrics files at\n"
328 " *\n"
329 " *\t "
330 "ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/base35/\n"
331 " *\n"
332 " *\twhich are Copyright 1985-1998 Adobe Systems Incorporated.\n"
333 " *\n"
334 " */\n"
335 "\n"
336 "#include \"psdrv.h\"\n"
337 "#include \"data/agl.h\"\n", f);
338 }
339
340 /*
341 * Write the array of glyph names (also populates indexes)
342 */
343
344 static void write_glyph_names(FILE *f_c, FILE *f_h)
345 {
346 int i, num_names = 0, index = 0;
347
348 for (i = 0; i < num_glyphs; ++i)
349 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
350 ++num_names;
351
352 fputs( "/*\n"
353 " * Every glyph name in the AGL and the 35 core PostScript fonts\n"
354 " */\n"
355 "\n", f_c);
356
357 fprintf(f_c, "const INT PSDRV_AGLGlyphNamesSize = %i;\n\n", num_names);
358
359 fprintf(f_c, "GLYPHNAME PSDRV_AGLGlyphNames[%i] =\n{\n", num_names);
360
361 for (i = 0; i < num_glyphs - 1; ++i)
362 {
363 int cp = 0;
364
365 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
366 {
367 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
368 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
369
370 cp = fprintf(f_c, " { %4i, \"%s\" },", index, glyphs[i].name);
371 glyphs[i].index = index;
372 ++index;
373 }
374 else
375 {
376 glyphs[i].index = glyphs[i - 1].index;
377 }
378
379 fcpto(f_c, 40, cp);
380
381 fprintf(f_c, "/* %s */\n", glyphs[i].comment);
382 }
383
384 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
385 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
386
387 glyphs[i].index = index;
388 fcpto(f_c, 40, fprintf(f_c, " { %4i, \"%s\" }", index, glyphs[i].name));
389 fprintf(f_c, "/* %s */\n};\n", glyphs[i].comment);
390 }
391
392
393 /*
394 * Write the AGL encoding vector, sorted by glyph name
395 */
396
397 static void write_encoding_by_name(FILE *f)
398 {
399 int i, size = 0, even = 1;
400
401 for (i = 0; i < num_glyphs; ++i)
402 if (glyphs[i].UV != -1 &&
403 (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0))
404 ++size; /* should be 1039 */
405
406 fputs( "/*\n"
407 " * The AGL encoding vector, sorted by glyph name - "
408 "duplicates omitted\n"
409 " */\n"
410 "\n", f);
411
412 fprintf(f, "const INT PSDRV_AGLbyNameSize = %i;\n\n", size);
413 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyName[%i] =\n{\n", size);
414
415 for (i = 0; i < num_glyphs - 1; ++i)
416 {
417 int cp;
418
419 if (glyphs[i].UV == -1)
420 continue;
421
422 if (i != 0 && strcmp(glyphs[i - 1].name, glyphs[i].name) == 0)
423 continue;
424
425 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
426
427 even = !even;
428 if (even)
429 fputc('\n', f);
430 else
431 fcpto(f, 40, cp);
432 }
433
434 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
435 }
436
437 /*
438 * Write the AGL encoding vector, sorted by Unicode value
439 */
440
441 static void write_encoding_by_UV(FILE *f)
442 {
443 int i, size = 0, even = 1;
444
445 for (i = 0; i < num_glyphs; ++i)
446 if (glyphs[i].UV != -1)
447 ++size; /* better be 1051! */
448
449 sort_by_UV();
450
451 fputs( "/*\n"
452 " * The AGL encoding vector, sorted by Unicode value - "
453 "duplicates included\n"
454 " */\n"
455 "\n", f);
456
457 fprintf(f, "const INT PSDRV_AGLbyUVSize = %i;\n\n", size);
458 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyUV[%i] =\n{\n", size);
459
460 for (i = 0; i < num_glyphs - 1; ++i)
461 {
462 int cp;
463
464 if (glyphs[i].UV == -1)
465 continue;
466
467 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
468
469 even = !even;
470 if (even)
471 fputc('\n', f);
472 else
473 fcpto(f, 40, cp);
474 }
475
476 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
477 }
478
479
480 /*
481 * Do it!
482 */
483
484 int main(int argc, char *argv[])
485 {
486 FILE *f_c, *f_h;
487
488 if (argc < 3)
489 {
490 fprintf(stderr, "Usage: %s <C file> <header file>\n", argv[0]);
491 exit(__LINE__);
492 }
493
494 f_c = fopen(argv[1], "w");
495 if (f_c == NULL)
496 {
497 fprintf(stderr, "Error opening %s for writing\n", argv[1]);
498 exit(__LINE__);
499 }
500
501 f_h = fopen(argv[2], "w");
502 if (f_h == NULL)
503 {
504 fprintf(stderr, "Error opening %s for writing\n", argv[2]);
505 exit(__LINE__);
506 }
507
508 write_header(f_c);
509 triple_space(f_c);
510 read_agl();
511 read_afms(f_c, f_h); /* also writes font list */
512 triple_space(f_c);
513 write_glyph_names(f_c, f_h);
514 triple_space(f_c);
515 write_encoding_by_name(f_c);
516 triple_space(f_c);
517 write_encoding_by_UV(f_c);
518
519 /* Clean up */
520 fclose(f_c);
521 fclose(f_h);
522
523 return 0;
524 }
525
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.