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