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