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