mkagl.c 11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * Copyright 2001 Ian Pilcher
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
17 18
 */

19 20
#include "config.h"

21
#include <sys/types.h>
22 23 24
#ifdef HAVE_DIRENT_H
# include <dirent.h>
#endif
25 26 27 28 29 30 31 32 33
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>


/*
 *  The array of glyph information
 */
34

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
typedef struct
{
    int     	UV;
    int     	index;	    	/* in PSDRV_AGLGlyphNames */
    const char	*name;
    const char	*comment;

} GLYPHINFO;

static GLYPHINFO    glyphs[1500];
static int  	    num_glyphs = 0;


/*
 *  Functions to search and sort the array
 */
51

52 53 54 55 56 57 58 59 60 61
static int cmp_by_UV(const void *a, const void *b)
{
    return ((const GLYPHINFO *)a)->UV - ((const GLYPHINFO *)b)->UV;
}

static int cmp_by_name(const void *a, const void *b)
{
    return strcmp(((const GLYPHINFO *)a)->name, ((const GLYPHINFO *)b)->name);
}

62
static inline void sort_by_UV(void)
63 64 65 66
{
    qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_UV);
}

67
static inline void sort_by_name(void)
68 69 70 71
{
    qsort(glyphs, num_glyphs, sizeof(GLYPHINFO), cmp_by_name);
}

72
static inline GLYPHINFO *search_by_name(const char *name)
73 74
{
    GLYPHINFO	gi;
75

76
    gi.name = name;
77

78 79 80 81 82 83 84 85
    return (GLYPHINFO *)bsearch(&gi, glyphs, num_glyphs, sizeof(GLYPHINFO),
    	    cmp_by_name);
}


/*
 *  Use the 'optimal' combination of tabs and spaces to position the cursor
 */
86

87
static inline void fcpto(FILE *f, int newpos, int curpos)
88 89 90
{
    int newtpos = newpos & ~7;
    int curtpos = curpos & ~7;
91

92 93 94 95 96 97
    while (curtpos < newtpos)
    {
    	fputc('\t', f);
	curtpos += 8;
	curpos = curtpos;
    }
98

99 100 101 102 103 104 105 106 107 108
    while (curpos < newpos)
    {
    	fputc(' ', f);
	++curpos;
    }
}

/*
 *  Make main() look "purty"
 */
109

110
static inline void triple_space(FILE *f)
111 112 113 114 115 116 117 118
{
    fputc('\n', f);  fputc('\n', f);
}


/*
 *  Read the Adobe Glyph List from 'glyphlist.txt'
 */
119

120
static void read_agl(void)
121 122 123
{
    FILE    *f = fopen("glyphlist.txt", "r");
    char    linebuf[256], namebuf[128], commbuf[128];
124

125 126 127 128 129
    if (f == NULL)
    {
    	fprintf(stderr, "Error opening glyphlist.txt\n");
	exit(__LINE__);
    }
130

131 132 133
    while (fgets(linebuf, sizeof(linebuf), f) != NULL)
    {
    	unsigned int	UV;
134

135 136
    	if (linebuf[0] == '#')
	    continue;
137

138
    	sscanf(linebuf, "%X;%[^;];%[^\n]", &UV, namebuf, commbuf);
139

140 141 142
	glyphs[num_glyphs].UV = (int)UV;
	glyphs[num_glyphs].name = strdup(namebuf);
	glyphs[num_glyphs].comment = strdup(commbuf);
143

144 145 146 147 148 149
	if (glyphs[num_glyphs].name == NULL ||
	    	glyphs[num_glyphs].comment == NULL)
	{
	    fprintf(stderr, "Memory allocation failure\n");
	    exit(__LINE__);
	}
150

151 152
	++num_glyphs;
    }
153

154
    fclose(f);
155

156 157 158 159 160 161 162 163 164 165 166
    if (num_glyphs != 1051)
    {
    	fprintf(stderr, "Read %i glyphs\n", num_glyphs);
	exit(__LINE__);
    }
}


/*
 *  Read glyph names from all AFM files in current directory
 */
