1 /*
2  * Copyright � 1999, 2001 Free Software Foundation, Inc.
3  *
4  * $Id: afm.c,v 1.10 2001/02/13 23:38:05 danny Exp $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this software; see the file COPYING.  If not, write to
18  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 /*
22  * This is Oleo's AFM module.
23  *
24  * Its purpose is to locate and interpret AFM (Adobe Font Metric) files,
25  * and to determine string lengths based on that information.
26  *
27  * This implementation is based on Adobe's document "5004.AFM_Spec.pdf".
28  *
29  * The return value of AfmStringWidth is of course a number that represents
30  * the string's width in points.
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #ifdef	WITH_DMALLOC
38 #include <dmalloc.h>
39 #endif
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <sys/param.h>
46 
47 #include "afm.h"
48 #include "cmd.h"
49 
50 #define	AFM_PATH	"/share/afm"
51 #define	USRLOCAL_PATH	"/usr/local"
52 #define	USR_PATH	"/usr"
53 #define	GS_PATH		"/share/ghostscript/fonts"
54 
55 #define	LINE_LEN	256
56 
57 static char	*CurrentFontName = NULL,
58 		*CurrentFontSlant = NULL;
59 static int	CurrentFontSize = 10;
60 FILE		*fp;
61 
62 struct charmetrics {
63 	unsigned int	code;
64 	char	*name;
65 	int	width;
66 };
67 
68 struct afm {
69 	int			IsFixedPitch, ItalicAngle,
70 				FontBBox1, FontBBox2, FontBBox3, FontBBox4,
71 				UnderlinePosition, UnderlineThickness, CapHeight,
72 				XHeight, Ascender, Descender,
73 				StartCharMetrics;
74 	struct charmetrics *	charMetrics;
75 	int			charIndex[256];
76 };
77 
78 static struct afm *afm = 0;
79 
changed(char * a,char * b)80 static int changed(char *a, char *b)
81 {
82 	if (a == 0 && b == 0)
83 		return 0;
84 	if (a != 0 && b != 0 && strcmp(a, b) == 0)
85 		return 0;
86 	return 1;
87 }
88 
89 static char *Where, *line;
90 
IsCommand(char * literal)91 static int IsCommand(char *literal)
92 {
93 	int	len;
94 
95 	len = strlen(literal);
96 
97 	Where = line + len + 1;
98 
99 	return (strncmp(literal, line, len) == 0);
100 }
101 
Value(void)102 static int Value(void)
103 {
104 	int	v;
105 
106 	while (isspace(*Where))
107 		Where++;
108 	sscanf(Where, "%d", &v);
109 	return v;
110 }
111 
ValueBoolean(void)112 static int ValueBoolean(void)
113 {
114 	while (isspace(*Where))
115 		Where++;
116 	if (strncmp(Where, "True", 4) == 0)
117 		return 1;
118 	if (strncmp(Where, "true", 4) == 0)
119 		return 1;
120 	if (strncmp(Where, "TRUE", 4) == 0)
121 		return 1;
122 	return 0;
123 }
124 
skip(void)125 static void skip(void)
126 {
127 	while (*Where != ';' && *Where != '\n' && *Where != '\0')
128 		Where++;
129 }
130 
namelen(void)131 static int namelen(void)
132 {
133 	char	*p;
134 	int	i;
135 
136 	for (i=0, p=Where; !isspace(*p); i++, p++) ;
137 	return i;
138 }
139 
ReadCharMetrics(int n)140 static void ReadCharMetrics(int n)
141 {
142 	int	i, l;
143 
144 	afm->StartCharMetrics = n;
145 
146 	if (afm->charMetrics)
147 		free(afm->charMetrics);
148 	afm->charMetrics = (struct charmetrics *)calloc(n, sizeof(struct charmetrics));
149 
150 	for (i=0; i<n; i++) {
151 		if (fgets(line, LINE_LEN, fp) == 0)
152 			return;	/* FIX ME */
153 		Where = line;
154 		while (*Where != '\n') {
155 			if (isspace(*Where)) {
156 				Where++;
157 				continue;
158 			}
159 			if (*Where == 'C' && isspace(*(Where+1))) {
160 				afm->charMetrics[i].code = atoi(Where+2);
161 				skip();
162 			} else if (*Where == 'C' && *(Where+1) == 'X' && isspace(*(Where+2))) {
163 				sscanf(Where+3, "%x", &afm->charMetrics[i].code);
164 				skip();
165 			} else if (*Where == 'N' && isspace(*(Where+1))) {
166 				Where += 2;
167 				l = namelen();
168 				afm->charMetrics[i].name = malloc(l+1);
169 				afm->charMetrics[i].name[l] = '\0';
170 				strncpy(afm->charMetrics[i].name, Where, l);
171 				skip();
172 			} else if (*Where == 'W' && *(Where+1) == 'X' && isspace(*(Where+2))) {
173 				afm->charMetrics[i].width = atoi(Where+3);
174 				skip();
175 			} else {
176 				skip();
177 				/* FIX ME */
178 			}
179 
180 			Where++;
181 		}
182 	}
183 }
184 
185 static void
ReadAfmLine(void)186 ReadAfmLine(void)
187 {
188 	if (afm == 0) {
189 		afm = (struct afm *)malloc(sizeof(struct afm));
190 		memset(afm, 0, sizeof(struct afm));
191 	}
192 
193 	if (IsCommand("IsFixedPitch")) afm->IsFixedPitch = ValueBoolean();
194 	if (IsCommand("ItalicAngle")) afm->ItalicAngle = Value();
195 	if (IsCommand("FontBBox"))
196 		sscanf(Where, "%d %d %d %d", &afm->FontBBox1, &afm->FontBBox2,
197 			&afm->FontBBox3, &afm->FontBBox4);
198 	if (IsCommand("StartCharMetrics")) {
199 		int	n = atoi(Where);
200 		ReadCharMetrics(n);
201 	}
202 }
203 
204 char *
GSName(char * name,char * slant)205 GSName(char *name, char *slant)
206 {
207 	if (slant == NULL)
208 		slant = "";
209 
210 	if (strcmp(name, "Courier") == 0 && strcmp(slant, "") == 0)
211 		return "n022003l";	/* NimbusMonL-Regu */
212 	if (strcmp(name, "CGTimes") == 0 && strcmp(slant, "") == 0)
213 		return "n021003l";	/* NimbusRomNo9L-Regu */
214 	return NULL;
215 }
216 
217 FILE *
OpenAfmFile(char * name,char * slant)218 OpenAfmFile(char *name, char *slant)
219 {
220 	FILE	*fp;
221 	char	*fn, *alias;
222 
223 	fn = malloc(MAXPATHLEN);
224 
225 	sprintf(fn, "%s/%s%s.afm", BUILD_PREFIX AFM_PATH, name, slant ? slant : "");
226 	fp = fopen(fn, "r");
227 	if (fp)
228 		return fp;
229 #ifdef	VERBOSE
230 	else
231 		MessageAppend(0, "Failed to open %s\n", fn);
232 #endif
233 
234 	sprintf(fn, "%s/%s%s.afm", USR_PATH GS_PATH, name, slant ? slant : "");
235 	fp = fopen(fn, "r");
236 	if (fp)
237 		return fp;
238 #ifdef	VERBOSE
239 	else
240 		MessageAppend(0, "Failed to open %s\n", fn);
241 #endif
242 
243 	sprintf(fn, "%s/%s%s.afm", USRLOCAL_PATH GS_PATH, name, slant ? slant : "");
244 	fp = fopen(fn, "r");
245 	if (fp)
246 		return fp;
247 #ifdef	VERBOSE
248 	else
249 		MessageAppend(0, "Failed to open %s\n", fn);
250 #endif
251 
252 	if ((alias = GSName(name, slant)) != NULL) {
253 		sprintf(fn, "%s/%s.afm", USR_PATH GS_PATH, alias);
254 		fp = fopen(fn, "r");
255 		if (fp)
256 			return fp;
257 #ifdef	VERBOSE
258 	else
259 		MessageAppend(0, "Failed to open %s\n", fn);
260 #endif
261 		sprintf(fn, "%s/%s.afm", USRLOCAL_PATH GS_PATH, alias);
262 		fp = fopen(fn, "r");
263 		if (fp)
264 			return fp;
265 #ifdef	VERBOSE
266 	else
267 		MessageAppend(0, "Failed to open %s\n", fn);
268 #endif
269 	}
270 
271 	if (fp == 0) {
272 		io_info_msg(PACKAGE ": couldn't open AFM file for %s%s\n", name, slant);
273 		free(fn);
274 		return NULL;
275 	}
276 	free(fn);
277 
278 	return fp;
279 }
280 
281 void
AfmSetFont(char * name,char * slant,int size)282 AfmSetFont(char *name, char *slant, int size)
283 {
284 /* Have the font name/slant changed ? */
285 	CurrentFontSize = size;
286 
287 	if ( ( ! changed(name, CurrentFontName)) &&
288 		( ! changed(slant, CurrentFontSlant)))
289 		return;
290 
291 /*
292  * Something's changed, need to read another file.
293  *
294  * First however remember current state.
295  */
296 	if (CurrentFontName) {
297 		free(CurrentFontName);
298 		CurrentFontName = 0;
299 	}
300 	if (CurrentFontSlant) {
301 		free(CurrentFontSlant);
302 		CurrentFontSlant = 0;
303 	}
304 
305 	if (name)
306 		CurrentFontName = strdup(name);
307 	if (slant)
308 		CurrentFontSlant = strdup(slant);
309 
310 /*
311  * Start reading file.
312  */
313 	fp = OpenAfmFile(name, slant);
314 	if (fp) {
315 		line = malloc(LINE_LEN + 3);
316 
317 		while (fgets(line, LINE_LEN, fp) != NULL) {
318 			ReadAfmLine();
319 		}
320 
321 		fclose(fp);
322 		free(line);
323 	}
324 
325 	AfmSetEncoding("ISOLatin1");
326 }
327 
328 int
AfmFontHeight(void)329 AfmFontHeight(void)
330 {
331 	if (! afm) {
332 		/* FIX ME */
333 		io_info_msg("AfmFontHeight: failed\n");
334 		return 0;
335 	}
336 	return afm->FontBBox4 * CurrentFontSize / 1000;
337 }
338 
339 int
AfmFontWidth(void)340 AfmFontWidth(void)
341 {
342 	if (! afm) {
343 		/* FIX ME */
344 		io_info_msg("AfmFontWidth: failed\n");
345 		return 8;
346 	}
347 	return afm->FontBBox3 * CurrentFontSize / 1000;
348 }
349 
350 int
AfmPitch(void)351 AfmPitch(void)
352 {
353 	float	p;
354 
355 	if (! afm) {
356 		io_info_msg("AfmPitch: failed\n");
357 		return 10;	/* FIX ME this is the fallback value */
358 	}
359 	p = 72.0 * 1000 / (afm->FontBBox3 * CurrentFontSize);
360 	return p;
361 }
362 
363 int
AfmStringWidth(char * s)364 AfmStringWidth(char *s)
365 {
366 	int	r, i, cw;
367 	unsigned int	pc;
368 	char	*p;
369 
370 	if (s == NULL || afm == 0)
371 		return 0;
372 
373 	if (afm->IsFixedPitch)
374 		r = strlen(s) * afm->FontBBox3 * CurrentFontSize / 1000;
375 	else {
376 		if (afm->charMetrics == 0) {
377 			return 0;	/* FIX ME */
378 		}
379 		for (r=0, p=s; *p; p++) {
380 			pc = 255 & *p;
381 			cw = 0;
382 #if 1	/* Use quick access */
383 			if (afm->charIndex[pc] >= 0)
384 				cw = afm->charMetrics[afm->charIndex[pc]].width;
385 #else
386 			for (i=0; cw == 0 && i<afm->StartCharMetrics; i++)
387 				if (afm->charMetrics[i].code == pc) {
388 					cw = afm->charMetrics[i].width;
389 					break;
390 				}
391 #endif
392 			if (cw == 0) {
393 				fprintf(stderr, "Width of char(%c) not found\n", *p);
394 /*				return 0;	*/
395 			}
396 			r += cw;
397 		}
398 		r = r * CurrentFontSize / 1000;
399 	}
400 
401 #if 0
402 	fprintf(stderr, "AfmStringWidth(%s) -> %d\n", s, r);
403 #endif
404 
405 	return r;
406 }
407 
408 static char *IsoLatin1Encoding[256] = {
409 	/* 0x00 */	"non-printable",
410 	/* 0x01 */	"non-printable",
411 	/* 0x02 */	"non-printable",
412 	/* 0x03 */	"non-printable",
413 	/* 0x04 */	"non-printable",
414 	/* 0x05 */	"non-printable",
415 	/* 0x06 */	"non-printable",
416 	/* 0x07 */	"non-printable",
417 	/* 0x08 */	"non-printable",
418 	/* 0x09 */	"non-printable",
419 	/* 0x0a */	"non-printable",
420 	/* 0x0b */	"non-printable",
421 	/* 0x0c */	"non-printable",
422 	/* 0x0d */	"non-printable",
423 	/* 0x0e */	"non-printable",
424 	/* 0x0f */	"non-printable",
425 	/* 0x10 */	"non-printable",
426 	/* 0x11 */	"non-printable",
427 	/* 0x12 */	"non-printable",
428 	/* 0x13 */	"non-printable",
429 	/* 0x14 */	"non-printable",
430 	/* 0x15 */	"non-printable",
431 	/* 0x16 */	"non-printable",
432 	/* 0x17 */	"non-printable",
433 	/* 0x18 */	"non-printable",
434 	/* 0x19 */	"non-printable",
435 	/* 0x1a */	"non-printable",
436 	/* 0x1b */	"non-printable",
437 	/* 0x1c */	"non-printable",
438 	/* 0x1d */	"non-printable",
439 	/* 0x1e */	"non-printable",
440 	/* 0x1f */	"non-printable",
441 	/* 0x20 */	"/space",
442 	/* 0x21 */	"/exclam",
443 	/* 0x22 */	"/quotedbl",
444 	/* 0x23 */	"/numbersign",
445 	/* 0x24 */	"/dollar",
446 	/* 0x25 */	"/percent",
447 	/* 0x26 */	"/ampersand",
448 	/* 0x27 */	"/quoteright",
449 	/* 0x28 */	"/parenleft",
450 	/* 0x29 */	"/parenright",
451 	/* 0x2a */	"/asterisk",
452 	/* 0x2b */	"/plus",
453 	/* 0x2c */	"/comma",
454 	/* 0x2d */	"/hyphen",
455 	/* 0x2e */	"/period",
456 	/* 0x2f */	"/slash",
457 	/* 0x30 */	"/zero",
458 	/* 0x31 */	"/one",
459 	/* 0x32 */	"/two",
460 	/* 0x33 */	"/three",
461 	/* 0x34 */	"/four",
462 	/* 0x35 */	"/five",
463 	/* 0x36 */	"/six",
464 	/* 0x37 */	"/seven",
465 	/* 0x38 */	"/eight",
466 	/* 0x39 */	"/nine",
467 	/* 0x3a */	"/colon",
468 	/* 0x3b */	"/semicolon",
469 	/* 0x3c */	"/less",
470 	/* 0x3d */	"/equal",
471 	/* 0x3e */	"/greater",
472 	/* 0x3f */	"/question",
473 	/* 0x40 */	"/at",
474 	/* 0x41 */	"/A",
475 	/* 0x42 */	"/B",
476 	/* 0x43 */	"/C",
477 	/* 0x44 */	"/D",
478 	/* 0x45 */	"/E",
479 	/* 0x46 */	"/F",
480 	/* 0x47 */	"/G",
481 	/* 0x48 */	"/H",
482 	/* 0x49 */	"/I",
483 	/* 0x4a */	"/J",
484 	/* 0x4b */	"/K",
485 	/* 0x4c */	"/L",
486 	/* 0x4d */	"/M",
487 	/* 0x4e */	"/N",
488 	/* 0x4f */	"/O",
489 	/* 0x50 */	"/P",
490 	/* 0x51 */	"/Q",
491 	/* 0x52 */	"/R",
492 	/* 0x53 */	"/S",
493 	/* 0x54 */	"/T",
494 	/* 0x55 */	"/U",
495 	/* 0x56 */	"/V",
496 	/* 0x57 */	"/W",
497 	/* 0x58 */	"/X",
498 	/* 0x59 */	"/Y",
499 	/* 0x5a */	"/Z",
500 	/* 0x5b */	"/bracketleft",
501 	/* 0x5c */	"/backslash",
502 	/* 0x5d */	"/bracketright",
503 	/* 0x5e */	"/asciicircum",
504 	/* 0x5f */	"/underscore",
505 	/* 0x60 */	"/quoteleft",
506 	/* 0x61 */	"/a",
507 	/* 0x62 */	"/b",
508 	/* 0x63 */	"/c",
509 	/* 0x64 */	"/d",
510 	/* 0x65 */	"/e",
511 	/* 0x66 */	"/f",
512 	/* 0x67 */	"/g",
513 	/* 0x68 */	"/h",
514 	/* 0x69 */	"/i",
515 	/* 0x6a */	"/j",
516 	/* 0x6b */	"/k",
517 	/* 0x6c */	"/l",
518 	/* 0x6d */	"/m",
519 	/* 0x6e */	"/n",
520 	/* 0x6f */	"/o",
521 	/* 0x70 */	"/p",
522 	/* 0x71 */	"/q",
523 	/* 0x72 */	"/r",
524 	/* 0x73 */	"/s",
525 	/* 0x74 */	"/t",
526 	/* 0x75 */	"/u",
527 	/* 0x76 */	"/v",
528 	/* 0x77 */	"/w",
529 	/* 0x78 */	"/x",
530 	/* 0x79 */	"/y",
531 	/* 0x7a */	"/z",
532 	/* 0x7b */	"/braceleft",
533 	/* 0x7c */	"/bar",
534 	/* 0x7d */	"/braceright",
535 	/* 0x7e */	"/tilde",
536 	/* 0x7f */	"non-printable",
537 	/* 0x80 */	"non-printable",
538 	/* 0x81 */	"non-printable",
539 	/* 0x82 */	"non-printable",
540 	/* 0x83 */	"non-printable",
541 	/* 0x84 */	"non-printable",
542 	/* 0x85 */	"non-printable",
543 	/* 0x86 */	"non-printable",
544 	/* 0x87 */	"non-printable",
545 	/* 0x88 */	"non-printable",
546 	/* 0x89 */	"non-printable",
547 	/* 0x8a */	"non-printable",
548 	/* 0x8b */	"non-printable",
549 	/* 0x8c */	"non-printable",
550 	/* 0x8d */	"non-printable",
551 	/* 0x8e */	"non-printable",
552 	/* 0x8f */	"non-printable",
553 	/* 0x90 */	"non-printable",
554 	/* 0x91 */	"non-printable",
555 	/* 0x92 */	"non-printable",
556 	/* 0x93 */	"non-printable",
557 	/* 0x94 */	"non-printable",
558 	/* 0x95 */	"non-printable",
559 	/* 0x96 */	"non-printable",
560 	/* 0x97 */	"non-printable",
561 	/* 0x98 */	"non-printable",
562 	/* 0x99 */	"non-printable",
563 	/* 0x9a */	"non-printable",
564 	/* 0x9b */	"non-printable",
565 	/* 0x9c */	"non-printable",
566 	/* 0x9d */	"non-printable",
567 	/* 0x9e */	"non-printable",
568 	/* 0x9f */	"non-printable",
569 	/* 0xa0 */	"/space",
570 	/* 0xa1 */	"/exclamdown",
571 	/* 0xa2 */	"/cent",
572 	/* 0xa3 */	"/sterling",
573 	/* 0xa4 */	"/currency",
574 	/* 0xa5 */	"/yen",
575 	/* 0xa6 */	"/brokenbar",
576 	/* 0xa7 */	"/section",
577 	/* 0xa8 */	"/dieresis",
578 	/* 0xa9 */	"/copyright",
579 	/* 0xaa */	"/ordfeminine",
580 	/* 0xab */	"/guillemotleft",
581 	/* 0xac */	"/logicalnot",
582 	/* 0xad */	"/hyphen",
583 	/* 0xae */	"/registered",
584 	/* 0xaf */	"/macron",
585 	/* 0xb0 */	"/degree",
586 	/* 0xb1 */	"/plusminus",
587 	/* 0xb2 */	"/twosuperior",
588 	/* 0xb3 */	"/threesuperior",
589 	/* 0xb4 */	"/acute",
590 	/* 0xb5 */	"/mu",
591 	/* 0xb6 */	"/paragraph",
592 	/* 0xb7 */	"/bullet",
593 	/* 0xb8 */	"/cedilla",
594 	/* 0xb9 */	"/dotlessi",
595 	/* 0xba */	"/ordmasculine",
596 	/* 0xbb */	"/guillemotright",
597 	/* 0xbc */	"/onequarter",
598 	/* 0xbd */	"/onehalf",
599 	/* 0xbe */	"/threequarters",
600 	/* 0xbf */	"/questiondown",
601 	/* 0xc0 */	"/Agrave",
602 	/* 0xc1 */	"/Aacute",
603 	/* 0xc2 */	"/Acircumflex",
604 	/* 0xc3 */	"/Atilde",
605 	/* 0xc4 */	"/Adieresis",
606 	/* 0xc5 */	"/Aring",
607 	/* 0xc6 */	"/AE",
608 	/* 0xc7 */	"/Ccedilla",
609 	/* 0xc8 */	"/Egrave",
610 	/* 0xc9 */	"/Eacute",
611 	/* 0xca */	"/Ecircumflex",
612 	/* 0xcb */	"/Edieresis",
613 	/* 0xcc */	"/Igrave",
614 	/* 0xcd */	"/Iacute",
615 	/* 0xce */	"/Icircumflex",
616 	/* 0xcf */	"/Idieresis",
617 	/* 0xd0 */	"/Eth",
618 	/* 0xd1 */	"/Ntilde",
619 	/* 0xd2 */	"/Ograve",
620 	/* 0xd3 */	"/Oacute",
621 	/* 0xd4 */	"/Ocircumflex",
622 	/* 0xd5 */	"/Otilde",
623 	/* 0xd6 */	"/Odieresis",
624 	/* 0xd7 */	"/multiply",
625 	/* 0xd8 */	"/Oslash",
626 	/* 0xd9 */	"/Ugrave",
627 	/* 0xda */	"/Uacute",
628 	/* 0xdb */	"/Ucircumflex",
629 	/* 0xdc */	"/Udieresis",
630 	/* 0xdd */	"/Yacute",
631 	/* 0xde */	"/Thorn",
632 	/* 0xdf */	"/germandbls",
633 	/* 0xe0 */	"/agrave",
634 	/* 0xe1 */	"/aacute",
635 	/* 0xe2 */	"/acircumflex",
636 	/* 0xe3 */	"/atilde",
637 	/* 0xe4 */	"/adieresis",
638 	/* 0xe5 */	"/aring",
639 	/* 0xe6 */	"/ae",
640 	/* 0xe7 */	"/ccedilla",
641 	/* 0xe8 */	"/egrave",
642 	/* 0xe9 */	"/eacute",
643 	/* 0xea */	"/ecircumflex",
644 	/* 0xeb */	"/edieresis",
645 	/* 0xec */	"/igrave",
646 	/* 0xed */	"/iacute",
647 	/* 0xee */	"/icircumflex",
648 	/* 0xef */	"/idieresis",
649 	/* 0xf0 */	"/eth",
650 	/* 0xf1 */	"/ntilde",
651 	/* 0xf2 */	"/ograve",
652 	/* 0xf3 */	"/oacute",
653 	/* 0xf4 */	"/ocircumflex",
654 	/* 0xf5 */	"/otilde",
655 	/* 0xf6 */	"/odieresis",
656 	/* 0xf7 */	"/divide",
657 	/* 0xf8 */	"/oslash",
658 	/* 0xf9 */	"/ugrave",
659 	/* 0xfa */	"/uacute",
660 	/* 0xfb */	"/ucircumflex",
661 	/* 0xfc */	"/udieresis",
662 	/* 0xfd */	"/yacute",
663 	/* 0xfe */	"/thorn",
664 	/* 0xff */	"/ydieresis"
665 };
666 
667 /*
668  * Process the encoding
669  */
670 static void
DoEncoding(void)671 DoEncoding(void)
672 {
673 	int	i, j;
674 
675 	if (! afm)
676 		return;
677 
678 	for (i=0; i<afm->StartCharMetrics; i++) {
679 		afm->charMetrics[i].code = -1;
680 
681 		for (j=0; j<256; j++) {
682 			if (strcmp(IsoLatin1Encoding[j] + 1, afm->charMetrics[i].name) == 0) {
683 				afm->charMetrics[i].code = j;
684 				break;
685 			}
686 		}
687 	}
688 
689 	/* Build the quick access */
690 	for (i=0; i<256; i++)
691 		afm->charIndex[i] = -1;
692 	for (i=0; i<afm->StartCharMetrics; i++)
693 		if (afm->charMetrics[i].code > 0 && afm->charMetrics[i].code < 256)
694 			afm->charIndex[afm->charMetrics[i].code] = i;
695 }
696 
697 void
AfmSetEncoding(const char * enc)698 AfmSetEncoding(const char *enc)
699 {
700 #if 0
701 	fprintf(stderr, "AfmSetEncoding(%s)\n", enc);
702 #endif
703 	DoEncoding();
704 
705 	/* FIX ME */
706 }
707