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