windows.applicationmodel/tests: Use PathRemoveFileSpecW() instead of PathCchRemoveFil...
[wine.git] / dlls / wineps.drv / mkagl.c
blob7c18cbd720d6504f843c32fc854bd08ba91d39ec
1 /*
2 * Copyright 2001 Ian Pilcher
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.
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.
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
19 #include "config.h"
21 #include <sys/types.h>
22 #include <dirent.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <ctype.h>
30 * The array of glyph information
33 typedef struct
35 int UV;
36 int index; /* in PSDRV_AGLGlyphNames */
37 const char *name;
38 const char *comment;
40 } GLYPHINFO;
42 static GLYPHINFO glyphs[1500];
43 static int num_glyphs = 0;
47 * Functions to search and sort the array
50 static int cmp_by_UV(const void *a, const void *b)
52 return ((const GLYPHINFO *)a)->UV - ((const GLYPHINFO *)b)->UV;
55 static int cmp_by_name(const void *a, const void *b)
57 return strcmp(((const GLYPHINFO *)a)->name, ((const GLYPHINFO *)b)->name);
60 static inline void sort_by_UV(void)
62 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_UV);
65 static inline void sort_by_name(void)
67 qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_name);
70 static inline GLYPHINFO *search_by_name(const char *name)
72 GLYPHINFO gi;
74 gi.name = name;
76 return (GLYPHINFO *)bsearch(&gi, glyphs, num_glyphs, sizeof(GLYPHINFO),
77 cmp_by_name);
82 * Use the 'optimal' combination of tabs and spaces to position the cursor
85 static inline void fcpto(FILE *f, int newpos, int curpos)
87 int newtpos = newpos & ~7;
88 int curtpos = curpos & ~7;
90 while (curtpos < newtpos)
92 fputc('\t', f);
93 curtpos += 8;
94 curpos = curtpos;
97 while (curpos < newpos)
99 fputc(' ', f);
100 ++curpos;
105 * Make main() look "purty"
108 static inline void triple_space(FILE *f)
110 fputc('\n', f); fputc('\n', f);
115 * Read the Adobe Glyph List from 'glyphlist.txt'
118 static void read_agl(void)
120 FILE *f = fopen("glyphlist.txt", "r");
121 char linebuf[256], namebuf[128], commbuf[128];
123 if (f == NULL)
125 fprintf(stderr, "Error opening glyphlist.txt\n");
126 exit(__LINE__);
129 while (fgets(linebuf, sizeof(linebuf), f) != NULL)
131 unsigned int UV;
133 if (linebuf[0] == '#')
134 continue;
136 sscanf(linebuf, "%X;%[^;];%[^\n]", &UV, namebuf, commbuf);
138 glyphs[num_glyphs].UV = (int)UV;
139 glyphs[num_glyphs].name = strdup(namebuf);
140 glyphs[num_glyphs].comment = strdup(commbuf);
142 if (glyphs[num_glyphs].name == NULL ||
143 glyphs[num_glyphs].comment == NULL)
145 fprintf(stderr, "Memory allocation failure\n");
146 exit(__LINE__);
149 ++num_glyphs;
152 fclose(f);
154 if (num_glyphs != 1051)
156 fprintf(stderr, "Read %i glyphs\n", num_glyphs);
157 exit(__LINE__);
163 * Read glyph names from all AFM files in current directory
166 static void read_afms(FILE *f_c, FILE *f_h)
168 DIR *d = opendir(".");
169 struct dirent *de;
171 fputs( "/*\n"
172 " * Built-in font metrics\n"
173 " */\n"
174 "\n"
175 "const AFM *const PSDRV_BuiltinAFMs[] =\n"
176 "{\n", f_c);
179 if (d == NULL)
181 fprintf(stderr, "Error opening current directory\n");
182 exit(__LINE__);
185 while ((de = readdir(d)) != NULL)
187 FILE *f;
188 char *cp, linebuf[256], font_family[128];
189 int i, num_metrics;
191 cp = strrchr(de->d_name, '.'); /* Does it end in */
192 if (cp == NULL || stricmp(cp, ".afm") != 0) /* .afm or .AFM? */
193 continue;
195 f = fopen(de->d_name, "r");
196 if (f == NULL)
198 fprintf(stderr, "Error opening %s\n", de->d_name);
199 exit(__LINE__);
202 while (1)
204 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
206 fprintf(stderr, "FontName not found in %s\n", de->d_name);
207 exit(__LINE__);
210 if (strncmp(linebuf, "FontName ", 9) == 0)
211 break;
214 sscanf(linebuf, "FontName %[^\r\n]", font_family);
216 for (i = 0; font_family[i] != '\0'; ++i)
217 if (font_family[i] == '-')
218 font_family[i] = '_';
220 fprintf(f_h, "extern const AFM PSDRV_%s;\n", font_family);
221 fprintf(f_c, " &PSDRV_%s,\n", font_family);
223 while (1)
225 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
227 fprintf(stderr, "FamilyName not found in %s\n", de->d_name);
228 exit(__LINE__);
231 if (strncmp(linebuf, "FamilyName ", 11) == 0)
232 break;
235 sscanf(linebuf, "FamilyName %[^\r\n]", font_family);
237 while (1)
239 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
241 fprintf(stderr, "StartCharMetrics not found in %s\n",
242 de->d_name);
243 exit(__LINE__);
246 if (strncmp(linebuf, "StartCharMetrics ", 17) == 0)
247 break;
250 sscanf(linebuf, "StartCharMetrics %i", &num_metrics);
252 for (i = 0; i < num_metrics; ++i)
254 char namebuf[128];
256 if (fgets(linebuf, sizeof(linebuf), f) == NULL)
258 fprintf(stderr, "Unexpected EOF after %i glyphs in %s\n", i,
259 de->d_name);
260 exit(__LINE__);
263 cp = strchr(linebuf, 'N');
264 if (cp == NULL || strlen(cp) < 3)
266 fprintf(stderr, "Parse error after %i glyphs in %s\n", i,
267 de->d_name);
268 exit(__LINE__);
271 sscanf(cp, "N %s", namebuf);
272 if (search_by_name(namebuf) != NULL)
273 continue;
275 sprintf(linebuf, "FONT FAMILY;%s", font_family);
277 glyphs[num_glyphs].UV = -1;
278 glyphs[num_glyphs].name = strdup(namebuf);
279 glyphs[num_glyphs].comment = strdup(linebuf);
281 if (glyphs[num_glyphs].name == NULL ||
282 glyphs[num_glyphs].comment == NULL)
284 fprintf(stderr, "Memory allocation failure\n");
285 exit(__LINE__);
288 ++num_glyphs;
290 sort_by_name();
293 fclose(f);
296 closedir(d);
298 fputs(" NULL\n};\n", f_c);
303 * Write opening comments, etc.
306 static void write_header(FILE *f)
308 int i;
310 fputc('/', f);
311 for (i = 0; i < 79; ++i)
312 fputc('*', f);
313 fputs("\n"
314 " *\n"
315 " *\tFont and glyph data for the Wine PostScript driver\n"
316 " *\n"
317 " *\tCopyright 2001 Ian Pilcher\n"
318 " *\n"
319 " *\n"
320 " *\tThis data is derived from the Adobe Glyph list at\n"
321 " *\n"
322 " *\t "
323 "http://partners.adobe.com/asn/developer/type/glyphlist.txt\n"
324 " *\n"
325 " *\tand the Adobe Font Metrics files at\n"
326 " *\n"
327 " *\t "
328 "ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/base35/\n"
329 " *\n"
330 " *\twhich are Copyright 1985-1998 Adobe Systems Incorporated.\n"
331 " *\n"
332 " */\n"
333 "\n"
334 "#include \"psdrv.h\"\n"
335 "#include \"data/agl.h\"\n", f);
339 * Write the array of glyph names (also populates indexes)
342 static void write_glyph_names(FILE *f_c, FILE *f_h)
344 int i, num_names = 0, index = 0;
346 for (i = 0; i < num_glyphs; ++i)
347 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
348 ++num_names;
350 fputs( "/*\n"
351 " * Every glyph name in the AGL and the 35 core PostScript fonts\n"
352 " */\n"
353 "\n", f_c);
355 fprintf(f_c, "const INT PSDRV_AGLGlyphNamesSize = %i;\n\n", num_names);
357 fprintf(f_c, "GLYPHNAME PSDRV_AGLGlyphNames[%i] =\n{\n", num_names);
359 for (i = 0; i < num_glyphs - 1; ++i)
361 int cp = 0;
363 if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
365 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
366 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
368 cp = fprintf(f_c, " { %4i, \"%s\" },", index, glyphs[i].name);
369 glyphs[i].index = index;
370 ++index;
372 else
374 glyphs[i].index = glyphs[i - 1].index;
377 fcpto(f_c, 40, cp);
379 fprintf(f_c, "/* %s */\n", glyphs[i].comment);
382 fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
383 fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
385 glyphs[i].index = index;
386 fcpto(f_c, 40, fprintf(f_c, " { %4i, \"%s\" }", index, glyphs[i].name));
387 fprintf(f_c, "/* %s */\n};\n", glyphs[i].comment);
392 * Write the AGL encoding vector, sorted by glyph name
395 static void write_encoding_by_name(FILE *f)
397 int i, size = 0, even = 1;
399 for (i = 0; i < num_glyphs; ++i)
400 if (glyphs[i].UV != -1 &&
401 (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0))
402 ++size; /* should be 1039 */
404 fputs( "/*\n"
405 " * The AGL encoding vector, sorted by glyph name - "
406 "duplicates omitted\n"
407 " */\n"
408 "\n", f);
410 fprintf(f, "const INT PSDRV_AGLbyNameSize = %i;\n\n", size);
411 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyName[%i] =\n{\n", size);
413 for (i = 0; i < num_glyphs - 1; ++i)
415 int cp;
417 if (glyphs[i].UV == -1)
418 continue;
420 if (i != 0 && strcmp(glyphs[i - 1].name, glyphs[i].name) == 0)
421 continue;
423 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
425 even = !even;
426 if (even)
427 fputc('\n', f);
428 else
429 fcpto(f, 40, cp);
432 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
436 * Write the AGL encoding vector, sorted by Unicode value
439 static void write_encoding_by_UV(FILE *f)
441 int i, size = 0, even = 1;
443 for (i = 0; i < num_glyphs; ++i)
444 if (glyphs[i].UV != -1)
445 ++size; /* better be 1051! */
447 sort_by_UV();
449 fputs( "/*\n"
450 " * The AGL encoding vector, sorted by Unicode value - "
451 "duplicates included\n"
452 " */\n"
453 "\n", f);
455 fprintf(f, "const INT PSDRV_AGLbyUVSize = %i;\n\n", size);
456 fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyUV[%i] =\n{\n", size);
458 for (i = 0; i < num_glyphs - 1; ++i)
460 int cp;
462 if (glyphs[i].UV == -1)
463 continue;
465 cp = fprintf(f, " { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
467 even = !even;
468 if (even)
469 fputc('\n', f);
470 else
471 fcpto(f, 40, cp);
474 fprintf(f, " { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
479 * Do it!
482 int main(int argc, char *argv[])
484 FILE *f_c, *f_h;
486 if (argc < 3)
488 fprintf(stderr, "Usage: %s <C file> <header file>\n", argv[0]);
489 exit(__LINE__);
492 f_c = fopen(argv[1], "w");
493 if (f_c == NULL)
495 fprintf(stderr, "Error opening %s for writing\n", argv[1]);
496 exit(__LINE__);
499 f_h = fopen(argv[2], "w");
500 if (f_h == NULL)
502 fprintf(stderr, "Error opening %s for writing\n", argv[2]);
503 exit(__LINE__);
506 write_header(f_c);
507 triple_space(f_c);
508 read_agl();
509 read_afms(f_c, f_h); /* also writes font list */
510 triple_space(f_c);
511 write_glyph_names(f_c, f_h);
512 triple_space(f_c);
513 write_encoding_by_name(f_c);
514 triple_space(f_c);
515 write_encoding_by_UV(f_c);
517 /* Clean up */
518 fclose(f_c);
519 fclose(f_h);
521 return 0;