167

168
static void read_afms(FILE *f_c, FILE *f_h)
169 170 171
{
    DIR     	    *d = opendir(".");
    struct dirent   *de;
172

173 174 175 176
    fputs(  "/*\n"
    	    " *  Built-in font metrics\n"
	    " */\n"
	    "\n"
177
	    "const AFM *const PSDRV_BuiltinAFMs[] =\n"
178
	    "{\n", f_c);
179 180


181 182 183 184 185
    if (d == NULL)
    {
    	fprintf(stderr, "Error opening current directory\n");
	exit(__LINE__);
    }
186

187 188 189 190 191
    while ((de = readdir(d)) != NULL)
    {
    	FILE   	*f;
	char   	*cp, linebuf[256], font_family[128];
	int	i, num_metrics;
192

193 194 195
	cp = strrchr(de->d_name, '.');	    	    	/* Does it end in   */
	if (cp == NULL || strcasecmp(cp, ".afm") != 0)	/*   .afm or .AFM?  */
	    continue;
196

197 198 199 200 201 202
	f = fopen(de->d_name, "r");
	if (f == NULL)
	{
	    fprintf(stderr, "Error opening %s\n", de->d_name);
	    exit(__LINE__);
	}
203

204 205 206 207 208 209 210
	while (1)
	{
	    if (fgets(linebuf, sizeof(linebuf), f) == NULL)
	    {
	    	fprintf(stderr, "FontName not found in %s\n", de->d_name);
		exit(__LINE__);
	    }
211

212 213 214
	    if (strncmp(linebuf, "FontName ", 9) == 0)
	    	break;
	}
215

216
	sscanf(linebuf, "FontName %[^\r\n]", font_family);
217

218 219 220
	for (i = 0; font_family[i] != '\0'; ++i)
	    if (font_family[i] == '-')
	    	font_family[i] = '_';
221

222
	fprintf(f_h, "DECLSPEC_HIDDEN extern const AFM PSDRV_%s;\n", font_family);
223
	fprintf(f_c, "    &PSDRV_%s,\n", font_family);
224

225 226 227 228 229 230 231
	while (1)
	{
	    if (fgets(linebuf, sizeof(linebuf), f) == NULL)
	    {
	    	fprintf(stderr, "FamilyName not found in %s\n", de->d_name);
		exit(__LINE__);
	    }
232

233 234 235
	    if (strncmp(linebuf, "FamilyName ", 11) == 0)
	    	break;
	}
236

237
	sscanf(linebuf, "FamilyName %[^\r\n]", font_family);
238

239 240 241 242 243 244 245 246
	while (1)
	{
	    if (fgets(linebuf, sizeof(linebuf), f) == NULL)
	    {
	    	fprintf(stderr, "StartCharMetrics not found in %s\n",
		    	de->d_name);
		exit(__LINE__);
	    }
247

248 249 250
	    if (strncmp(linebuf, "StartCharMetrics ", 17) == 0)
	    	break;
	}
251

252
	sscanf(linebuf, "StartCharMetrics %i", &num_metrics);
253

254 255 256
	for (i = 0; i < num_metrics; ++i)
	{
	    char    namebuf[128];
257

258 259 260 261 262 263
	    if (fgets(linebuf, sizeof(linebuf), f) == NULL)
	    {
	    	fprintf(stderr, "Unexpected EOF after %i glyphs in %s\n", i,
		    	de->d_name);
		exit(__LINE__);
	    }
264

265 266 267 268 269 270 271
	    cp = strchr(linebuf, 'N');
	    if (cp == NULL || strlen(cp) < 3)
	    {
	    	fprintf(stderr, "Parse error after %i glyphs in %s\n", i,
		    	de->d_name);
		exit(__LINE__);
	    }
272

273 274 275
	    sscanf(cp, "N %s", namebuf);
	    if (search_by_name(namebuf) != NULL)
	    	continue;
276

277
	    sprintf(linebuf, "FONT FAMILY;%s", font_family);
278

279 280 281
	    glyphs[num_glyphs].UV = -1;
	    glyphs[num_glyphs].name = strdup(namebuf);
	    glyphs[num_glyphs].comment = strdup(linebuf);
282

283 284 285 286 287 288
	    if (glyphs[num_glyphs].name == NULL ||
	    	    glyphs[num_glyphs].comment == NULL)
	    {
	    	fprintf(stderr, "Memory allocation failure\n");
		exit(__LINE__);
	    }
289

290
	    ++num_glyphs;
291

292 293
	    sort_by_name();
	}
294

295 296
	fclose(f);
    }
297

298
    closedir(d);
299

300
    fputs("    NULL\n};\n", f_c);
301 302 303 304 305 306
}


