WINELIB applications (like reaktivate) might have very long (C++)
[wine/wine-kai.git] / dlls / wineps / mkagl.c
blobcdbe14c9260500c1aefd57ee5374cefb85d42c9b
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>
11 * The array of glyph information
14 typedef struct
16 int UV;
17 int index; /* in PSDRV_AGLGlyphNames */
18 const char *name;
19 const char *comment;
21 } GLYPHINFO;
23 static GLYPHINFO glyphs[1500];
24 static int num_glyphs = 0;
28 * Functions to search and sort the array
31 static int cmp_by_UV(const void *a, const void *b)
33 return ((const GLYPHINFO *)a)->UV - ((const GLYPHINFO *)b)->UV;
36 static int cmp_by_name(const void *a, const void *b)
38 return strcmp(((const GLYPHINFO *)a)->name, ((const GLYPHINFO *)b)->name);
41 inline static void sort_by_UV()
43 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_UV);
46 inline static void sort_by_name()
48 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_name);
51 inline static GLYPHINFO *search_by_name(const char *name)
53 GLYPHINFO gi;
55 gi.name = name;
57 return (GLYPHINFO *)bsearch(&gi, glyphs, num_glyphs, sizeof(GLYPHINFO),
58 cmp_by_name);
63 * Use the 'optimal' combination of tabs and spaces to position the cursor
66 inline static void fcpto(FILE *f, int newpos, int curpos)
68 int newtpos = newpos & ~7;
69 int curtpos = curpos & ~7;
71 while (curtpos < newtpos)
73 fputc('\t', f);
74 curtpos += 8;
75 curpos = curtpos;
78 while (curpos < newpos)
80 fputc(' ', f);
81 ++curpos;
85 inline static void cpto(int newpos, int curpos)
87 fcpto(stdout, newpos, curpos);
92 * Make main() look "purty"
95 inline static void double_space(FILE *f)
97 fputc('\n', f);
100 inline static void triple_space(FILE *f)
102 fputc('\n', f); fputc('\n', f);
107 * Read the Adobe Glyph List from 'glyphlist.txt'
110 static void read_agl()
112 FILE *f = fopen("glyphlist.txt", "r");
113 char linebuf[256], namebuf[128], commbuf[128];
115 if (f == NULL)
117 fprintf(stderr, "Error opening glyphlist.txt\n");
118 exit(__LINE__);
121 while (fgets(linebuf, sizeof(linebuf), f) != NULL)
123 unsigned int UV;
125 if (linebuf[0] == '#')
126 continue;
128 sscanf(linebuf, "%X;%[^;];%[^\n]", &UV, namebuf, commbuf);
130 glyphs[num_glyphs].UV = (int)UV;
131 glyphs[num_glyphs].name = strdup(namebuf);
132 glyphs[num_glyphs].comment = strdup(commbuf);
134 if (glyphs[num_glyphs].name == NULL ||
135 glyphs[num_glyphs].comment == NULL)
137 fprintf(stderr, "Memory allocation failure\n");
138 exit(__LINE__);
141 ++num_glyphs;
144 fclose(f);
146 if (num_glyphs != 1051)
148 fprintf(stderr, "Read %i glyphs\n", num_glyphs);
149 exit(__LINE__);
155 * Read glyph names from all AFM files in current directory
158 static void read_afms(FILE *f_c, FILE *f_h)
160 DIR *d = opendir(".");
161 struct dirent *de;
163 fputs( "/*\n"
164 " * Built-in font metrics\n"
165 " */\n"
166 "\n"
167 "const AFM *const PSDRV_BuiltinAFMs[] =\n"
168 "{\n", f_c);
171 if (d == NULL)
173 fprintf(stderr, "Error opening current directory\n");
174 exit(__LINE__);
177 while ((de = readdir(d)) != NULL)
179 FILE *f;
180 char *cp, linebuf[256], font_family[128];
181 int i, num_metrics;
183 cp = strrchr(de->d_name, '.'); /* Does it end in */
184 if (cp == NULL || strcasecmp(cp, ".afm") != 0) /* .afm or .AFM? */
185 continue;
187 f = fopen(de->d_name, "r");
188 if (f == NULL)
190 fprintf(stderr, "Error opening %s\n", de->d_name);
191 exit(__LINE__);
194 while (1)
196 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
198 fprintf(stderr, "FontName not found in %s\n", de->d_name);
199 exit(__LINE__);
202 if (strncmp(linebuf, "FontName ", 9) == 0)
203 break;
206 sscanf(linebuf, "FontName %[^\r\n]", font_family);
208 for (i = 0; font_family[i] != '\0'; ++i)
209 if (font_family[i] == '-')
210 font_family[i] = '_';
212 fprintf(f_h, "extern const AFM PSDRV_%s;\n", font_family);
213 fprintf(f_c, " &PSDRV_%s,\n", font_family);
215 while (1)
217 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
219 fprintf(stderr, "FamilyName not found in %s\n", de->d_name);
220 exit(__LINE__);
223 if (strncmp(linebuf, "FamilyName ", 11) == 0)
224 break;
227 sscanf(linebuf, "FamilyName %[^\r\n]", font_family);
229 while (1)
231 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
233 fprintf(stderr, "StartCharMetrics not found in %s\n",
234 de->d_name);
235 exit(__LINE__);
238 if (strncmp(linebuf, "StartCharMetrics ", 17) == 0)
239 break;
242 sscanf(linebuf, "StartCharMetrics %i", &num_metrics);
244 for (i = 0; i < num_metrics; ++i)
246 char namebuf[128];
248 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
250 fprintf(stderr, "Unexpected EOF after %i glyphs in %s\n", i,
251 de->d_name);
252 exit(__LINE__);
255 cp = strchr(linebuf, 'N');
256 if (cp == NULL || strlen(cp) < 3)
258 fprintf(stderr, "Parse error after %i glyphs in %s\n", i,
259 de->d_name);
260 exit(__LINE__);
263 sscanf(cp, "N %s", namebuf);
264 if (search_by_name(namebuf) != NULL)
265 continue;
267 sprintf(linebuf, "FONT FAMILY;%s", font_family);
269 glyphs[num_glyphs].UV = -1;
270 glyphs[num_glyphs].name = strdup(namebuf);
271 glyphs[num_glyphs].comment = strdup(linebuf);
273 if (glyphs[num_glyphs].name == NULL ||
274 glyphs[num_glyphs].comment == NULL)
276 fprintf(stderr, "Memory allocation failure\n");
277 exit(__LINE__);
280 ++num_glyphs;
282 sort_by_name();
285 fclose(f);
288 closedir(d);
290 fputs(" NULL\n};\n", f_c);
295 * Write opening comments, etc.
298 static void write_header(FILE *f)
300 int i;
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);
331 * Write the array of glyph names (also populates indexes)
334 static void write_glyph_names(FILE *f_c, FILE *f_h)
336 int i, num_names = 0, index = 0;
338 for (i = 0; i < num_glyphs; ++i)
339 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
340 ++num_names;
342 fputs( "/*\n"
343 " * Every glyph name in the AGL and the 35 core PostScript fonts\n"
344 " */\n"
345 "\n", f_c);
347 fprintf(f_c, "const INT PSDRV_AGLGlyphNamesSize = %i;\n\n", num_names);
349 fprintf(f_c, "GLYPHNAME PSDRV_AGLGlyphNames[%i] =\n{\n", num_names);
351 for (i = 0; i < num_glyphs - 1; ++i)
353 int cp = 0;
355 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
357 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
358 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
360 cp = fprintf(f_c, " { %4i, \"%s\" },", index, glyphs[i].name);
361 glyphs[i].index = index;
362 ++index;
364 else
366 glyphs[i].index = glyphs[i - 1].index;
369 fcpto(f_c, 40, cp);
371 fprintf(f_c, "/* %s */\n", glyphs[i].comment);
374 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
375 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
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);
384 * Write the AGL encoding vector, sorted by glyph name
387 static void write_encoding_by_name(FILE *f)
389 int i, size = 0, even = 1;
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 */
396 fputs( "/*\n"
397 " * The AGL encoding vector, sorted by glyph name - "
398 "duplicates omitted\n"
399 " */\n"
400 "\n", f);
402 fprintf(f, "const INT PSDRV_AGLbyNameSize = %i;\n\n", size);
403 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyName[%i] = \n{\n", size);
405 for (i = 0; i < num_glyphs - 1; ++i)
407 int cp;
409 if (glyphs[i].UV == -1)
410 continue;
412 if (i != 0 && strcmp(glyphs[i - 1].name, glyphs[i].name) == 0)
413 continue;
415 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
417 even = !even;
418 if (even)
419 fputc('\n', f);
420 else
421 fcpto(f, 40, cp);
424 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
428 * Write the AGL encoding vector, sorted by Unicode value
431 static void write_encoding_by_UV(FILE *f)
433 int i, size = 0, even = 1;
435 for (i = 0; i < num_glyphs; ++i)
436 if (glyphs[i].UV != -1)
437 ++size; /* better be 1051! */
439 sort_by_UV();
441 fputs( "/*\n"
442 " * The AGL encoding vector, sorted by Unicode value - "
443 "duplicates included\n"
444 " */\n"
445 "\n", f);
447 fprintf(f, "const INT PSDRV_AGLbyUVSize = %i;\n\n", size);
448 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyUV[%i] = \n{\n", size);
450 for (i = 0; i < num_glyphs - 1; ++i)
452 int cp;
454 if (glyphs[i].UV == -1)
455 continue;
457 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
459 even = !even;
460 if (even)
461 fputc('\n', f);
462 else
463 fcpto(f, 40, cp);
466 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
471 * Do it!
474 int main(int argc, char *argv[])
476 FILE *f_c, *f_h;
478 if (argc < 3)
480 fprintf(stderr, "Usage: %s <C file> <header file>\n", argv[0]);
481 exit(__LINE__);
484 f_c = fopen(argv[1], "w");
485 if (f_c == NULL)
487 fprintf(stderr, "Error opening %s for writing\n", argv[1]);
488 exit(__LINE__);
491 f_h = fopen(argv[2], "w");
492 if (f_h == NULL)
494 fprintf(stderr, "Error opening %s for writing\n", argv[2]);
495 exit(__LINE__);
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);
509 return 0;