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