/*
 *  Write opening comments, etc.
 */
307

308 309 310 311 312 313 314 315 316
static void write_header(FILE *f)
{
    int i;

    fputc('/', f);
    for (i = 0; i < 79; ++i)
    	fputc('*', f);
    fputs("\n"
    	    " *\n"
317
	    " *\tFont and glyph data for the Wine PostScript driver\n"
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    	    " *\n"
	    " *\tCopyright 2001 Ian Pilcher\n"
	    " *\n"
	    " *\n"
	    " *\tThis data is derived from the Adobe Glyph list at\n"
    	    " *\n"
	    " *\t    "
	    "http://partners.adobe.com/asn/developer/type/glyphlist.txt\n"
	    " *\n"
	    " *\tand the Adobe Font Metrics files at\n"
	    " *\n"
	    " *\t    "
	    "ftp://ftp.adobe.com/pub/adobe/type/win/all/afmfiles/base35/\n"
	    " *\n"
	    " *\twhich are Copyright 1985-1998 Adobe Systems Incorporated.\n"
	    " *\n"
	    " */\n"
	    "\n"
336 337
	    "#include \"psdrv.h\"\n"
	    "#include \"data/agl.h\"\n", f);
338 339 340
}

/*
341
 *  Write the array of glyph names (also populates indexes)
342
 */
343

344
static void write_glyph_names(FILE *f_c, FILE *f_h)
345
{
346
    int i, num_names = 0, index = 0;
347

348 349 350
    for (i = 0; i < num_glyphs; ++i)
    	if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
	    ++num_names;
351

352
    fputs(  "/*\n"
353
    	    " *  Every glyph name in the AGL and the 35 core PostScript fonts\n"
354
	    " */\n"
355
	    "\n", f_c);
356

357
    fprintf(f_c, "const INT PSDRV_AGLGlyphNamesSize = %i;\n\n", num_names);
358

359
    fprintf(f_c, "GLYPHNAME PSDRV_AGLGlyphNames[%i] =\n{\n", num_names);
360

361 362 363
    for (i = 0; i < num_glyphs - 1; ++i)
    {
    	int cp = 0;
364

365 366
	if (i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0)
	{
367 368
	    fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
	    fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
369

370
	    cp = fprintf(f_c, "    { %4i, \"%s\" },", index, glyphs[i].name);
371 372 373 374 375
	    glyphs[i].index = index;
	    ++index;
	}
	else
	{
376
	    glyphs[i].index = glyphs[i - 1].index;
377
	}
378

379
	fcpto(f_c, 40, cp);
380

381
	fprintf(f_c, "/* %s */\n", glyphs[i].comment);
382
    }
383

384 385
    fcpto(f_h, 32, fprintf(f_h, "#define GN_%s", glyphs[i].name));
    fprintf(f_h, "(PSDRV_AGLGlyphNames + %i)\n", index);
386

387
    glyphs[i].index = index;
388
    fcpto(f_c, 40, fprintf(f_c, "    { %4i, \"%s\" }", index, glyphs[i].name));
389
    fprintf(f_c, "/* %s */\n};\n", glyphs[i].comment);
390 391 392 393
}


/*
394 395 396 397 398 399
 *  Write the AGL encoding vector, sorted by glyph name
 */

