file-name: Generalize fn_interp_vars().
[pspp-builds.git] / src / output / afm.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2006 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program 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
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include "afm.h"
19 #include "c-ctype.h"
20 #include "c-strtod.h"
21 #include <ctype.h>
22 #include <errno.h>
23 #include <limits.h>
24 #include <stdarg.h>
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <setjmp.h>
30 #include "error.h"
31 #include "minmax.h"
32 #include <libpspp/assertion.h>
33 #include <libpspp/pool.h>
34 #include <libpspp/str.h>
35
36 #include "gettext.h"
37 #define _(msgid) gettext (msgid)
38
39 /* A kern pair entry. */
40 struct afm_kern_pair
41   {
42     struct afm_character *successor; /* Second character. */
43     int adjust;                 /* Adjustment. */
44   };
45
46 /* A ligature. */
47 struct afm_ligature
48   {
49     struct afm_character *successor; /* Second character. */
50     struct afm_character *ligature;  /* Resulting ligature. */
51   };
52
53 /* How to map between byte strings and character values. */
54 enum mapping_scheme
55   {
56     MAP_UNKNOWN,                /* Not yet determined. */
57     MAP_ONE_BYTE,               /* 8-bit coding. */
58     MAP_TWO_BYTE,               /* 16-bit coding. */
59     MAP_ESCAPE,                 /* 8-bit coding with escape to change fonts. */
60     MAP_DOUBLE_ESCAPE,          /* 8-bit coding with multiple escapes. */
61     MAP_SHIFT                   /* 8-bit coding with 2 fonts that toggle. */
62   };
63
64 /* AFM file data.  */
65 struct afm
66   {
67     struct pool *pool;          /* Containing pool. */
68     char *findfont_name;        /* Name for PostScript /findfont operator. */
69     int ascent;                 /* Height above the baseline (non-negative). */
70     int descent;                /* Depth below the baseline (non-negative). */
71
72     /* Encoding characters into strings. */
73     enum mapping_scheme mapping; /* Basic mapping scheme. */
74     char escape_char;           /* MAP_ESCAPE only: escape character to use. */
75     char shift_out;             /* MAP_SHIFT only: selects font 0. */
76     char shift_in;              /* MAP_SHIFT only: selects font 1. */
77
78     /* Characters. */
79     struct afm_character *undefined_codes[256];
80     struct afm_character **codes[256];
81     struct afm_character **chars;
82     size_t char_cnt;
83   };
84
85 /* AFM file parser. */
86 struct parser
87   {
88     struct pool *pool;          /* Containing pool. */
89     struct afm *afm;            /* AFM being parsed. */
90     FILE *file;                 /* File being parsed. */
91     const char *file_name;      /* Name of file being parsed. */
92     int line_number;            /* Current line number in file. */
93     jmp_buf bail_out;           /* longjmp() target for error handling. */
94
95     size_t char_allocated;
96     int max_code;
97   };
98
99 static struct afm *create_afm (void);
100 static struct afm_character *create_character (struct afm *);
101
102 static void afm_error (struct parser *, const char *, ...)
103      PRINTF_FORMAT (2, 3)
104      NO_RETURN;
105
106 static void parse_afm (struct parser *);
107 static void skip_section (struct parser *, const char *end_key);
108 static bool parse_set_specific (struct parser *, const char *end_key);
109 static void parse_direction (struct parser *);
110 static void parse_char_metrics (struct parser *);
111 static void parse_kern_pairs (struct parser *);
112 static void add_kern_pair (struct parser *p,
113                            struct afm_character *, struct afm_character *,
114                            int adjust);
115
116 static int skip_spaces (struct parser *);
117 static char *parse_key (struct parser *);
118 static void skip_line (struct parser *);
119 static void force_eol (struct parser *);
120 static bool get_integer (struct parser *, int *);
121 static int force_get_integer (struct parser *);
122 static bool get_number (struct parser *, int *);
123 static int force_get_number (struct parser *);
124 static bool get_hex_code (struct parser *, int *);
125 static int force_get_hex_code (struct parser *);
126 static bool get_word (struct parser *, char **);
127 static char *force_get_word (struct parser *);
128 static bool get_string (struct parser *, char **);
129 static char *force_get_string (struct parser *);
130
131 static struct afm_character *get_char_by_name (struct parser *, const char *);
132 static struct afm_character *get_char_by_code (const struct afm *, int code);
133
134 /* Reads FILE_NAME as an AFM file and returns the metrics data.
135    Returns a null pointer if the file cannot be parsed. */
136 struct afm *
137 afm_open (const char *file_name)
138 {
139   struct afm *volatile afm;
140   struct parser *parser;
141
142   parser = pool_create_container (struct parser, pool);
143   afm = parser->afm = create_afm ();
144   parser->file = pool_fopen (parser->pool, file_name, "r");
145   parser->file_name = file_name;
146   parser->line_number = 0;
147   if (parser->file == NULL)
148     {
149       error (0, errno, _("opening font metrics file \"%s\""), file_name);
150       goto error;
151     }
152
153   if (setjmp (parser->bail_out))
154     goto error;
155
156   parse_afm (parser);
157   pool_destroy (parser->pool);
158   return afm;
159
160  error:
161   pool_destroy (parser->pool);
162   pool_destroy (afm->pool);
163   return create_afm ();
164 }
165
166 /* Creates and returns an empty set of metrics. */
167 static struct afm *
168 create_afm (void)
169 {
170   struct afm *afm;
171   struct afm_character *def_char;
172   size_t i;
173
174   afm = pool_create_container (struct afm, pool);
175   afm->findfont_name = NULL;
176   afm->ascent = 0;
177   afm->descent = 0;
178   afm->mapping = MAP_UNKNOWN;
179   afm->escape_char = 255;
180   afm->shift_out = 14;
181   afm->shift_in = 15;
182   def_char = create_character (afm);
183   for (i = 0; i < 256; i++)
184     afm->undefined_codes[i] = def_char;
185   for (i = 0; i < 256; i++)
186     afm->codes[i] = afm->undefined_codes;
187   afm->chars = NULL;
188   afm->char_cnt = 0;
189
190   return afm;
191 }
192
193 /* Creates and returns an initialized character within AFM. */
194 static struct afm_character *
195 create_character (struct afm *afm)
196 {
197   struct afm_character *c = pool_alloc (afm->pool, sizeof *c);
198   c->code = ' ';
199   c->name = NULL;
200   c->width = 12000;
201   c->ascent = 0;
202   c->descent = 0;
203   c->kern_pairs = NULL;
204   c->kern_pair_cnt = 0;
205   c->ligatures = NULL;
206   c->ligature_cnt = 0;
207   return c;
208 }
209
210 /* Reports the given MESSAGE at the current line in parser P
211    and bails out with longjmp(). */
212 static void
213 afm_error (struct parser *p, const char *message, ...)
214 {
215   va_list args;
216   char *msg;
217
218   va_start (args, message);
219   msg = xasprintf (message, args);
220   va_end (args);
221
222   error_at_line (0, 0, p->file_name, p->line_number, "%s", msg);
223   free (msg);
224
225   longjmp (p->bail_out, 1);
226 }
227
228 /* Parses an AFM file with parser P. */
229 static void
230 parse_afm (struct parser *p)
231 {
232   char *key;
233
234   p->char_allocated = 0;
235   p->max_code = 0;
236
237   key = force_get_word (p);
238   if (strcmp (key, "StartFontMetrics"))
239     afm_error (p, _("first line must be StartFontMetrics"));
240   skip_line (p);
241
242   do
243     {
244       key = parse_key (p);
245       if (!strcmp (key, "FontName"))
246         p->afm->findfont_name = pool_strdup (p->afm->pool,
247                                              force_get_string (p));
248       else if (!strcmp (key, "Ascender"))
249         p->afm->ascent = force_get_integer (p);
250       else if (!strcmp (key, "Descender"))
251         p->afm->descent = force_get_integer (p);
252       else if (!strcmp (key, "MappingScheme"))
253         {
254           int scheme = force_get_integer (p);
255           if (scheme == 4)
256             p->afm->mapping = MAP_ONE_BYTE;
257           else if (scheme == 2 || scheme == 5 || scheme == 6)
258             p->afm->mapping = MAP_TWO_BYTE;
259           else if (scheme == 3)
260             p->afm->mapping = MAP_ESCAPE;
261           else if (scheme == 7)
262             p->afm->mapping = MAP_DOUBLE_ESCAPE;
263           else if (scheme == 8)
264             p->afm->mapping = MAP_SHIFT;
265           else
266             afm_error (p, _("unsupported MappingScheme %d"), scheme);
267         }
268       else if (!strcmp (key, "EscChar"))
269         p->afm->escape_char = force_get_integer (p);
270       else if (!strcmp (key, "StartDirection"))
271         parse_direction (p);
272       else if (!strcmp (key, "StartCharMetrics"))
273         parse_char_metrics (p);
274       else if (!strcmp (key, "StartKernPairs")
275                || !strcmp (key, "StartKernPairs0"))
276         parse_kern_pairs (p);
277       else if (!strcmp (key, "StartTrackKern"))
278         skip_section (p, "EndTrackKern");
279       else if (!strcmp (key, "StartComposites"))
280         skip_section (p, "EndComposites");
281       else
282         skip_line (p);
283     }
284   while (strcmp (key, "EndFontMetrics"));
285
286   if (p->afm->findfont_name == NULL)
287     afm_error (p, _("required FontName is missing"));
288   if (p->afm->mapping == MAP_UNKNOWN)
289     {
290       /* There seem to be a number of fonts out there that use a
291          2-byte encoding but don't announce it with
292          MappingScheme. */
293       p->afm->mapping = p->max_code > 255 ? MAP_TWO_BYTE : MAP_ONE_BYTE;
294     }
295 }
296
297 /* Reads lines from parser P until one starts with END_KEY. */
298 static void
299 skip_section (struct parser *p, const char *end_key)
300 {
301   const char *key;
302   skip_line (p);
303   do
304     {
305       key = parse_key (p);
306       skip_line (p);
307     }
308   while (strcmp (key, end_key));
309 }
310
311 /* Attempts to read an integer from parser P.
312    If one is found, and it is nonzero, skips lines until END_KEY
313    is encountered and returns false.
314    Otherwise, skips the rest of the line and returns true.
315    (This is useful because AFM files can have multiple sets of
316    metrics.  Set 0 is for normal text, other sets are for
317    vertical text, etc.  We only care about set 0.) */
318 static bool
319 parse_set_specific (struct parser *p, const char *end_key)
320 {
321   int set;
322
323   if (get_integer (p, &set) && set != 0)
324     {
325       skip_section (p, end_key);
326       return false;
327     }
328   else
329     {
330       force_eol (p);
331       return true;
332     }
333 }
334
335 /* Parses a StartDirection...EndDirection section in parser P. */
336 static void
337 parse_direction (struct parser *p)
338 {
339   const char *key;
340
341   if (!parse_set_specific (p, "EndDirection"))
342     return;
343
344   do
345     {
346       key = parse_key (p);
347       if (!strcmp (key, "CharWidth"))
348         p->afm->codes[0][0]->width = force_get_integer (p);
349       skip_line (p);
350     }
351   while (strcmp (key, "EndDirection"));
352 }
353
354 /* Parses a StartCharMetrics...EndCharMetrics section in parser
355    P. */
356 static void
357 parse_char_metrics (struct parser *p)
358 {
359   struct parsing_ligature
360     {
361       struct afm_character *first;
362       char *successor;
363       char *ligature;
364     };
365
366   struct parsing_ligature *ligatures = NULL;
367   size_t ligature_cnt = 0;
368   size_t ligature_allocated = 0;
369
370   size_t i;
371
372   skip_line (p);
373
374   for (;;)
375     {
376       char *key;
377       struct afm_character *c;
378
379       key = parse_key (p);
380       if (!strcmp (key, "EndCharMetrics"))
381         break;
382
383       if (p->afm->char_cnt == p->char_allocated)
384         p->afm->chars = pool_2nrealloc (p->afm->pool, p->afm->chars,
385                                         &p->char_allocated,
386                                         sizeof *p->afm->chars);
387       c = create_character (p->afm);
388
389       if (!strcmp (key, "C"))
390         c->code = force_get_integer (p);
391       else if (!strcmp (key, "CH"))
392         c->code = force_get_hex_code (p);
393       else
394         afm_error (p, _("CharMetrics line must start with C or CH"));
395       if (c->code < 0 || c->code > 65535)
396         c->code = -1;
397
398       if (c->code > p->max_code)
399         p->max_code = c->code;
400
401       p->afm->chars[p->afm->char_cnt++] = c;
402       if (c->code != -1)
403         p->afm->codes[c->code >> 8][c->code & 0xff] = c;
404
405       key = force_get_word (p);
406       while (!strcmp (key, ";"))
407         {
408           if (!get_word (p, &key))
409             break;
410
411           if (!strcmp (key, "N"))
412             c->name = force_get_word (p);
413           else if (!strcmp (key, "WX") || !strcmp (key, "W0X"))
414             c->width = force_get_number (p);
415           else if (!strcmp (key, "W") || !strcmp (key, "W0"))
416             {
417               c->width = force_get_number (p);
418               force_get_number (p);
419             }
420           else if (!strcmp (key, "B"))
421             {
422               int llx, lly, urx, ury;
423               llx = force_get_number (p);
424               lly = force_get_number (p);
425               urx = force_get_number (p);
426               ury = force_get_number (p);
427               c->ascent = MAX (0, ury);
428               c->descent = MAX (0, -lly);
429             }
430           else if (!strcmp (key, "L"))
431             {
432               struct parsing_ligature *ligature;
433               if (ligature_cnt == ligature_allocated)
434                 ligatures = pool_2nrealloc (p->pool, ligatures,
435                                             &ligature_allocated,
436                                             sizeof *ligatures);
437               ligature = &ligatures[ligature_cnt++];
438               ligature->first = c;
439               ligature->successor = force_get_word (p);
440               ligature->ligature = force_get_word (p);
441             }
442           else
443             {
444               while (strcmp (key, ";"))
445                 key = force_get_word (p);
446               continue;
447             }
448           if (!get_word (p, &key))
449             break;
450         }
451     }
452   skip_line (p);
453
454   for (i = 0; i < ligature_cnt; i++)
455     {
456       struct parsing_ligature *src = &ligatures[i];
457       struct afm_ligature *dst;
458       src->first->ligatures = pool_nrealloc (p->afm->pool,
459                                              src->first->ligatures,
460                                              src->first->ligature_cnt + 1,
461                                              sizeof *src->first->ligatures);
462       dst = &src->first->ligatures[src->first->ligature_cnt++];
463       dst->successor = get_char_by_name (p, src->successor);
464       dst->ligature = get_char_by_name (p, src->ligature);
465     }
466 }
467
468 /* Parses a StartKernPairs...EndKernPairs section in parser P. */
469 static void
470 parse_kern_pairs (struct parser *p)
471 {
472   char *key;
473
474   skip_line (p);
475
476   do
477     {
478       struct afm_character *c1, *c2;
479       int adjust;
480
481       key = parse_key (p);
482       if (!strcmp (key, "KP") || !strcmp (key, "KPX"))
483         {
484           c1 = get_char_by_name (p, force_get_word (p));
485           c2 = get_char_by_name (p, force_get_word (p));
486           adjust = force_get_number (p);
487           if (!strcmp (key, "KP"))
488             force_get_number (p);
489           add_kern_pair (p, c1, c2, adjust);
490         }
491       else if (!strcmp (key, "KPH"))
492         {
493           c1 = get_char_by_code (p->afm, force_get_hex_code (p));
494           c2 = get_char_by_code (p->afm, force_get_hex_code (p));
495           adjust = force_get_number (p);
496           force_get_number (p);
497           add_kern_pair (p, c1, c2, adjust);
498         }
499       else
500         skip_line (p);
501     }
502   while (strcmp (key, "EndKernPairs"));
503 }
504
505 /* Adds a kern pair that adjusts (FIRST, SECOND) by ADJUST units
506    to the metrics within parser P. */
507 static void
508 add_kern_pair (struct parser *p, struct afm_character *first,
509                struct afm_character *second, int adjust)
510 {
511   struct afm_kern_pair *kp;
512
513   first->kern_pairs = pool_nrealloc (p->afm->pool, first->kern_pairs,
514                                      first->kern_pair_cnt + 1,
515                                      sizeof *first->kern_pairs);
516   kp = &first->kern_pairs[first->kern_pair_cnt++];
517   kp->successor = second;
518   kp->adjust = adjust;
519 }
520
521 /* Returns the character with the given NAME with the metrics for
522    parser P.  Reports an error if no character has the given
523    name. */
524 static struct afm_character *
525 get_char_by_name (struct parser *p, const char *name)
526 {
527   size_t i;
528
529   for (i = 0; i < p->afm->char_cnt; i++)
530     {
531       struct afm_character *c = p->afm->chars[i];
532       if (c->name != NULL && !strcmp (c->name, name))
533         return c;
534     }
535   afm_error (p, _("reference to unknown character \"%s\""), name);
536 }
537
538 /* Returns the character with the given CODE within AFM.
539    Returns a default character if the font doesn't have a
540    character with that code. */
541 static struct afm_character *
542 get_char_by_code (const struct afm *afm, int code_)
543 {
544   uint16_t code = code_;
545   return afm->codes[code >> 8][code & 0xff];
546 }
547 \f
548 /* Skips white space, except for new-lines, within parser P. */
549 static int
550 skip_spaces (struct parser *p)
551 {
552   int c;
553   while (isspace (c = getc (p->file)) && c != '\n')
554     continue;
555   ungetc (c, p->file);
556   return c;
557 }
558
559 /* Parses a word at the beginning of a line.
560    Skips comments.
561    Reports an error if not at the beginning of a line. */
562 static char *
563 parse_key (struct parser *p)
564 {
565   force_eol (p);
566   for (;;)
567     {
568       char *key;
569
570       do
571         {
572           p->line_number++;
573           getc (p->file);
574         }
575       while (skip_spaces (p) == '\n');
576
577       key = force_get_word (p);
578       if (strcmp (key, "Comment"))
579         return key;
580
581       skip_line (p);
582     }
583 }
584
585 /* Skips to the next line within parser P. */
586 static void
587 skip_line (struct parser *p)
588 {
589   for (;;)
590     {
591       int c = getc (p->file);
592       if (c == EOF)
593         afm_error (p, _("expected end of file"));
594       if (c == '\n')
595         break;
596     }
597   ungetc ('\n', p->file);
598 }
599
600 /* Ensures that parser P is at the end of a line. */
601 static void
602 force_eol (struct parser *p)
603 {
604   if (skip_spaces (p) != '\n')
605     afm_error (p, _("syntax error expecting end of line"));
606 }
607
608 /* Tries to read an integer into *INTEGER at the current position
609    in parser P.
610    Returns success. */
611 static bool
612 get_integer (struct parser *p, int *integer)
613 {
614   int c = skip_spaces (p);
615   if (isdigit (c) || c == '-')
616     {
617       char *tail;
618       long tmp;
619
620       errno = 0;
621       tmp = strtol (force_get_word (p), &tail, 10);
622       if (errno == ERANGE || tmp < INT_MIN || tmp > INT_MAX)
623         afm_error (p, _("number out of valid range"));
624       if (*tail != '\0')
625         afm_error (p, _("invalid numeric syntax"));
626       *integer = tmp;
627
628       return true;
629     }
630   else
631     return false;
632 }
633
634 /* Returns an integer read from the current position in P.
635    Reports an error if unsuccessful. */
636 static int
637 force_get_integer (struct parser *p)
638 {
639   int integer;
640   if (!get_integer (p, &integer))
641     afm_error (p, _("syntax error expecting integer"));
642   return integer;
643 }
644
645 /* Tries to read a floating-point number at the current position
646    in parser P.  Stores the number's integer part into *INTEGER.
647    Returns success. */
648 static bool
649 get_number (struct parser *p, int *integer)
650 {
651   int c = skip_spaces (p);
652   if (c == '-' || c == '.' || isdigit (c))
653     {
654       char *tail;
655       double number;
656
657       errno = 0;
658       number = c_strtod (force_get_word (p), &tail);
659       if (errno == ERANGE || number < INT_MIN || number > INT_MAX)
660         afm_error (p, _("number out of valid range"));
661       if (*tail != '\0')
662         afm_error (p, _("invalid numeric syntax"));
663       *integer = number;
664
665       return true;
666     }
667   else
668     return false;
669 }
670
671 /* Returns the integer part of a floating-point number read from
672    the current position in P.
673    Reports an error if unsuccessful. */
674 static int
675 force_get_number (struct parser *p)
676 {
677   int integer;
678   if (!get_number (p, &integer))
679     afm_error (p, _("syntax error expecting number"));
680   return integer;
681 }
682
683 /* Tries to read an integer expressed in hexadecimal into
684    *INTEGER from P.
685    Returns success. */
686 static bool
687 get_hex_code (struct parser *p, int *integer)
688 {
689   if (skip_spaces (p) == '<')
690     {
691       if (fscanf (p->file, "<%x", integer) != 1 || getc (p->file) != '>')
692         afm_error (p, _("syntax error in hex constant"));
693       return true;
694     }
695   else
696     return false;
697 }
698
699 /* Reads an integer expressed in hexadecimal and returns its
700    value.
701    Reports an error if unsuccessful. */
702 static int
703 force_get_hex_code (struct parser *p)
704 {
705   int integer;
706   if (!get_hex_code (p, &integer))
707     afm_error (p, _("syntax error expecting hex constant"));
708   return integer;
709 }
710
711 /* Tries to read a word from P into *WORD.
712    The word is allocated in P's pool.
713    Returns success. */
714 static bool
715 get_word (struct parser *p, char **word)
716 {
717   if (skip_spaces (p) != '\n')
718     {
719       struct string s;
720       int c;
721
722       ds_init_empty (&s);
723       while (!isspace (c = getc (p->file)) && c != EOF)
724         ds_put_char (&s, c);
725       ungetc (c, p->file);
726       *word = ds_cstr (&s);
727       pool_register (p->pool, free, *word);
728       return true;
729     }
730   else
731     {
732       *word = NULL;
733       return false;
734     }
735 }
736
737 /* Reads a word from P and returns it.
738    The word is allocated in P's pool.
739    Reports an error if unsuccessful. */
740 static char *
741 force_get_word (struct parser *p)
742 {
743   char *word;
744   if (!get_word (p, &word))
745     afm_error (p, _("unexpected end of line"));
746   return word;
747 }
748
749 /* Reads a string, consisting of the remainder of the current
750    line, from P, and stores it in *STRING.
751    Leading and trailing spaces are removed.
752    The word is allocated in P's pool.
753    Returns true if a non-empty string was successfully read,
754    false otherwise. */
755 static bool
756 get_string (struct parser *p, char **string)
757 {
758   struct string s = DS_EMPTY_INITIALIZER;
759
760   skip_spaces (p);
761   for (;;)
762     {
763       int c = getc (p->file);
764       if (c == EOF || c == '\n')
765         break;
766       ds_put_char (&s, c);
767     }
768   ungetc ('\n', p->file);
769   ds_rtrim (&s, ss_cstr (CC_SPACES));
770
771   if (!ds_is_empty (&s))
772     {
773       *string = ds_cstr (&s);
774       pool_register (p->pool, free, *string);
775       return true;
776     }
777   else
778     {
779       *string = NULL;
780       ds_destroy (&s);
781       return false;
782     }
783 }
784
785 /* Reads a string, consisting of the remainder of the current
786    line, from P, and returns it.
787    Leading and trailing spaces are removed.
788    The word is allocated in P's pool.
789    Reports an error if the string is empty. */
790 static char *
791 force_get_string (struct parser *p)
792 {
793   char *string;
794   if (!get_string (p, &string))
795     afm_error (p, _("unexpected end of line expecting string"));
796   return string;
797 }
798 \f
799 /* Closes AFM and frees its storage. */
800 void
801 afm_close (struct afm *afm)
802 {
803   if (afm != NULL)
804     pool_destroy (afm->pool);
805 }
806
807 /* Returns the string that must be passed to the PostScript
808    "findfont" operator to obtain AFM's font. */
809 const char *
810 afm_get_findfont_name (const struct afm *afm)
811 {
812   return afm->findfont_name;
813 }
814
815 /* Returns the ascent for AFM, that is, the font's height above
816    the baseline, in units of 1/1000 of the nominal font size. */
817 int
818 afm_get_ascent (const struct afm *afm)
819 {
820   return afm->ascent;
821 }
822
823 /* Returns the descent for AFM, that is, the font's depth below
824    the baseline, in units of 1/1000 of the nominal font size. */
825 int
826 afm_get_descent (const struct afm *afm)
827 {
828   return afm->descent;
829 }
830
831 /* Returns the character numbered CODE within AFM,
832    or a default character if the font has none. */
833 const struct afm_character *
834 afm_get_character (const struct afm *afm, int code)
835 {
836   return get_char_by_code (afm, code);
837 }
838
839 /* Returns the ligature formed when FIRST is followed by SECOND,
840    or a null pointer if there is no such ligature. */
841 const struct afm_character *
842 afm_get_ligature (const struct afm_character *first,
843                   const struct afm_character *second)
844 {
845   size_t i;
846
847   for (i = 0; i < first->ligature_cnt; i++)
848     if (first->ligatures[i].successor == second)
849       return first->ligatures[i].ligature;
850   return NULL;
851 }
852
853 /* Returns the pair kerning x-adjustment when FIRST is followed
854    by SECOND, or 0 if no pair kerning should be done for the
855    given pair of characters. */
856 int
857 afm_get_kern_adjustment (const struct afm_character *first,
858                          const struct afm_character *second)
859 {
860   size_t i;
861
862   for (i = 0; i < first->kern_pair_cnt; i++)
863     if (first->kern_pairs[i].successor == second)
864       return first->kern_pairs[i].adjust;
865   return 0;
866 }
867 \f
868 /* Encodes the N characters in S as a PostScript string in OUT,
869    using a single-byte encoding.
870    Returns the number of characters remaining after all those
871    that could be successfully encoded were. */
872 static size_t
873 encode_one_byte (const struct afm_character **s, size_t n,
874                  struct string *out)
875 {
876   ds_put_char (out, '(');
877   for (; n > 0; s++, n--)
878     {
879       uint8_t code = (*s)->code;
880       if (code != (*s)->code)
881         break;
882
883       if (code == '(' || code == ')' || code == '\\')
884         ds_put_format (out, "\\%c", code);
885       else if (!c_isprint (code))
886         ds_put_format (out, "\\%03o", code);
887       else
888         ds_put_char (out, code);
889     }
890   ds_put_char (out, ')');
891   return n;
892 }
893
894 /* State of binary encoder for PostScript. */
895 struct binary_encoder
896   {
897     struct string *out;         /* Output string. */
898     uint32_t b;                 /* Accumulated bytes for base-85 encoding. */
899     size_t n;                   /* Number of bytes in b (0...3). */
900   };
901
902 /* Initializes encoder E for output to OUT. */
903 static void
904 binary_init (struct binary_encoder *e, struct string *out)
905 {
906   e->out = out;
907   e->b = e->n = 0;
908 }
909
910 /* Returns the character that represents VALUE in ASCII85
911    encoding. */
912 static int
913 value_to_ascii85 (int value)
914 {
915   assert (value >= 0 && value < 85);
916 #if C_CTYPE_ASCII
917   return value + 33;
918 #else
919   return ("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJK"
920           "LMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstu")[value];
921 #endif
922 }
923
924 /* Appends the first N characters of the ASCII85 representation
925    of B to string OUT. */
926 static void
927 append_ascii85_block (unsigned b, size_t n, struct string *out)
928 {
929   char c[5];
930   int i;
931
932   for (i = 4; i >= 0; i--)
933     {
934       c[i] = value_to_ascii85 (b % 85);
935       b /= 85;
936     }
937   ds_put_substring (out, ss_buffer (c, n));
938 }
939
940 /* Encodes BYTE with encoder E. */
941 static void
942 binary_put (struct binary_encoder *e, uint8_t byte)
943 {
944   e->b = (e->b << 8) | byte;
945   e->n++;
946   if (e->n % 4 == 0)
947     {
948       if (e->n == 4)
949         ds_put_cstr (e->out, "<~");
950
951       if (e->b != 0)
952         append_ascii85_block (e->b, 5, e->out);
953       else
954         ds_put_char (e->out, 'z');
955     }
956 }
957
958 /* Finishes up encoding with E. */
959 static void
960 binary_finish (struct binary_encoder *e)
961 {
962   if (e->n >= 4)
963     {
964       /* We output at least one complete ASCII85 block.
965          Finish up. */
966       size_t n = e->n % 4;
967       if (n > 0)
968         append_ascii85_block (e->b << 8 * (4 - n), n + 1, e->out);
969       ds_put_cstr (e->out, "~>");
970     }
971   else if (e->n > 0)
972     {
973       /* It's cheaper (or at least the same cost) to encode this
974          string in hexadecimal. */
975       uint32_t b;
976       size_t i;
977
978       ds_put_cstr (e->out, "<");
979       b = e->b << 8 * (4 - e->n);
980       for (i = 0; i < e->n; i++)
981         {
982           ds_put_format (e->out, "%02x", b >> 24);
983           b <<= 8;
984         }
985       ds_put_cstr (e->out, ">");
986     }
987   else
988     {
989       /* Empty string. */
990       ds_put_cstr (e->out, "()");
991     }
992 }
993
994 /* Encodes the N characters in S into encoder E,
995    using a two-byte encoding.
996    Returns the number of characters remaining after all those
997    that could be successfully encoded were. */
998 static size_t
999 encode_two_byte (const struct afm_character **s, size_t n,
1000                  struct binary_encoder *e)
1001 {
1002   for (; n > 0; s++, n--)
1003     {
1004       uint16_t code = (*s)->code;
1005       if (code != (*s)->code)
1006         break;
1007
1008       binary_put (e, code >> 8);
1009       binary_put (e, code);
1010     }
1011   return n;
1012 }
1013
1014 /* Encodes the N characters in S into encoder E,
1015    using an escape-based encoding with ESCAPE_CHAR as escape.
1016    Returns the number of characters remaining after all those
1017    that could be successfully encoded were. */
1018 static size_t
1019 encode_escape (const struct afm_character **s, size_t n,
1020                unsigned char escape_char,
1021                struct binary_encoder *e)
1022 {
1023   uint8_t cur_font = 0;
1024
1025   for (; n > 0; s++, n--)
1026     {
1027       uint16_t code = (*s)->code;
1028       uint8_t font_num = code >> 8;
1029       uint8_t char_num = code & 0xff;
1030       if (code != (*s)->code)
1031         break;
1032
1033       if (font_num != cur_font)
1034         {
1035           if (font_num == escape_char)
1036             break;
1037           binary_put (e, escape_char);
1038           binary_put (e, font_num);
1039           cur_font = font_num;
1040         }
1041       binary_put (e, char_num);
1042     }
1043   return n;
1044 }
1045
1046 /* Encodes the N characters in S into encoder E,
1047    using an double escape-based encoding with ESCAPE_CHAR as
1048    escape.
1049    Returns the number of characters remaining after all those
1050    that could be successfully encoded were. */
1051 static size_t
1052 encode_double_escape (const struct afm_character **s, size_t n,
1053                       unsigned char escape_char,
1054                       struct binary_encoder *e)
1055 {
1056   unsigned cur_font = 0;
1057
1058   for (; n > 0; s++, n--)
1059     {
1060       unsigned font_num = (*s)->code >> 8;
1061       uint8_t char_num = (*s)->code & 0xff;
1062       if ((*s)->code & ~0x1ffff)
1063         break;
1064
1065       if (font_num != cur_font)
1066         {
1067           if (font_num == (escape_char & 0xff))
1068             break;
1069           if (font_num >= 256)
1070             binary_put (e, escape_char);
1071           binary_put (e, escape_char);
1072           binary_put (e, font_num & 0xff);
1073           cur_font = font_num;
1074         }
1075       binary_put (e, char_num);
1076     }
1077   return n;
1078 }
1079
1080 /* Encodes the N characters in S into encoder E,
1081    using a shift-based encoding with SHIFT_IN and SHIFT_OUT as
1082    shift characters.
1083    Returns the number of characters remaining after all those
1084    that could be successfully encoded were. */
1085 static size_t
1086 encode_shift (const struct afm_character **s, size_t n,
1087               unsigned char shift_in, unsigned char shift_out,
1088               struct binary_encoder *e)
1089 {
1090   unsigned cur_font = 0;
1091
1092   for (; n > 0; s++, n--)
1093     {
1094       int font_num = ((*s)->code & 0x100) != 0;
1095       uint8_t char_num = (*s)->code & 0xff;
1096       if ((*s)->code & ~0x1ff)
1097         break;
1098
1099       if (font_num != cur_font)
1100         {
1101           binary_put (e, font_num ? shift_out : shift_in);
1102           cur_font = font_num;
1103         }
1104       binary_put (e, char_num);
1105     }
1106   return n;
1107 }
1108
1109 /* Encodes the N characters in S into a PostScript string in OUT,
1110    according to AFM's character encoding.
1111    Returns the number of characters successfully encoded,
1112    which may be less than N if an unencodable character was
1113    encountered. */
1114 size_t
1115 afm_encode_string (const struct afm *afm,
1116                    const struct afm_character **s, size_t n,
1117                    struct string *out)
1118 {
1119   size_t initial_length = ds_length (out);
1120   size_t chars_left;
1121
1122   if (afm->mapping == MAP_ONE_BYTE)
1123     chars_left = encode_one_byte (s, n, out);
1124   else
1125     {
1126       struct binary_encoder e;
1127
1128       binary_init (&e, out);
1129       switch (afm->mapping)
1130         {
1131         case MAP_TWO_BYTE:
1132           chars_left = encode_two_byte (s, n, &e);
1133           break;
1134
1135         case MAP_ESCAPE:
1136           chars_left = encode_escape (s, n, afm->escape_char, &e);
1137           break;
1138
1139         case MAP_DOUBLE_ESCAPE:
1140           chars_left = encode_double_escape (s, n, afm->escape_char, &e);
1141           break;
1142
1143         case MAP_SHIFT:
1144           chars_left = encode_shift (s, n, afm->shift_in, afm->shift_out, &e);
1145           break;
1146
1147         default:
1148           NOT_REACHED ();
1149         }
1150       binary_finish (&e);
1151     }
1152
1153   if (chars_left == n)
1154     ds_truncate (out, initial_length);
1155   return n - chars_left;
1156 }