Back to index

tetex-bin  3.0
type1.c
Go to the documentation of this file.
00001 /*  $Header$
00002 
00003     This is dvipdfm, a DVI to PDF translator.
00004     Copyright (C) 1998, 1999 by Mark A. Wicks
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019     
00020     The author may be contacted via the e-mail address
00021 
00022        mwicks@kettering.edu
00023 */
00024 
00025 /* This is tailored for PDF */
00026 
00027 #include <string.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 #include <time.h>
00032 #include <ctype.h>
00033 #include "system.h"
00034 #include "mem.h"
00035 #include "error.h"
00036 #include "mfileio.h"
00037 #include "pdfobj.h"
00038 #include "numbers.h"
00039 #include "type1.h"
00040 #include "tfm.h"
00041 #include "pdfparse.h"
00042 #include "pdflimits.h"
00043 #include "t1crypt.h"
00044 #include "twiddle.h"
00045 #include "encodings.h"
00046 
00047 static unsigned char verbose = 0;
00048 
00049 void type1_set_verbose(void)
00050 {
00051   if (verbose < 255) {
00052     verbose += 1;
00053   }
00054 }
00055 
00056 
00057 static unsigned long get_low_endian_quad (FILE *file)
00058 {
00059   unsigned long result;
00060   static unsigned bytes[4];
00061   int ch, i;
00062   for (i=0; i<4; i++) {
00063     if ((ch = fgetc (file)) < 0) {
00064       ERROR ("get_low_endian_quad:  Error reading file");
00065     }
00066     bytes[i] = ch;
00067   }
00068   result = bytes[3];
00069   for (i=2; i>=0; i--) {
00070     result = result*256u + bytes[i];
00071   }
00072   return result;
00073 }
00074 
00075 /* PFB section */
00076 
00077 static char partial_enabled = 1;
00078 
00079 void type1_disable_partial (void)
00080 {
00081   partial_enabled = 0;
00082 }
00083 
00084 static unsigned num_pfbs = 0;
00085 static unsigned max_pfbs = 0;
00086 struct a_pfb
00087 {
00088   char *pfb_name;
00089   char *fontname;
00090   pdf_obj *direct, *indirect, *descriptor;
00091   char **used_glyphs;
00092   char **int_encoding;
00093   char *used_def_enc_chars; /* The positions used from the default
00094                                encoding.  When a default encoding
00095                                is used, the glyph names will not
00096                                be known until the font is actually
00097                                read.  Since the glyph names are
00098                                unknown, only the positions of the
00099                                used chars are stored when the
00100                                default encoding is used */
00101   unsigned n_used_glyphs, max_used_glyphs;
00102 } *pfbs = NULL;
00103 
00104 static void init_a_pfb (struct a_pfb *pfb)
00105 {
00106   int i;
00107   pfb -> n_used_glyphs = 0;
00108   pfb -> max_used_glyphs = 0;
00109   pfb -> used_glyphs = NULL;
00110   pfb->pfb_name = NULL;
00111   pfb->fontname = NULL;
00112   pfb->direct = NULL;
00113   pfb->indirect = NULL;
00114   pfb->descriptor = NULL;
00115   pfb -> used_def_enc_chars = NULL;
00116   if (partial_enabled) {
00117     pfb -> int_encoding = NEW (256, char *);
00118     for (i=0; i<256; i++) {
00119       (pfb -> int_encoding)[i] = NULL;
00120     }
00121   } else {
00122     pfb -> int_encoding = NULL;
00123   }
00124 }
00125 
00126 #include "standardenc.h"
00127 
00128 static void do_a_standard_enc(char **glyphs, char **encoding) 
00129 {
00130   int i;
00131   for (i=0; i<256; i++) {
00132     RELEASE (glyphs[i]);
00133     glyphs[i] = NEW (strlen(encoding[i])+1, char);
00134     strcpy (glyphs[i], encoding[i]);
00135   }
00136 }
00137 #define FIXED_WIDTH 1
00138 #define SERIF 2
00139 #define STANDARD 32
00140 #define ITALIC 64
00141 #define SYMBOLIC 4   /* Fonts that don't have Adobe encodings (e.g.,
00142                      cmr, should be set to be symbolic */
00143 #define STEMV 80
00144 
00145 
00146 int CDECL glyph_cmp (const void *v1, const void *v2)
00147 {
00148   char *s1, *s2;
00149   s1 = *((char **) v1);
00150   s2 = *((char **) v2);
00151   return (strcmp (s1, s2));
00152 }
00153 
00154 int CDECL glyph_match (const void *key, const void *v)
00155 {
00156   char *s;
00157   s = *((char **) v);
00158   return (strcmp (key, s));
00159 }
00160 
00161 static unsigned long parse_header (unsigned char *filtered, unsigned char *buffer,
00162                                unsigned long length, int pfb_id)
00163 {
00164   /* If the encoding has been overridden, this routine should eliminate any
00165      built-in encoding (other than things like StandardEncoding) in
00166      the header to save space */
00167 
00168   /* On second thought, that's the way it _should_ work, but the
00169      reader doesn't seem to agree.  The reader is happy if you don't
00170      specify an encoding as long as you actually change the locations
00171      in the overriding encoding. The reader is unhappy if you don't
00172      specify an encoding and don't change the location of the
00173      characters in the overriding encoding.  Ghostscript doesn't
00174      have a problem with it. */
00175 
00176   unsigned char *filtered_pointer;
00177   int state = 0;
00178   char *start, *end, *lead;
00179   int copy = 1;
00180   int last_number = 0;
00181   char *glyph = NULL;
00182 #ifdef MEM_DEBUG
00183   MEM_START
00184 #endif
00185   /* This routine uses a state machine parser rather than trying to
00186      interpret Postcript the way mpost.c does.  There are only
00187      a few key parameters it is trying to find */
00188 
00189   /* State definitions 
00190      state 0: Initial state
00191      state 1: Saw /FontName
00192      state 2: Saw /Encoding
00193      state 3: Saw "dup" in state 2
00194      state 4: Saw a number in state 3
00195      state 5: Saw /glyphname in state 4
00196      state 6: Saw /FontBBox in state 0
00197      state 7: Saw a '{' or a '[' in state 6  
00198      state 8: Saw /ItalicAngle in state 0 */
00199   /* As the parser operates, start always points to the next point in
00200      the buffer */
00201   start = (char *) buffer;
00202   end = start+length;
00203   filtered_pointer = filtered;
00204   /* When the parser decides to keep text, the text
00205      between lead and start is copied to the output buffer.  To
00206      keep a block of text from being copied, the parser simply
00207      sets copy = 0 */
00208   lead = start;
00209   skip_white (&start, end);
00210   if (filtered && lead != start) {
00211     memcpy (filtered_pointer, lead, start-lead);
00212     filtered_pointer += start-lead;
00213     lead = start;
00214   }
00215   while (start < end) {
00216     char *ident;
00217     pdf_obj *pdfobj;
00218     copy = 1; /* By default, we copy most things */
00219     switch (state) {
00220       /* First three states are very similar.  In most cases we just
00221         ignore other postscript junk and don't change state */
00222     case 0:
00223     case 1:
00224     case 2:
00225       switch (*start) {
00226        /* Ignore arrays and procedures */
00227       case '[':
00228       case ']':  
00229       case '{':
00230       case '}':
00231        start += 1;
00232        if (state >= 2) 
00233          state = 2;
00234        break;
00235       case '(':
00236        pdfobj = parse_pdf_string (&start, end);
00237        if (pdfobj == NULL) {
00238          ERROR ("parse_header:  Error parsing a string in pfb header");
00239        }
00240        pdf_release_obj (pdfobj);
00241        if (state == 1) {
00242          if (filtered)
00243            sprintf ((char *)filtered_pointer, "/%s ", pfbs[pfb_id].fontname);
00244             filtered_pointer += strlen ((char *)filtered_pointer);
00245          copy = 0; /* Don't copy old string to output */
00246          lead = start; /* Forget what we've seen */
00247          state = 0;
00248        }
00249        if (state >= 2)
00250          state = 2;
00251        break;
00252       case '/':
00253        start += 1;
00254        ident = parse_ident (&start, end);
00255        if (state == 0 && !strcmp (ident, "FontName")) {
00256          state = 1;
00257        } else if (state == 0 && !strcmp (ident, "Encoding")) {
00258          state = 2;
00259          if (filtered && !pfbs[pfb_id].used_def_enc_chars) {
00260            sprintf ((char *)filtered_pointer, "/Encoding StandardEncoding readonly ");
00261             filtered_pointer += strlen ((char *)filtered_pointer);
00262          }
00263        } else if (state == 0 && !strcmp (ident, "FontBBox")) {
00264          state = 6;
00265        } else if (state == 0 && !strcmp (ident, "ItalicAngle")) {
00266          state = 8;
00267        } else if (state == 1) {
00268          if (filtered) {
00269            sprintf ((char *)filtered_pointer, "/%s ", pfbs[pfb_id].fontname);
00270            filtered_pointer += strlen ((char *)filtered_pointer);
00271           }
00272          copy = 0;   /* Don't copy old string to putput */
00273          lead = start;      /* Forget the name we've seen  */
00274          state = 0;
00275        }
00276        RELEASE (ident);
00277        break;
00278       default:
00279        ident = parse_ident (&start, end);
00280        if (state == 2 && !strcmp (ident, "def")) {
00281          /* Assume this is the end of the encoding */
00282          state = 0;
00283        } else if (state == 2 &&
00284            !strcmp (ident, "dup")) {
00285          copy = 0;   /* Don't copy this to output buffer until we
00286                         know if we want to keep it */  
00287          state = 3;
00288        } else if (state == 2 &&
00289                  !strcmp (ident, "StandardEncoding") &&
00290                  pfbs[pfb_id].int_encoding) {
00291          do_a_standard_enc(pfbs[pfb_id].int_encoding, standardencoding);
00292        } else if (state == 2 &&
00293                  !strcmp (ident, "ISOLatin1Encoding") &&
00294                  pfbs[pfb_id].int_encoding) {
00295          do_a_standard_enc(pfbs[pfb_id].int_encoding, isoencoding);
00296        }
00297        RELEASE (ident);
00298        break;
00299       }
00300       break;
00301     case 3:
00302       ident = parse_ident (&start, end);
00303       if (is_an_int (ident)) {
00304        last_number = (int) atof (ident);
00305        copy = 0;     /* We still don't know if we want to keep it */
00306        state = 4;
00307       } else {
00308        state = 2;    /* Contents back to "lead" will be flushed */
00309       }
00310       RELEASE (ident);
00311       break;
00312     case 4:
00313       if (*start == '/') {
00314        start += 1;
00315        glyph = parse_ident (&start, end);
00316        copy = 0;     /* We still don't know if we want to keep it.
00317                       Wait for a complete sequence before making
00318                       that decision */
00319        state = 5;
00320       } else {
00321        state = 2;
00322       }
00323       break;
00324     case 5:
00325       ident = parse_ident (&start, end);
00326       /* Here we either decide to keep or remove the encoding entry */
00327       if (ident != NULL && !strcmp (ident, "put") && 
00328          (int) last_number < 256 && (int) last_number >= 0) {
00329        skip_white(&start, end); /* Remove white space */
00330        lead = start;  /* Remove this entry (it may or may not be
00331                        replaced with a rewritten entry) */
00332        copy = 0;
00333        if (filtered && 
00334            pfbs[pfb_id].used_def_enc_chars &&
00335            (pfbs[pfb_id].used_def_enc_chars)[last_number]) {
00336          sprintf((char *) filtered_pointer, "dup %d /%s put\n",
00337                 last_number,
00338                 glyph);
00339           filtered_pointer += strlen ((char *) filtered_pointer);
00340        }
00341        /* Add this glyph to the internal encoding table for the pfb
00342         */
00343        if (pfbs[pfb_id].int_encoding &&
00344            (!(pfbs[pfb_id].int_encoding)[last_number])) {
00345          if ((pfbs[pfb_id].int_encoding)[last_number]) {
00346            RELEASE ((pfbs[pfb_id].int_encoding)[last_number]);
00347          }
00348          (pfbs[pfb_id].int_encoding)[last_number] = glyph;
00349          glyph = NULL; /* Prevent glyph from being released */
00350        }
00351       }
00352       if (glyph)
00353        RELEASE (glyph);
00354       if (ident != NULL)
00355        RELEASE (ident);
00356       state = 2;
00357       break;
00358     case 6:
00359       switch (*start) {
00360       case '[':
00361       case '{': 
00362        start += 1 ;
00363        state = 7;
00364        break;
00365       default:
00366        state = 0;    /* Something's probably wrong */
00367        fprintf (stderr, "\nUnexpected token after FontBBox.   Struggling along\n");
00368        dump (start, end);
00369       }
00370       break;
00371     case 7:
00372       switch (*start) {
00373       case ']':
00374       case '}':
00375        start += 1 ;
00376        state = 0;
00377        break;
00378       case '{':
00379       case '[':
00380       case '(':
00381       case '/':
00382        state = 0;    /* Something's probably wrong */
00383        fprintf (stderr, "\nUnexpected token in FontBBox array.  Struggling along\n");
00384        dump (start, end);
00385        break;
00386       default:
00387        ident = parse_ident (&start, end);
00388        if ((ident) && is_a_number (ident)) {
00389          pdf_obj *tmp = pdf_lookup_dict (pfbs[pfb_id].descriptor,
00390                                      "FontBBox");
00391          pdf_add_array (tmp, pdf_new_number (atof (ident)));
00392        }
00393        if (ident)
00394          RELEASE (ident);
00395       }
00396       break;
00397     case 8:
00398       switch (*start) {
00399       case '{': case '}': case '[': case ']': case '/':
00400        state = 0;
00401        break;
00402       default:
00403        ident = parse_ident (&start, end);
00404        if ((ident) && is_a_number (ident)) {
00405          double italic = atof(ident);
00406          if (italic != 0.0) {
00407            int flags = (int) pdf_number_value(pdf_lookup_dict (pfbs[pfb_id].descriptor,
00408                                                         "Flags"));
00409            pdf_add_dict (pfbs[pfb_id].descriptor, 
00410                        pdf_new_name ("ItalicAngle"),
00411                        pdf_new_number (italic));
00412            pdf_add_dict (pfbs[pfb_id].descriptor,
00413                        pdf_new_name ("Flags"),
00414                        pdf_new_number (flags+ITALIC));
00415          }
00416        }
00417        if (ident)
00418          RELEASE (ident);
00419        state = 0;
00420       }
00421     }
00422     skip_white (&start, end);
00423     if (state >=2 && state <= 5 && !pfbs[pfb_id].used_def_enc_chars) {
00424       lead = start;
00425     }
00426     if (copy && start != lead) { /* Flush everything back to "lead" */
00427       if (filtered) {
00428        memcpy (filtered_pointer, lead, start-lead);
00429        filtered_pointer += start-lead;
00430       }
00431       lead = start;
00432     }
00433   }
00434 #ifdef MEM_DEBUG
00435   MEM_END
00436 #endif /* MEM_DEBUG */
00437   return filtered? filtered_pointer-filtered: length;
00438 }
00439 
00440 static void dump_glyphs( char **glyphs, int n, int show_index)
00441 {
00442   int i;
00443   for (i=0; i<n; i++) {
00444     if (show_index)
00445       fprintf (stderr, "(%d", i);
00446     if (glyphs[i])
00447       fprintf (stderr, "/%s", glyphs[i]);
00448     else
00449       fprintf (stderr, "(null)");
00450     if (show_index)
00451       fprintf (stderr, ")");
00452   }
00453   return;
00454 }
00455 static void dump_used( char *used_chars)
00456 {
00457   int i;
00458   for (i=0; i<256; i++)
00459     fprintf (stderr, "(%d/%d)", i, used_chars[i]);
00460   return;
00461 }
00462 
00463 
00464 #define ASCII 1
00465 #define BINARY 2
00466 
00467 static int is_a_pfb (FILE *file)
00468 {
00469   int result, ch;
00470   if ((ch = fgetc (file)) == 128 &&
00471       ((ch = fgetc (file)) == ASCII ||
00472        (ch == BINARY))) {
00473     result = 1;
00474   } else 
00475     result = 0;
00476   rewind (file);
00477   return result;
00478 }
00479 
00480 static unsigned char *get_pfb_segment (unsigned long *length,
00481                                    FILE *file, int expected_type)
00482 {
00483   unsigned char *buffer = NULL;
00484   unsigned long nread;
00485   unsigned long new_length;
00486   int stream_type, ch;
00487 
00488   *length = 0;
00489   /* Unfortunately, there can be several segments that need to be
00490      concatenated, so we loop through all of them */
00491   for (;;) {
00492     if ((ch = fgetc (file)) < 0) /* Some files don't terminate
00493                                 properly */
00494       break;
00495     if (ch != 128){
00496       sprintf (work_buffer, "get_pfb_segment:  Not a pfb file.\n");
00497       sprintf (work_buffer, "get_pfb_segment:  pfb header has %d, expecting 128\n", ch);
00498       ERROR (work_buffer);
00499     }
00500     if ((stream_type = fgetc (file)) < 0 || stream_type != expected_type) {
00501       seek_relative (file, -2); /* Backup up two (yuck!) */
00502       break;
00503     }
00504     new_length = get_low_endian_quad (file);
00505     if (verbose > 4) {
00506       fprintf (stderr, "Length of next PFB segment: %ld\n",
00507               new_length);
00508     }
00509     buffer = RENEW (buffer, (*length)+new_length, unsigned char);
00510     if ((nread = fread(buffer+(*length), sizeof(unsigned char), new_length, file)) !=
00511        new_length) {
00512       fprintf (stderr, "Found only %ld/%ld bytes\n", nread, new_length);
00513       ERROR ("type1_do_pfb_segment:  Are you sure this is a pfb?");
00514     }
00515     *length += new_length;
00516   }
00517   if (*length == 0) {
00518     ERROR ("type1_get_pfb_segment: Segment length is zero");
00519   }
00520   if (expected_type == ASCII) {
00521     int i;
00522     for (i=0; i<(*length); i++) {
00523       if (buffer[i] == '\r')
00524        buffer[i] = '\n';  /* Show my Unix prejudice */
00525     }
00526   }
00527   return buffer;
00528 }
00529 
00530 static unsigned int glyph_length (char **glyphs) 
00531 {
00532   int i;
00533   unsigned result = 0;
00534   for (i=0; i<256; i++) {
00535     result += strlen (glyphs[i]);
00536   }
00537   return result;
00538 }
00539 
00540 static char *pfb_find_name (FILE *pfb_file) 
00541 {
00542   unsigned char *buffer;
00543   unsigned long length = 0;
00544   char *start, *end, *fontname;
00545   int state = 0;
00546 #ifdef MEM_DEBUG
00547   MEM_START
00548 #endif
00549   rewind (pfb_file);
00550   buffer = get_pfb_segment (&length, pfb_file, ASCII);
00551   /* State definitions 
00552      state 0: Initial state
00553      state 1: Saw /FontName */
00554   start = (char *) buffer;
00555   end = start+length;
00556   skip_white (&start, end);
00557   fontname = NULL;
00558   while (start < end && fontname == NULL) {
00559     char *ident;
00560     pdf_obj *pdfobj;
00561     switch (*start) {
00562       /* Ignore arrays and procedures */
00563     case '[':
00564     case ']':  
00565     case '{':
00566     case '}':
00567       start += 1;
00568       if (state == 1) {
00569        ERROR ("Garbage following /FontName");
00570       }
00571       break;
00572     case '(':
00573       pdfobj = parse_pdf_string (&start, end);
00574       if (pdfobj == NULL) {
00575        ERROR ("parse_header:  Error parsing a string in pfb header");
00576       }
00577       if (state == 1) { /* This string must be the font name */
00578        char *tmp = pdf_string_value (pdfobj);
00579        fontname = NEW (strlen(tmp)+1, char);
00580        memcpy (fontname, tmp, strlen(tmp)+1);
00581       }
00582       pdf_release_obj (pdfobj);
00583       break;
00584     case '/':
00585       start += 1;
00586       ident = parse_ident (&start, end);
00587       if (state == 0 && !strcmp (ident, "FontName")) {
00588        state = 1;
00589       } else if (state == 1) {
00590        fontname = NEW (strlen(ident)+1, char);
00591        memcpy (fontname, ident, strlen(ident)+1);
00592       }
00593       RELEASE (ident);
00594       break;
00595     default:
00596       ident = parse_ident (&start, end);
00597       RELEASE (ident);
00598       break;
00599     }
00600     skip_white (&start, end);
00601   }
00602   RELEASE (buffer);
00603 #ifdef MEM_DEBUG
00604   MEM_END
00605 #endif /* MEM_DEBUG */
00606   return fontname;
00607 }
00608 
00609 static void pfb_add_to_used_glyphs (int pfb_id, char *glyph)
00610 {
00611   if (pfb_id >= 0 && pfb_id < num_pfbs && glyph) {
00612     if (pfbs[pfb_id].n_used_glyphs == 0 ||
00613        !bsearch (glyph, pfbs[pfb_id].used_glyphs,
00614                 pfbs[pfb_id].n_used_glyphs,
00615                 sizeof (char *), glyph_match)) {
00616       if (pfbs[pfb_id].n_used_glyphs+1 >=
00617          pfbs[pfb_id].max_used_glyphs) {
00618        pfbs[pfb_id].max_used_glyphs += 16;
00619        pfbs[pfb_id].used_glyphs = RENEW (pfbs[pfb_id].used_glyphs,
00620                                      pfbs[pfb_id].max_used_glyphs,
00621                                      char *);
00622       }
00623       (pfbs[pfb_id].used_glyphs)[pfbs[pfb_id].n_used_glyphs] = 
00624        NEW (strlen(glyph)+1, char);
00625       strcpy((pfbs[pfb_id].used_glyphs)[pfbs[pfb_id].n_used_glyphs],
00626             glyph);
00627       pfbs[pfb_id].n_used_glyphs += 1;
00628       qsort (pfbs[pfb_id].used_glyphs, pfbs[pfb_id].n_used_glyphs, 
00629             sizeof (char *), glyph_cmp);
00630     }
00631   }
00632 }
00633 
00634 static char *new_used_chars (void)
00635 {
00636   char *result;
00637   int i;
00638   result = NEW (256, char);
00639   for (i=0; i<256; i++) {
00640     result[i] = 0;
00641   }
00642   return result;
00643 }
00644 
00645 /* Mark the character at position "code" as used in the pfb font
00646    corresponding to "pfb_id" */
00647 static void pfb_add_to_used_chars (int pfb_id, unsigned code)
00648 {
00649   if (pfb_id >= 0 && pfb_id < num_pfbs && code < 256) {
00650     if (!pfbs[pfb_id].used_def_enc_chars) {
00651       pfbs[pfb_id].used_def_enc_chars = new_used_chars();
00652     }
00653     (pfbs[pfb_id].used_def_enc_chars)[code] = 1;
00654   }
00655   if (code >= 256)
00656     ERROR ("pfb_add_to_used_chars(): code >= 256");
00657   return;
00658 }
00659 
00660 static unsigned long do_pfb_header (FILE *file, int pfb_id)
00661 {
00662   unsigned char *buffer, *filtered = NULL;
00663   unsigned long length = 0;
00664 #ifdef MEM_DEBUG
00665 MEM_START
00666 #endif
00667   buffer = get_pfb_segment (&length, file, ASCII);
00668   if (partial_enabled) {
00669     filtered = NEW (length+strlen(pfbs[pfb_id].fontname)+1+1024, unsigned
00670                   char);
00671   }
00672   /* We must parse the header even if not doing font subsetting so
00673      that we can determine the parameters for the font descriptor.
00674      parse_head() won't write to a null pointer */
00675   length = parse_header (filtered, buffer, length, pfb_id);
00676   if (filtered) {    
00677     pdf_add_stream (pfbs[pfb_id].direct, (char *) filtered, length);
00678     RELEASE (filtered);
00679   } else {
00680     pdf_add_stream (pfbs[pfb_id].direct, (char *) buffer, length);
00681   }
00682   RELEASE (buffer);
00683 #ifdef MEM_DEBUG
00684 MEM_END
00685 #endif
00686   return length;
00687 }
00688 
00689 
00690 static unsigned long parse_body (unsigned char *filtered, unsigned char
00691                              *unfiltered, unsigned long length, 
00692                              char **used_glyphs, unsigned *n_used,
00693                              pdf_obj *descriptor)
00694 {
00695   char *start, *end, *tail, *ident;
00696   unsigned char *filtered_pointer;
00697   double last_number = 0.0;
00698   int state = 0;
00699   if (verbose > 2) {
00700     fprintf (stderr, "\nSearching for following glyphs in font:\n");
00701     dump_glyphs (used_glyphs, *n_used, 0);
00702   }
00703   start = (char *) unfiltered, end = (char *) unfiltered+length;
00704   /* Skip first four bytes */
00705   tail = start; filtered_pointer = filtered;
00706   start += 4;
00707   /* Skip everything up to the charstrings section */
00708   while (start < end) {
00709     pdf_obj *pdfobj;
00710     skip_white (&start, end);
00711     /* Very simple state machine
00712        state = 0: nothing special
00713        state = 1: Saw StdVW, but waiting for number after it */
00714     switch (*start) {
00715     case '[':
00716     case ']':
00717     case '{':
00718     case '}':
00719       start += 1;
00720       continue;
00721     case '(':
00722       pdfobj = parse_pdf_string (&start, end);
00723       if (pdfobj == NULL) {
00724        ERROR ("Error processing a string in a PFB file.");
00725       }
00726       pdf_release_obj (pdfobj);
00727       continue;
00728     case '/':
00729       start += 1;
00730       if ((ident = parse_ident (&start, end)) &&
00731          !strcmp ((char *) ident, "CharStrings")) {
00732        RELEASE (ident);
00733        break;
00734       } else if (ident && !strcmp ((char *) ident, "StdVW")) {
00735        state = 1; /* Saw StdVW */
00736       }
00737       if (ident) {
00738        RELEASE (ident);
00739       } else {
00740        fprintf (stderr, "\nError processing identifier in PFB file.\n");
00741        dump (start, end);
00742       }
00743       continue;
00744     default:
00745       ident = parse_ident (&start, end);
00746       if (ident == NULL)
00747        ERROR ("Error processing a symbol in the PFB file.");
00748       if (is_an_int(ident))
00749        if (state == 1) {
00750          pdf_add_dict (descriptor, pdf_new_name ("StemV"),
00751                      pdf_new_number (atof (ident)));
00752          state = 0;  /* Return to normal processing */
00753        } else
00754          last_number = atof (ident); /* Might be start of RD */
00755       else {
00756        if (!strcmp (ident, "RD") ||
00757            !strcmp (ident, "-|")) {
00758          start += ((unsigned long) last_number) + 1;
00759        }
00760       }
00761       RELEASE (ident);
00762       continue;
00763     }
00764     break;
00765   }
00766   if (start >= end)
00767     ERROR ("Unexpected end of binary portion of PFB file");
00768   /* Copy what we have so far over to the new buffer */
00769   if (filtered) {
00770     memcpy (filtered_pointer, tail, start-tail);
00771     /* Advance pointer into new buffer */
00772     filtered_pointer += (start-tail);
00773   }
00774   /* At this point, start is positioned just before the beginning of the glyphs, just after
00775      the word /CharStrings.  The earlier portion of the input buffer has
00776      been copied to the output.  The remainder of the routine need not
00777      be executed if not doing font subsetting */  
00778   if (filtered) {
00779     char **this_glyph;
00780     sprintf ((char *) filtered_pointer, " %d", *n_used);
00781     filtered_pointer += strlen ((char *) filtered_pointer);
00782     skip_white(&start, end);
00783     /* The following ident *should* be the number of glyphs in this
00784        file */
00785     ident = parse_ident (&start, end);
00786     if (verbose>1) {
00787       fprintf (stderr, "\n  Embedding %d of %s glyphs\n", *n_used, ident);
00788     }
00789     if (ident == NULL || !is_an_int (ident) || *n_used > atof (ident)) 
00790       ERROR ("More glyphs needed than present in file");
00791     RELEASE (ident);
00792     tail = start;
00793     while (start < end && *start != '/') start++;
00794     if (filtered) {
00795       memcpy (filtered_pointer, tail, start-tail);
00796       filtered_pointer += (start-tail);
00797     }
00798     /* Now we are exactly at the beginning of the glyphs */
00799     while (start < end && *start == '/') {
00800       char *glyph;
00801       tail = start;
00802       start += 1;
00803       glyph = parse_ident (&start, end);
00804       /* Get the number that should follow the glyph name */
00805       skip_white(&start, end);
00806       ident = parse_ident (&start, end);
00807       if (!is_an_int (ident))
00808        ERROR ("Expecting an integer after glyph name");
00809       last_number = atof (ident);
00810       RELEASE (ident);
00811       /* The next identifier should be a "RD" or a "-|".  We don't
00812         really care what it is */
00813       skip_white(&start, end);
00814       ident = parse_ident (&start, end);
00815       RELEASE (ident);
00816       /* Skip a blank */
00817       start += 1;
00818       /* Skip the binary stream */
00819       start += (unsigned long) last_number;
00820       /* Skip the "ND" or "|-" terminator */
00821       skip_white(&start, end);
00822       ident = parse_ident (&start, end);
00823       RELEASE (ident);
00824       skip_white (&start, end);
00825       if (*n_used != 0 && (this_glyph = bsearch (glyph, used_glyphs, *n_used, sizeof (char *),
00826                                           glyph_match))) {
00827        memcpy (filtered_pointer, tail, start-tail);
00828        filtered_pointer += start-tail;
00829        (*n_used)--;
00830        /* Remove glyph and rearrange used_glyphs array */
00831        {
00832          RELEASE (*this_glyph);
00833          (*this_glyph) = used_glyphs[*n_used];
00834          qsort (used_glyphs, *n_used, sizeof (char *), glyph_cmp);
00835        }
00836       }
00837       RELEASE (glyph);
00838     }
00839     if (*n_used != 0) {
00840       fprintf (stderr,  "Didn't find following required glyphs in the font:\n");
00841       dump_glyphs (used_glyphs, *n_used, 0);
00842       ERROR ("Possibly the encoding is incorrect.");
00843     }
00844     /* Include the rest of the file verbatim */
00845     if (start < end){
00846       memcpy (filtered_pointer, start, end-start);
00847       filtered_pointer += end-start;
00848     }
00849     if (verbose>1) {
00850       fprintf (stderr, "  (subsetting eliminated %ld bytes)", length-(filtered_pointer-filtered));
00851     }
00852   }
00853   return (filtered? filtered_pointer-filtered: length);
00854 }
00855 
00856 static unsigned long do_pfb_body (FILE *file, int pfb_id)
00857 {
00858   int i;
00859   unsigned char *buffer=NULL, *filtered=NULL;
00860   unsigned long length=0;
00861 #ifdef MEM_DEBUG
00862   MEM_START
00863 #endif
00864   buffer = get_pfb_segment (&length, file, BINARY);
00865   /* We need to decrypt the binary
00866      portion of the pfb */
00867   t1_crypt_init(EEKEY);
00868   for (i=0; i<length; i++) {
00869     buffer[i] = t1_decrypt(buffer[i]);
00870   }
00871   if (partial_enabled) {
00872     filtered = NEW (length, unsigned char);
00873   }
00874   length = parse_body (filtered, buffer, length, 
00875                      pfbs[pfb_id].used_glyphs,
00876                      &pfbs[pfb_id].n_used_glyphs,
00877                      pfbs[pfb_id].descriptor);
00878   /* And reencrypt the whole thing */
00879   t1_crypt_init (EEKEY);
00880   for (i=0; i<length; i++) {
00881     buffer[i] = t1_encrypt(partial_enabled? filtered[i]: buffer[i]);
00882   }
00883   if (filtered)
00884     RELEASE (filtered);
00885   pdf_add_stream (pfbs[pfb_id].direct, (char *) buffer, length);
00886   RELEASE (buffer);
00887 #ifdef MEM_DEBUG
00888   MEM_START
00889 #endif
00890   return length;
00891 }
00892 
00893 static unsigned long do_pfb_trailer (FILE *file, pdf_obj *stream)
00894 {
00895   unsigned char *buffer;
00896   unsigned long length;
00897   buffer = get_pfb_segment (&length, file, ASCII);
00898   pdf_add_stream (stream, (char *) buffer, length);
00899   RELEASE (buffer);
00900   return length;
00901 }
00902 
00903 
00904 static pdf_obj *type1_fontfile (int pfb_id) 
00905 {
00906   if (pfb_id >= 0 && pfb_id < num_pfbs)
00907     return pdf_link_obj(pfbs[pfb_id].indirect);
00908   else
00909     return NULL;
00910 }
00911 
00912 static char *type1_fontname (int pfb_id)
00913 {
00914   if (pfb_id >= 0 && pfb_id < num_pfbs)
00915     return pfbs[pfb_id].fontname;
00916   else
00917     return NULL;
00918 }
00919 
00920 /* Mangle_fontname mangles the name in place.  fontname
00921    must be big enough to add seven characters */
00922 
00923 static void mangle_fontname(char *fontname)
00924 {
00925   int i;
00926   char ch;
00927   static char first = 1;
00928   memmove (fontname+7, fontname, strlen(fontname)+1);
00929   /* The following procedure isn't very random, but it
00930      doesn't need to be for this application. */
00931   if (first) {
00932     srand (time(NULL));
00933     first = 0;
00934   }
00935   for (i=0; i<6; i++) {
00936     ch = rand() % 26;
00937     fontname[i] = ch+'A';
00938   }
00939   fontname[6] = '+';
00940 }
00941 
00942 
00943 /* This routine builds a default font descriptor with dummy values
00944    filled in for the required keys.  As the pfb file is parsed,
00945    any values that are found are rewritten.  By doing this,
00946    all the required fields are found in the font descriptor
00947    even if the pfb is somewhat defective. This approach is
00948    conservative, with the cost of keeping the names around in memory 
00949    for a while.
00950 */
00951 
00952 static void type1_start_font_descriptor (int pfb_id)
00953 {
00954   pdf_obj *tmp1;
00955   pfbs[pfb_id].descriptor = pdf_new_dict ();
00956   pdf_add_dict (pfbs[pfb_id].descriptor,
00957               pdf_new_name ("Type"),
00958               pdf_new_name ("FontDescriptor"));
00959   /* For now, insert dummy values */
00960   pdf_add_dict (pfbs[pfb_id].descriptor,
00961               pdf_new_name ("CapHeight"),
00962               pdf_new_number (850.0)); /* This number is arbitrary */
00963   pdf_add_dict (pfbs[pfb_id].descriptor,
00964               pdf_new_name ("Ascent"),
00965               pdf_new_number (850.0));    /* This number is arbitrary */
00966   pdf_add_dict (pfbs[pfb_id].descriptor,
00967               pdf_new_name ("Descent"),
00968               pdf_new_number (-200.0));
00969   tmp1 = pdf_new_array ();
00970   pdf_add_dict (pfbs[pfb_id].descriptor, pdf_new_name ("FontBBox"), tmp1);
00971   pdf_add_dict (pfbs[pfb_id].descriptor,
00972               pdf_new_name ("FontName"),
00973               pdf_new_name (type1_fontname(pfb_id)));
00974 
00975   pdf_add_dict (pfbs[pfb_id].descriptor,
00976               pdf_new_name ("ItalicAngle"),
00977               pdf_new_number(0.0));
00978   pdf_add_dict (pfbs[pfb_id].descriptor,
00979               pdf_new_name ("StemV"),  /* StemV is required, StemH
00980                                        is not */
00981               pdf_new_number (STEMV)); /* Use a default value */
00982   /* You don't need a fontfile for the standard fonts */
00983   if (pfb_id >= 0)
00984     pdf_add_dict (pfbs[pfb_id].descriptor,
00985                 pdf_new_name ("FontFile"),
00986                 type1_fontfile (pfb_id));
00987 
00988   pdf_add_dict (pfbs[pfb_id].descriptor,
00989               pdf_new_name ("Flags"),
00990               pdf_new_number (SYMBOLIC));  /* Treat all fonts as symbolic */
00991   return;
00992 }
00993 
00994 static int pfb_get_id (const char *pfb_name)
00995 {
00996   int i;
00997   for (i=0; i<num_pfbs; i++) {
00998     if (pfbs[i].pfb_name && !strcmp (pfbs[i].pfb_name, pfb_name))
00999       break;
01000   }
01001   if (i == num_pfbs) { /* This font not previously called for */
01002     FILE *pfb_file = NULL;
01003     char *full_pfb_name, *short_fontname;
01004     if (!(full_pfb_name = kpse_find_file (pfb_name, kpse_type1_format,
01005                                 1)) || 
01006        !(pfb_file = MFOPEN (full_pfb_name, FOPEN_RBIN_MODE)) ||
01007        !(is_a_pfb (pfb_file))) {
01008       if (pfb_file)
01009        MFCLOSE (pfb_file);
01010       i = -1;
01011     } else {
01012       short_fontname = pfb_find_name (pfb_file);
01013       MFCLOSE (pfb_file);
01014       if (num_pfbs >= max_pfbs) {
01015        max_pfbs += MAX_FONTS;
01016        pfbs = RENEW (pfbs, max_pfbs, struct a_pfb);
01017       }
01018       num_pfbs += 1;
01019       init_a_pfb (pfbs+i);
01020       pfbs[i].pfb_name = NEW (strlen(pfb_name)+1, char);
01021       strcpy (pfbs[i].pfb_name, pfb_name);
01022       pfbs[i].direct = pdf_new_stream(STREAM_COMPRESS);
01023       pfbs[i].indirect = pdf_ref_obj (pfbs[i].direct);
01024       if (partial_enabled) {
01025        pfbs[i].fontname = NEW (strlen(short_fontname)+8, char);
01026        strcpy (pfbs[i].fontname, short_fontname);
01027        mangle_fontname(pfbs[i].fontname);
01028       }
01029       else {
01030        pfbs[i].fontname = NEW (strlen(short_fontname)+1, char);
01031        strcpy (pfbs[i].fontname, short_fontname);
01032       }
01033       type1_start_font_descriptor(i);
01034       if (short_fontname)
01035        RELEASE (short_fontname);
01036     }
01037   }
01038   return i;
01039 }
01040 
01041 static void pfb_release (int id)
01042 {
01043   if (id >= 0 && id < num_pfbs) {
01044     pdf_release_obj (pfbs[id].direct);
01045     RELEASE (pfbs[id].pfb_name);
01046     pdf_release_obj (pfbs[id].indirect);
01047     RELEASE (pfbs[id].fontname);
01048     if (pfbs[id].used_def_enc_chars)
01049       RELEASE (pfbs[id].used_def_enc_chars);
01050     if (pfbs[id].int_encoding){
01051       int i;
01052       for (i=0; i<256; i++) {
01053        if ((pfbs[id].int_encoding)[i])
01054          RELEASE ((pfbs[id].int_encoding)[i]);
01055       }
01056       RELEASE (pfbs[id].int_encoding);
01057     }
01058     if (pfbs[id].used_glyphs) {
01059       unsigned i;
01060       for (i=0; i<pfbs[id].n_used_glyphs; i++) {
01061        RELEASE ((pfbs[id].used_glyphs)[i]);
01062       }
01063       RELEASE (pfbs[id].used_glyphs);
01064     }
01065   }
01066 }
01067 
01068 static void release_glyphs (char **glyphs)
01069 {
01070   int i;
01071   for (i=0; i<256; i++) {
01072     RELEASE (glyphs[i]);
01073   }
01074 }
01075 
01076 static void do_pfb (int pfb_id)
01077 {
01078   char *full_pfb_name;
01079   FILE *type1_binary_file;
01080   pdf_obj *stream_dict;
01081   unsigned long length1, length2, length3;
01082   int ch;
01083   full_pfb_name = kpse_find_file (pfbs[pfb_id].pfb_name, kpse_type1_format,
01084                               1);
01085   if (verbose == 1)
01086     fprintf (stderr, "(PFB:%s", pfbs[pfb_id].pfb_name);
01087   if (verbose > 1)
01088     fprintf (stderr, "(PFB:%s", full_pfb_name);
01089   if (full_pfb_name == NULL ||
01090       (type1_binary_file = MFOPEN (full_pfb_name, FOPEN_RBIN_MODE)) == NULL) {
01091     fprintf (stderr, "type1_fontfile:  Unable to find or open binary font file (%s)",
01092             pfbs[pfb_id].pfb_name);
01093     ERROR ("This existed when I checked it earlier!");
01094     return;
01095   }
01096   /* Following section doesn't hide PDF stream structure very well */
01097   length1 = do_pfb_header (type1_binary_file, pfb_id);
01098   /* The following section seems determines which, if any,
01099      glyphs were used via the internal encoding, which hasn't
01100      been known until now.*/
01101   if (partial_enabled) {
01102     int j;
01103     if (verbose > 2) {
01104       fprintf (stderr, "Default encoding:\n");
01105       dump_glyphs (pfbs[pfb_id].int_encoding, 256, 1);
01106     }
01107     if (pfbs[pfb_id].used_def_enc_chars) {
01108       if (verbose > 2)
01109        fprintf (stderr, "\nRetaining portion of default encoding:\n");
01110       for (j=0; j<256; j++) {
01111        if ((pfbs[pfb_id].used_def_enc_chars)[j]) {
01112          if (verbose > 2)
01113            fprintf (stderr, "(%d/%s)", j, (pfbs[pfb_id].int_encoding)[j]);
01114          pfb_add_to_used_glyphs (pfb_id, (pfbs[pfb_id].int_encoding)[j]);
01115        }
01116       }
01117     }
01118   }
01119   length2 = do_pfb_body (type1_binary_file, pfb_id);
01120   length3 = do_pfb_trailer (type1_binary_file, pfbs[pfb_id].direct);
01121   if ((ch = fgetc (type1_binary_file)) != 128 ||
01122       (ch = fgetc (type1_binary_file)) != 3) {
01123     fprintf (stderr, "\n\nWarning:  PFB file may be improperly terminated\n");
01124   }
01125   /* Got entire file! */
01126   if (verbose > 1)
01127     fprintf (stderr, "\n  Embedded size: %ld bytes\n", length1+length2+length3);
01128   if (verbose) {
01129     fprintf (stderr, ")");
01130   }
01131   MFCLOSE (type1_binary_file);
01132   stream_dict = pdf_stream_dict (pfbs[pfb_id].direct);
01133   pdf_add_dict (stream_dict, pdf_new_name("Length1"),
01134               pdf_new_number (length1));
01135   pdf_add_dict (stream_dict, pdf_new_name("Length2"),
01136               pdf_new_number (length2));
01137   pdf_add_dict (stream_dict, pdf_new_name("Length3"),
01138               pdf_new_number (length3));
01139   /* Finally, flush the descriptor */
01140   pdf_release_obj (pfbs[pfb_id].descriptor);
01141   return;
01142 }
01143 
01144 void pfb_flush_all (void)
01145 {
01146   int i;
01147   for (i=0; i<num_pfbs; i++) {
01148     do_pfb(i);
01149     pfb_release (i);
01150   }
01151   if (pfbs)
01152     RELEASE (pfbs);
01153 }
01154 
01155 struct a_type1_font
01156 {
01157   pdf_obj *indirect, *encoding;
01158   long pfb_id;
01159   int encoding_id;
01160   char *used_chars;
01161 } *type1_fonts = NULL;
01162 int num_type1_fonts = 0, max_type1_fonts = 0;
01163 
01164 
01165 static void init_a_type1_font (struct a_type1_font *this_type1_font) 
01166 {
01167   if (partial_enabled) {
01168     this_type1_font -> used_chars = new_used_chars ();
01169   } else {
01170     this_type1_font -> used_chars = NULL;
01171   }
01172 }
01173 
01174 pdf_obj *type1_font_resource (int type1_id)
01175 {
01176   if (type1_id>=0 && type1_id<max_type1_fonts)
01177     return pdf_link_obj(type1_fonts[type1_id].indirect);
01178   else {
01179     ERROR ("Invalid font id in type1_font_resource");
01180     return NULL;
01181   }
01182 }
01183 
01184 char *type1_font_used (int type1_id)
01185 {
01186   char *result;
01187   if (type1_id>=0 && type1_id<max_type1_fonts) {
01188     result = type1_fonts[type1_id].used_chars;
01189   } else {
01190     fprintf (stderr, "type1_font_used: type1_id=%d\n", type1_id);
01191     ERROR ("Invalid font id in type1_font_used");
01192   }
01193   return result;
01194 }
01195 
01196 
01197 static int is_a_base_font (const char *name)
01198 {
01199   static char *basefonts[] = {
01200     "Courier",                     "Courier-Bold",             "Courier-Oblique",
01201     "Courier-BoldOblique",  "Helvetica",         "Helvetica-Bold",
01202     "Helvetica-Oblique",    "Helvetica-BoldOblique",    "Symbol",
01203     "Times-Roman",          "Times-Bold",        "Times-Italic",
01204     "Times-BoldItalic",            "ZapfDingbats"
01205   };
01206   int i;
01207   for (i=0; i<14; i++) {
01208     if (!strcmp (name, basefonts[i]))
01209       return 1;
01210   }
01211   return 0;
01212 }
01213 
01214 int type1_font (const char *map_name, int tfm_font_id, char
01215               *resource_name, int encoding_id, int remap) 
01216 {
01217   int i, result = -1;
01218   int tfm_firstchar, tfm_lastchar;
01219   int pdf_firstchar, pdf_lastchar;
01220   int pfb_id = -1;
01221   pdf_obj *font_resource, *tmp1, *font_encoding_ref;
01222 
01223   if (num_type1_fonts >= max_type1_fonts) {
01224     max_type1_fonts = MAX (max_type1_fonts+MAX_FONTS, num_type1_fonts+1);
01225     type1_fonts = RENEW (type1_fonts, max_type1_fonts, struct
01226                       a_type1_font);
01227   }
01228 
01229   if ((map_name && is_a_base_font(map_name)) ||
01230       (pfb_id = pfb_get_id(map_name)) >= 0) {
01231     /* Looks like we have a physical font (either a reader font or a
01232        Type 1 font binary file).  */
01233     init_a_type1_font (type1_fonts+num_type1_fonts);
01234     type1_fonts[num_type1_fonts].pfb_id = pfb_id;
01235     type1_fonts[num_type1_fonts].encoding_id = encoding_id;
01236   /* Allocate a dictionary for the physical font */
01237     font_resource = pdf_new_dict ();
01238     if (type1_fonts[num_type1_fonts].encoding_id >= 0) {
01239       font_encoding_ref = encoding_ref (encoding_id);
01240       pdf_add_dict (font_resource,
01241                   pdf_new_name ("Encoding"),
01242                   font_encoding_ref);
01243     }
01244     pdf_add_dict (font_resource,
01245                 pdf_new_name ("Type"),
01246                 pdf_new_name ("Font"));
01247     pdf_add_dict (font_resource,
01248                 pdf_new_name ("Subtype"),
01249                 pdf_new_name ("Type1"));
01250     pdf_add_dict (font_resource, 
01251                 pdf_new_name ("Name"),
01252                 pdf_new_name (resource_name));
01253     if (type1_fonts[num_type1_fonts].pfb_id >= 0) {
01254       pdf_add_dict (font_resource, 
01255                   pdf_new_name ("FontDescriptor"),
01256                   pdf_ref_obj(pfbs[type1_fonts[num_type1_fonts].pfb_id].descriptor));
01257     }
01258       /* If we are embedding this font, it may have been used by another virtual
01259         font and we need to use the same mangled name.  Mangled
01260         names are known only to the pfb module, so we call it to get
01261         the name */
01262     if (type1_fonts[num_type1_fonts].pfb_id >= 0) {
01263       pdf_add_dict (font_resource, 
01264                   pdf_new_name ("BaseFont"),
01265                   pdf_new_name
01266                   (type1_fontname(type1_fonts[num_type1_fonts].pfb_id)));
01267        /* Otherwise we use the base name */
01268     } else {
01269       pdf_add_dict (font_resource,
01270                   pdf_new_name ("BaseFont"),
01271                   pdf_new_name (map_name));
01272     }
01273     if (!(map_name && is_a_base_font (map_name))) {
01274       tfm_firstchar = tfm_get_firstchar(tfm_font_id);
01275       tfm_lastchar = tfm_get_lastchar(tfm_font_id);
01276       if (remap) {
01277        unsigned char t;
01278        pdf_firstchar=255; pdf_lastchar=0;
01279        for (i=tfm_firstchar; i<=tfm_lastchar; i++) {
01280          if ((t=twiddle(i)) < pdf_firstchar)
01281            pdf_firstchar = t;
01282          if (t > pdf_lastchar)
01283            pdf_lastchar = t;
01284        }
01285       } else {
01286        pdf_firstchar = tfm_firstchar;
01287        pdf_lastchar = tfm_lastchar;
01288       }
01289       pdf_add_dict (font_resource,
01290                   pdf_new_name ("FirstChar"),
01291                   pdf_new_number (pdf_firstchar));
01292       pdf_add_dict (font_resource,
01293                   pdf_new_name ("LastChar"),
01294                   pdf_new_number (pdf_lastchar));
01295       tmp1 = pdf_new_array ();
01296       for (i=pdf_firstchar; i<=pdf_lastchar; i++) {
01297        if (remap) {
01298          int t;
01299          if ((t=untwiddle(i)) <= tfm_lastchar && t>=tfm_firstchar)
01300            pdf_add_array (tmp1,
01301                         pdf_new_number(ROUND(tfm_get_width
01302                                           (tfm_font_id,t)*1000.0,0.1)));
01303          else
01304            pdf_add_array (tmp1,
01305                         pdf_new_number(0.0));
01306        } else
01307          pdf_add_array (tmp1,
01308                       pdf_new_number(ROUND(tfm_get_width
01309                                          (tfm_font_id, i)*1000.0,0.1)));
01310       }
01311       pdf_add_dict (font_resource,
01312                   pdf_new_name ("Widths"),
01313                   tmp1);
01314     }
01315     type1_fonts[num_type1_fonts].indirect = pdf_ref_obj(font_resource);
01316     pdf_release_obj (font_resource);
01317     result = num_type1_fonts;
01318     num_type1_fonts += 1;
01319   } else { /* Don't have a physical font */
01320     result = -1;
01321   }
01322   return result;
01323 }
01324 
01325 
01326 void type1_close_all (void)
01327 {
01328   int i, j;
01329   /* Three arrays are created by this module and need to be released */
01330   /* First, each TeX font name that ends up as a postscript font gets
01331      added to type1_fonts (yes, even Times-Roman, etc.) */
01332   /* The first thing to do is to resolve all character references to 
01333      actual glyph references.  If an external encoding is specified,
01334      we simply look up the glyph name in the encoding.  If the internal
01335      encoding is being used, we add it to the used_chars array of
01336      the internal encoding */
01337   for (i=0; i<num_type1_fonts; i++) {
01338     /* If font subsetting is enabled, each used character needs
01339        to be added to the used_glyphs array in the corresponding pfb
01340     */
01341     if (partial_enabled) {
01342       /* We always consider .notdef to be used */
01343       pfb_add_to_used_glyphs (type1_fonts[i].pfb_id, ".notdef");
01344       for (j=0; j<256; j++) {
01345        char *glyph;
01346        if (type1_fonts[i].pfb_id >= 0 &&
01347            type1_fonts[i].encoding_id >= 0 &&
01348            (type1_fonts[i].used_chars)[j]) {
01349          glyph = encoding_glyph (type1_fonts[i].encoding_id,
01350                                    j);
01351          pfb_add_to_used_glyphs (type1_fonts[i].pfb_id, glyph);
01352        }
01353        if (type1_fonts[i].pfb_id >= 0 &&
01354            type1_fonts[i].encoding_id < 0 &&
01355            (type1_fonts[i].used_chars)[j])
01356          pfb_add_to_used_chars (type1_fonts[i].pfb_id, j);
01357       }
01358     }
01359     if (type1_fonts[i].used_chars)
01360       RELEASE (type1_fonts[i].used_chars);
01361     pdf_release_obj (type1_fonts[i].indirect);
01362   }
01363   RELEASE (type1_fonts);
01364   /* Second every distinct pfb name ends up in pfbs.  It is possible
01365      that two distinct tex names map to the same pfb name.  That's why
01366      there is a separate array for pfbs */
01367 
01368   /* Read any necessary font files and flush them */
01369   pfb_flush_all();
01370 
01371 }
01372