static void write_encoding_by_name(FILE *f)
{
    int i, size = 0, even = 1;
400

401 402 403 404
    for (i = 0; i < num_glyphs; ++i)
    	if (glyphs[i].UV != -1 &&
	    	(i == 0 || strcmp(glyphs[i - 1].name, glyphs[i].name) != 0))
	    ++size; 	    	    /* should be 1039 */
405

406 407 408 409 410
    fputs(  "/*\n"
    	    " *  The AGL encoding vector, sorted by glyph name - "
	    	    "duplicates omitted\n"
	    " */\n"
	    "\n", f);
411

412
    fprintf(f, "const INT PSDRV_AGLbyNameSize = %i;\n\n", size);
413 414
    fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyName[%i] =\n{\n", size);

415 416 417
    for (i = 0; i < num_glyphs - 1; ++i)
    {
    	int cp;
418

419 420
    	if (glyphs[i].UV == -1)
	    continue;
421

422 423
	if (i != 0 && strcmp(glyphs[i - 1].name, glyphs[i].name) == 0)
	    continue;
424

425
    	cp = fprintf(f, "    { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
426

427 428 429 430 431 432
	even = !even;
	if (even)
	    fputc('\n', f);
	else
	    fcpto(f, 40, cp);
    }
433

434 435 436 437 438
    fprintf(f, "    { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
}

/*
 *  Write the AGL encoding vector, sorted by Unicode value
439
 */
440

441
static void write_encoding_by_UV(FILE *f)
442
{
443
    int i, size = 0, even = 1;
444

445 446 447
    for (i = 0; i < num_glyphs; ++i)
    	if (glyphs[i].UV != -1)
	    ++size; 	    	    	/* better be 1051! */
448

449
    sort_by_UV();
450

451
    fputs(  "/*\n"
452 453
    	    " *  The AGL encoding vector, sorted by Unicode value - "
	    	    "duplicates included\n"
454 455
	    " */\n"
	    "\n", f);
456 457

    fprintf(f, "const INT PSDRV_AGLbyUVSize = %i;\n\n", size);
458 459
    fprintf(f, "const UNICODEGLYPH PSDRV_AGLbyUV[%i] =\n{\n", size);

460 461
    for (i = 0; i < num_glyphs - 1; ++i)
    {
462
    	int cp;
463

464 465
    	if (glyphs[i].UV == -1)
	    continue;
466

467
	cp = fprintf(f, "    { 0x%.4x, GN_%s },", glyphs[i].UV, glyphs[i].name);
468

469 470 471 472 473
	even = !even;
	if (even)
	    fputc('\n', f);
	else
	    fcpto(f, 40, cp);
474
    }
475

476
    fprintf(f, "    { 0x%.4x, GN_%s }\n};\n", glyphs[i].UV, glyphs[i].name);
477
}
478

479 480 481 482

/*
 *  Do it!
 */
483

484 485
int main(int argc, char *argv[])
{
486
    FILE    *f_c, *f_h;
487

488
    if (argc < 3)
489
    {
490 491
    	fprintf(stderr, "Usage: %s <C file> <header file>\n", argv[0]);
	exit(__LINE__);
492
    }
493 494 495

    f_c = fopen(argv[1], "w");
    if (f_c == NULL)
496
    {
497 498 499
	fprintf(stderr, "Error opening %s for writing\n", argv[1]);
	exit(__LINE__);
    }
500

501 502 503 504 505
    f_h = fopen(argv[2], "w");
    if (f_h == NULL)
    {
    	fprintf(stderr, "Error opening %s for writing\n", argv[2]);
	exit(__LINE__);
506
    }
507

508 509 510 511 512 513 514 515 516 517
    write_header(f_c);
    triple_space(f_c);
    read_agl();
    read_afms(f_c, f_h);    	    /* also writes font list */
    triple_space(f_c);
    write_glyph_names(f_c, f_h);
    triple_space(f_c);
    write_encoding_by_name(f_c);
    triple_space(f_c);
    write_encoding_by_UV(f_c);
518

519 520
    /* Clean up */
    fclose(f_c);
521
    fclose(f_h);
522

523 524
    return 0;
}