afm.c - enscript - GNU Enscript
(HTM) git clone git://thinkerwim.org/enscript.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
afm.c (19635B)
---
1 /*
2 * AFM library public interface.
3 * Copyright (c) 1995-1999 Markku Rossi.
4 *
5 * Author: Markku Rossi <mtr@iki.fi>
6 */
7
8 /*
9 * Enscript is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Enscript is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Enscript. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "afmint.h"
24 #include "afm.h"
25
26 /*
27 * Static variables
28 */
29
30 static char *default_path = "/usr/local/lib/ps:/usr/lib/ps";
31
32 static char *error_names[] =
33 {
34 "AFM Success",
35 "AFM Error",
36 "out of memory",
37 "illegal argument",
38 "unknown font",
39 "syntax error",
40 "unsupported format",
41 "file IO failed",
42 "file is not an AFM file",
43 };
44
45 /*
46 * Prototypes for static functions.
47 */
48
49 static void read_font_map ___P ((AFMHandle handle, char *name));
50 static void apply_encoding ___P ((AFMFont font, AFMEncodingTable *enc,
51 unsigned int flags));
52
53
54 /*
55 * Global functions.
56 */
57
58 void
59 afm_error_to_string (AFMError error, char *buf)
60 {
61 char *syserr;
62 int code, syserrno;
63
64 code = error & 0xffff;
65 syserrno = (error >> 16) & 0xffff;
66
67 if (syserrno)
68 syserr = strerror (syserrno);
69 else
70 syserr = NULL;
71
72 if (code >= NUM_ERRORS)
73 {
74 sprintf (buf, "afm_error_to_string(): illegal error code: %d\n",
75 error);
76 return;
77 }
78
79 if (code == 0)
80 sprintf (buf, "AFM Success");
81 else if (code == 1)
82 sprintf (buf, "%s%s%s", "AFM Error",
83 syserr ? ":" : "",
84 syserr ? syserr : "");
85 else
86 sprintf (buf, "AFM Error: %s%s%s", error_names[code],
87 syserr ? ": " : "",
88 syserr ? syserr : "");
89 }
90
91
92 AFMError
93 afm_create (const char *path, unsigned int verbose_level,
94 AFMHandle *handle_return)
95 {
96 AFMHandle handle;
97 AFMError error = AFM_SUCCESS;
98 const char *cp, *cp2;
99 int len;
100 char buf[512];
101 struct stat stat_st;
102
103 /* Init handle. */
104
105 handle = (AFMHandle) calloc (1, sizeof (*handle));
106 if (handle == NULL)
107 {
108 error = AFM_ERROR_MEMORY;
109 goto error_out;
110 }
111
112 handle->font_map = strhash_init ();
113 if (handle->font_map == NULL)
114 {
115 error = AFM_ERROR_MEMORY;
116 goto error_out;
117 }
118
119 handle->verbose = verbose_level;
120
121 /* Traverse path. */
122
123 if (path == NULL)
124 path = default_path;
125
126 afm_message (handle, 1, "AFM: scanning path...\n");
127 for (cp = path; cp; cp = strchr (cp, PATH_SEPARATOR))
128 {
129 if (cp != path)
130 cp++;
131
132 cp2 = strchr (cp, PATH_SEPARATOR);
133 if (cp2)
134 len = cp2 - cp;
135 else
136 len = strlen (cp);
137
138 memcpy (buf, cp, len);
139 buf[len] = '\0';
140 if (len > 0 && buf[len - 1] == '/')
141 buf[len - 1] = '\0';
142
143 strcat (buf, "/font.map");
144
145 if (stat (buf, &stat_st) == 0)
146 read_font_map (handle, buf);
147 }
148
149 *handle_return = handle;
150
151 return AFM_SUCCESS;
152
153
154 /* Error handling. */
155
156 error_out:
157
158 (void) afm_destroy (handle);
159
160 return error;
161 }
162
163
164 AFMError
165 afm_destroy (AFMHandle handle)
166 {
167 char *key;
168 int keylen;
169 char *cp;
170
171 if (handle == NULL)
172 return AFM_ERROR_ARGUMENT;
173
174 /* Free filenames. */
175 while (strhash_get_first (handle->font_map, &key, &keylen, (void *) &cp))
176 free (cp);
177
178 strhash_free (handle->font_map);
179 free (handle);
180
181 return AFM_SUCCESS;
182 }
183
184
185 AFMError
186 afm_set_verbose (AFMHandle handle, unsigned int level)
187 {
188 if (handle == NULL)
189 return AFM_ERROR_ARGUMENT;
190
191 handle->verbose = level;
192
193 return AFM_SUCCESS;
194 }
195
196
197 AFMError
198 afm_font_prefix (AFMHandle handle, const char *fontname,
199 const char **prefix_return)
200 {
201 char *filename;
202
203 if (handle == NULL || fontname == NULL || prefix_return == NULL)
204 return AFM_ERROR_ARGUMENT;
205
206 /* Lookup font. */
207 if (!strhash_get (handle->font_map, fontname, strlen (fontname),
208 (void *) &filename))
209 return AFM_ERROR_UNKNOWN_FONT;
210
211 *prefix_return = filename;
212
213 return AFM_SUCCESS;
214 }
215
216
217 AFMError
218 afm_open_font (AFMHandle handle, unsigned int info_level,
219 const char *fontname, AFMFont *font_return)
220 {
221 char *filename;
222 char fname[512];
223
224 if (handle == NULL || fontname == NULL)
225 return AFM_ERROR_ARGUMENT;
226
227 /* Lookup font. */
228 if (!strhash_get (handle->font_map, fontname, strlen (fontname),
229 (void *) &filename))
230 return AFM_ERROR_UNKNOWN_FONT;
231
232 /* Append suffix to the filename. */
233 sprintf (fname, "%s.afm", filename);
234
235 return afm_open_file (handle, info_level, fname, font_return);
236 }
237
238
239 AFMError
240 afm_open_file (AFMHandle handle, unsigned int info_level,
241 const char *filename, AFMFont *font_return)
242 {
243 AFMFont font;
244 AFMError error = AFM_SUCCESS;
245
246 if (handle == NULL || filename == NULL)
247 return AFM_ERROR_ARGUMENT;
248
249 font = (AFMFont) calloc (1, sizeof (*font));
250 if (font == NULL)
251 return AFM_ERROR_MEMORY;
252
253 font->private
254 = (struct afm_font_private_data_st *) calloc (1, sizeof (*font->private));
255 if (font->private == NULL)
256 {
257 error = AFM_ERROR_MEMORY;
258 goto error_out;
259 }
260 font->private->fontnames = strhash_init ();
261 if (font->private->fontnames == NULL)
262 {
263 error = AFM_ERROR_MEMORY;
264 goto error_out;
265 }
266
267 font->private->compositenames = strhash_init ();
268 if (font->private->compositenames == NULL)
269 {
270 error = AFM_ERROR_MEMORY;
271 goto error_out;
272 }
273
274 font->info_level = info_level;
275
276 /* Parse file. */
277 if (setjmp (handle->jmpbuf))
278 {
279 /* Error during parse. */
280 error = handle->parse_error;
281 goto error_out;
282 }
283 else
284 {
285 afm_parse_file (handle, filename, font);
286 /* Parse successful. */
287 }
288
289 *font_return = font;
290 return AFM_SUCCESS;
291
292
293 /* Error handling. */
294
295 error_out:
296
297 (void) afm_close_font (font);
298
299 return error;
300 }
301
302
303 #define FREE(ptr) if (ptr) free (ptr)
304 AFMError
305 afm_close_font (AFMFont font)
306 {
307 int i;
308
309 if (font == NULL)
310 return AFM_ERROR_ARGUMENT;
311
312 /* Global info. */
313 FREE (font->global_info.FontName);
314 FREE (font->global_info.FullName);
315 FREE (font->global_info.FamilyName);
316 FREE (font->global_info.Weight);
317 FREE (font->global_info.Version);
318 FREE (font->global_info.Notice);
319 FREE (font->global_info.EncodingScheme);
320 FREE (font->global_info.CharacterSet);
321
322 /* Character metrics. */
323 for (i = 0; i < font->num_character_metrics; i++)
324 FREE (font->character_metrics[i].name);
325 FREE (font->character_metrics);
326
327 /* Composites. */
328 for (i = 0; i < font->num_composites; i++)
329 FREE (font->composites[i].name);
330 FREE (font->composites);
331
332 /* Kern pairs. */
333 for (i = 0; i < font->num_kern_pairs; i++)
334 {
335 FREE (font->kern_pairs[i].name1);
336 FREE (font->kern_pairs[i].name2);
337 }
338 FREE (font->kern_pairs);
339
340 /* Track kern. */
341 FREE (font->track_kerns);
342
343 /* Private data. */
344 strhash_free (font->private->fontnames);
345 strhash_free (font->private->compositenames);
346
347 free (font);
348
349 return AFM_SUCCESS;
350 }
351
352
353 #define STR(str) (str ? str : "")
354 #define BOOL(val) (val ? "true" : "false")
355 void
356 afm_font_dump (FILE *fp, AFMFont font)
357 {
358 int i;
359
360 fprintf (fp, "AFM Format Specification version: %g\n", font->version);
361 fprintf (fp, "Global Font Information\n");
362 fprintf (fp, " FontName:\t%s\n", STR (font->global_info.FontName));
363 fprintf (fp, " FullName:\t%s\n", STR (font->global_info.FullName));
364 fprintf (fp, " FamilyName:\t%s\n", STR (font->global_info.FamilyName));
365 fprintf (fp, " Weight:\t%s\n", STR (font->global_info.Weight));
366 fprintf (fp, " FontBBox:\t%g %g %g %g\n",
367 font->global_info.FontBBox_llx, font->global_info.FontBBox_lly,
368 font->global_info.FontBBox_urx, font->global_info.FontBBox_ury);
369 fprintf (fp, " Version:\t%s\n", STR (font->global_info.Version));
370 fprintf (fp, " Notice:\t%s\n", STR (font->global_info.Notice));
371 fprintf (fp, " EncodingScheme:\t%s\n",
372 STR (font->global_info.EncodingScheme));
373 fprintf (fp, " MappingScheme:\t%ld\n", font->global_info.MappingScheme);
374 fprintf (fp, " EscChar:\t%ld\n", font->global_info.EscChar);
375 fprintf (fp, " CharacterSet:\t%s\n", STR (font->global_info.CharacterSet));
376 fprintf (fp, " Characters:\t%ld\n", font->global_info.Characters);
377 fprintf (fp, " IsBaseFont:\t%s\n", BOOL(font->global_info.IsBaseFont));
378 fprintf (fp, " VVector:\t%g %g\n",
379 font->global_info.VVector_0, font->global_info.VVector_1);
380 fprintf (fp, " IsFixedV:\t%s\n", BOOL(font->global_info.IsFixedV));
381 fprintf (fp, " CapHeight:\t%g\n", font->global_info.CapHeight);
382 fprintf (fp, " XHeight:\t%g\n", font->global_info.XHeight);
383 fprintf (fp, " Ascender:\t%g\n", font->global_info.Ascender);
384 fprintf (fp, " Descender:\t%g\n", font->global_info.Descender);
385
386 for (i = 0; i < 2; i++)
387 if (font->writing_direction_metrics[i].is_valid)
388 {
389 fprintf (fp, "Writing Direction %d\n", i);
390 fprintf (fp, " UnderlinePosition: %g\n",
391 font->writing_direction_metrics[i].UnderlinePosition);
392 fprintf (fp, " UnderlineThickness: %g\n",
393 font->writing_direction_metrics[i].UnderlineThickness);
394 fprintf (fp, " ItalicAngle: %g\n",
395 font->writing_direction_metrics[i].ItalicAngle);
396 fprintf (fp, " CharWidth: %g %g\n",
397 font->writing_direction_metrics[i].CharWidth_x,
398 font->writing_direction_metrics[i].CharWidth_y);
399 fprintf (fp, " IsFixedPitch: %s\n",
400 BOOL (font->writing_direction_metrics[i].IsFixedPitch));
401 }
402
403 /* Individual Character Metrics. */
404 fprintf (fp, "Individual Character Metrics %ld\n",
405 font->num_character_metrics);
406 for (i = 0; i < font->num_character_metrics; i++)
407 {
408 AFMIndividualCharacterMetrics *cm;
409 cm = &font->character_metrics[i];
410
411 fprintf (fp, " C %ld ; N %s ; B %g %g %g %g\n",
412 cm->character_code, STR (cm->name),
413 cm->llx, cm->lly, cm->urx, cm->ury);
414 fprintf (fp,
415 " W0X %g ; W0Y %g ; W1X %g ; W1Y %g ; VV %g %g\n",
416 cm->w0x, cm->w0y, cm->w1x, cm->w1y, cm->vv_x, cm->vv_y);
417 }
418
419 /* Composite Character Data. */
420 fprintf (fp, "Composite Character Data %ld\n", font->num_composites);
421 for (i = 0; i < font->num_composites; i++)
422 {
423 AFMComposite *cm;
424 int j;
425
426 cm = &font->composites[i];
427
428 fprintf (fp, " CC %s %ld", cm->name, cm->num_components);
429 for (j = 0; j < cm->num_components; j++)
430 fprintf (fp, " ; PCC %s %g %g",
431 cm->components[j].name,
432 cm->components[j].deltax,
433 cm->components[j].deltay);
434 fprintf (fp, "\n");
435 }
436
437 /* Kern pairs. */
438 fprintf (fp, "Pair-Wise Kerning %ld\n", font->num_kern_pairs);
439 for (i = 0; i < font->num_kern_pairs; i++)
440 {
441 AFMPairWiseKerning *kp;
442 kp = &font->kern_pairs[i];
443
444 fprintf (fp, " KP %s %s %g %g\n", STR (kp->name1), STR (kp->name2),
445 kp->kx, kp->ky);
446 }
447
448 fprintf (fp, "Track Kerning %ld\n", font->num_track_kerns);
449 for (i = 0; i < font->num_track_kerns; i++)
450 {
451 AFMTrackKern *tk;
452 tk = &font->track_kerns[i];
453
454 fprintf (fp, " TrackKern %ld %g %g %g %g\n", tk->degree,
455 tk->min_ptsize, tk->min_kern,
456 tk->max_ptsize, tk->max_kern);
457 }
458 }
459
460
461 AFMError
462 afm_font_stringwidth (AFMFont font, AFMNumber ptsize, char *string,
463 unsigned int stringlen, AFMNumber *w0x_return,
464 AFMNumber *w0y_return)
465 {
466 unsigned int i;
467 AFMNumber x = 0.0;
468 AFMNumber y = 0.0;
469 AFMIndividualCharacterMetrics *cm;
470
471 if (!font || !string || !font->writing_direction_metrics[0].is_valid)
472 return AFM_ERROR_ARGUMENT;
473
474 /* Check shortcut. */
475 if (font->writing_direction_metrics[0].IsFixedPitch)
476 {
477 /* This is the easy case. */
478 x = stringlen * font->writing_direction_metrics[0].CharWidth_x;
479 y = stringlen * font->writing_direction_metrics[0].CharWidth_y;
480 }
481 else
482 {
483 /* Count character by character. */
484 for (i = 0; i < stringlen; i++)
485 {
486 cm = font->encoding[(unsigned char) string[i]];
487 if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
488 {
489 /* Use the undef font. */
490 x += font->private->undef->w0x;
491 y += font->private->undef->w0y;
492 }
493 else
494 {
495 /* Font found and valid, take values. */
496 x += cm->w0x;
497 y += cm->w0y;
498 }
499 }
500 }
501
502 *w0x_return = x / UNITS_PER_POINT * ptsize;
503 *w0y_return = y / UNITS_PER_POINT * ptsize;
504
505 return AFM_SUCCESS;
506 }
507
508
509 AFMError
510 afm_font_charwidth (AFMFont font, AFMNumber ptsize, char ch,
511 AFMNumber *w0x_return, AFMNumber *w0y_return)
512 {
513 AFMNumber x = 0.0;
514 AFMNumber y = 0.0;
515 AFMIndividualCharacterMetrics *cm;
516
517 if (!font || !font->writing_direction_metrics[0].is_valid)
518 return AFM_ERROR_ARGUMENT;
519
520 /* Check shortcut. */
521 if (font->writing_direction_metrics[0].IsFixedPitch)
522 {
523 x = font->writing_direction_metrics[0].CharWidth_x;
524 y = font->writing_direction_metrics[0].CharWidth_y;
525 }
526 else
527 {
528 cm = font->encoding[(unsigned char) ch];
529 if (cm == AFM_ENC_NONE || cm == AFM_ENC_NON_EXISTENT)
530 {
531 /* Use the undef font. */
532 x = font->private->undef->w0x;
533 y = font->private->undef->w0y;
534 }
535 else
536 {
537 /* Font found and valid, take values. */
538 x = cm->w0x;
539 y = cm->w0y;
540 }
541 }
542
543 *w0x_return = x / UNITS_PER_POINT * ptsize;
544 *w0y_return = y / UNITS_PER_POINT * ptsize;
545
546 return AFM_SUCCESS;
547 }
548
549
550 AFMError
551 afm_font_encode (AFMFont font, unsigned char code, char *name,
552 unsigned int flags)
553 {
554 AFMIndividualCharacterMetrics *cm;
555 AFMComposite *comp;
556
557 if (font == NULL)
558 return AFM_ERROR_ARGUMENT;
559
560 if (name)
561 {
562 /* Get font. */
563 if (!strhash_get (font->private->fontnames, name, strlen (name),
564 (void *) &cm))
565 {
566 /* Check composite characters. */
567 if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
568 || strhash_get (font->private->compositenames, name,
569 strlen (name), (void *) &comp) == 0)
570 cm = AFM_ENC_NON_EXISTENT;
571 else
572 {
573 /*
574 * Ok, composite character found, now find the character
575 * specified by the first composite component.
576 */
577 if (!strhash_get (font->private->fontnames,
578 comp->components[0].name,
579 strlen (comp->components[0].name),
580 (void *) &cm))
581 cm = AFM_ENC_NON_EXISTENT;
582 }
583 }
584 }
585 else
586 cm = AFM_ENC_NONE;
587
588 font->encoding[(unsigned int) code] = cm;
589
590 return AFM_SUCCESS;
591 }
592
593
594 AFMError
595 afm_font_encoding (AFMFont font, AFMEncoding enc, unsigned int flags)
596 {
597 int i;
598 AFMIndividualCharacterMetrics *cm;
599
600 if (font == NULL)
601 return AFM_ERROR_ARGUMENT;
602
603 switch (enc)
604 {
605 case AFM_ENCODING_DEFAULT:
606 /* Clear encoding. */
607 for (i = 0; i < 256; i++)
608 font->encoding[i] = AFM_ENC_NONE;
609
610 /* Apply font's default encoding. */
611 for (i = 0; i < font->num_character_metrics; i++)
612 {
613 cm = &font->character_metrics[i];
614 font->encoding[cm->character_code] = cm;
615 }
616 break;
617
618 case AFM_ENCODING_ISO_8859_1:
619 apply_encoding (font, afm_88591_encoding, flags);
620 break;
621
622 case AFM_ENCODING_ISO_8859_2:
623 apply_encoding (font, afm_88592_encoding, flags);
624 break;
625
626 case AFM_ENCODING_ISO_8859_3:
627 apply_encoding (font, afm_88593_encoding, flags);
628 break;
629
630 case AFM_ENCODING_ISO_8859_4:
631 apply_encoding (font, afm_88594_encoding, flags);
632 break;
633
634 case AFM_ENCODING_ISO_8859_5:
635 apply_encoding (font, afm_88595_encoding, flags);
636 break;
637
638 case AFM_ENCODING_ISO_8859_7:
639 apply_encoding (font, afm_88597_encoding, flags);
640 break;
641
642 case AFM_ENCODING_ISO_8859_9:
643 apply_encoding (font, afm_88599_encoding, flags);
644 break;
645
646 case AFM_ENCODING_ISO_8859_10:
647 apply_encoding (font, afm_885910_encoding, flags);
648 break;
649
650 case AFM_ENCODING_IBMPC:
651 apply_encoding (font, afm_ibmpc_encoding, flags);
652 break;
653
654 case AFM_ENCODING_ASCII:
655 /*
656 * First apply one encoding (all have equal first 128 characters),
657 * then zap last 128 chars.
658 */
659 apply_encoding (font, afm_88591_encoding, flags);
660 for (i = 128; i < 256; i++)
661 font->encoding[i] = AFM_ENC_NONE;
662 break;
663
664 case AFM_ENCODING_MAC:
665 apply_encoding (font, afm_mac_encoding, flags);
666 break;
667
668 case AFM_ENCODING_VMS:
669 apply_encoding (font, afm_vms_encoding, flags);
670 break;
671
672 case AFM_ENCODING_HP8:
673 apply_encoding (font, afm_hp8_encoding, flags);
674 break;
675
676 case AFM_ENCODING_KOI8:
677 apply_encoding (font, afm_koi8_encoding, flags);
678 break;
679 }
680
681 return AFM_SUCCESS;
682 }
683
684
685 /*
686 * Internal help functions.
687 */
688
689
690 void
691 afm_message (AFMHandle handle, unsigned int level, char *message)
692 {
693 if (handle->verbose < level)
694 return;
695
696 fprintf (stderr, "%s", message);
697 }
698
699
700 void
701 afm_error (AFMHandle handle, char *message)
702 {
703 fprintf (stderr, "AFM Error: %s\n", message);
704 }
705
706
707 /*
708 * Static functions.
709 */
710
711 static void
712 read_font_map (AFMHandle handle, char *name)
713 {
714 FILE *fp;
715 char buf[512];
716 char fullname[512];
717 unsigned int dirlen;
718 char *cp, *cp2;
719 char msg[256];
720
721 sprintf (msg, "AFM: reading font map \"%s\"\n", name);
722 afm_message (handle, 1, msg);
723
724 fp = fopen (name, "r");
725 if (fp == NULL)
726 {
727 sprintf (msg, "AFM: couldn't open font map \"%s\": %s\n", name,
728 strerror (errno));
729 afm_message (handle, 1, msg);
730 return;
731 }
732
733 /* Get directory */
734 cp = strrchr (name, '/');
735 if (cp)
736 {
737 dirlen = cp - name + 1;
738 memcpy (fullname, name, dirlen);
739 }
740 else
741 {
742 dirlen = 2;
743 memcpy (fullname, "./", dirlen);
744 }
745
746 while (fgets (buf, sizeof (buf), fp))
747 {
748 char font[256];
749 char file[256];
750
751 if (sscanf (buf, "%s %s", font, file) != 2)
752 {
753 sprintf (msg, "malformed line in font map \"%s\":\n%s",
754 name, buf);
755 afm_error (handle, msg);
756 continue;
757 }
758
759 /* Do we already have this font? */
760 if (strhash_get (handle->font_map, font, strlen (font), (void *) &cp))
761 continue;
762
763 /* Append file name. */
764 strcpy (fullname + dirlen, file);
765 cp = (char *) malloc (strlen (fullname) + 1);
766 if (cp == NULL)
767 {
768 afm_error (handle, "couldn't add font: out of memory");
769 goto out;
770 }
771 strcpy (cp, fullname);
772
773 sprintf (msg, "AFM: font mapping: %s -> %s\n", font, cp);
774 afm_message (handle, 2, msg);
775 (void) strhash_put (handle->font_map, font, strlen (font), cp,
776 (void *) &cp2);
777 }
778
779 out:
780 fclose (fp);
781 }
782
783
784 static void
785 apply_encoding (AFMFont font, AFMEncodingTable *enc, unsigned int flags)
786 {
787 int i;
788 AFMIndividualCharacterMetrics *cm;
789 AFMComposite *comp;
790
791 for (i = 0; enc[i].code >= 0; i++)
792 {
793 if (enc[i].character == AFM_ENC_NONE)
794 font->encoding[enc[i].code] = AFM_ENC_NONE;
795 else if (enc[i].character == AFM_ENC_NON_EXISTENT)
796 font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
797 else
798 {
799 if (strhash_get (font->private->fontnames, enc[i].character,
800 strlen (enc[i].character), (void *) &cm))
801 font->encoding[enc[i].code] = cm;
802 else
803 {
804 /* Check composite characters. */
805 if ((flags & AFM_ENCODE_ACCEPT_COMPOSITES) == 0
806 || strhash_get (font->private->compositenames,
807 enc[i].character, strlen (enc[i].character),
808 (void *) &comp) == 0)
809 font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
810 else
811 {
812 /* Composite character found. */
813 if (strhash_get (font->private->fontnames,
814 comp->components[0].name,
815 strlen (comp->components[0].name),
816 (void *) &cm))
817 font->encoding[enc[i].code] = cm;
818 else
819 font->encoding[enc[i].code] = AFM_ENC_NON_EXISTENT;
820 }
821 }
822 }
823 }
824 }