Back to index

tetex-bin  3.0
scanfont.c
Go to the documentation of this file.
00001 /* $XConsortium: scanfont.c,v 1.9 92/07/07 17:14:56 gildea Exp $ */
00002 /* Copyright International Business Machines,Corp. 1991
00003  * All Rights Reserved
00004  *
00005  * License to use, copy, modify, and distribute this software
00006  * and its documentation for any purpose and without fee is
00007  * hereby granted, provided that the above copyright notice
00008  * appear in all copies and that both that copyright notice and
00009  * this permission notice appear in supporting documentation,
00010  * and that the name of IBM not be used in advertising or
00011  * publicity pertaining to distribution of the software without
00012  * specific, written prior permission.
00013  *
00014  * IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
00015  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
00016  * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
00018  * THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE QUALITY AND
00019  * PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
00020  * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF
00021  * THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
00022  * THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN
00023  * NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
00024  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
00025  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
00026  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00027  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00028  * SOFTWARE.
00029  */
00030 /* Author: Katherine A. Hitchcock    IBM Almaden Research Laboratory */
00031  
00032 #include <string.h>
00033 #include "t1stdio.h"
00034 #include "util.h"
00035 #include "token.h"
00036 #include "fontfcn.h"
00037 #include "blues.h"
00038 
00039 #include "../t1lib/t1misc.h"
00040 
00041 /* #define DEBUG_SCANFONT */
00042  
00043  
00044 static int rc;
00045 static boolean InPrivateDict;
00046 static boolean WantFontInfo;
00047 static boolean TwoSubrs;
00048 static psobj inputFile;
00049 static psobj filterFile;
00050 static psobj *inputP;
00051 
00052 
00053 extern int T1Getc(F_FILE * );
00054 extern int T1Ungetc( int,F_FILE *);
00055 extern int SearchDictName( psdict *dictP, psobj *keyP);
00056 extern void T1io_setblocklen( long len);
00057 
00058  
00059 /* functions from util.c */
00060 extern void objFormatInteger(psobj *objP, int value);
00061 extern void objFormatReal(psobj *objP, float value); 
00062 extern void objFormatBoolean(psobj *objP, boolean value);
00063 extern void objFormatEncoding( psobj *objP, int length, psobj *valueP);
00064 extern void objFormatArray( psobj *objP, int length, psobj *valueP);
00065 extern void objFormatString( psobj *objP, int length, char *valueP);
00066 extern void objFormatName( psobj *objP, int length, char *valueP);
00067 extern void objFormatFile( psobj *objP, FILE *valueP);
00068 
00069 
00070 /**********************************************************************/
00071 /*   Init_BuiltInEncoding()                                           */
00072 /*                                                                    */
00073 /*     Initializes the StandardEncoding.                              */
00074 /*                                                                    */
00075 /**********************************************************************/
00076 typedef struct                            /* Builtin Standard Encoding */
00077 {
00078    int  index;
00079    char *name;
00080 } EncodingTable;
00081 
00082 
00083 char not_def[]=".notdef";
00084 
00085 
00086 static EncodingTable StdEnc[] = {
00087    {040 , "space"},
00088    {041 , "exclam"},
00089    {042 , "quotedbl"},
00090    {043 , "numbersign"},
00091    {044 , "dollar"},
00092    {045 , "percent"},
00093    {046 , "ampersand"},
00094    {047 , "quoteright"},
00095    {050 , "parenleft"},
00096    {051 , "parenright"},
00097    {052 , "asterisk"},
00098    {053 , "plus"},
00099    {054 , "comma"},
00100    {055 , "hyphen"},
00101    {056 , "period"},
00102    {057 , "slash"},
00103    {060 , "zero"},
00104    {061 , "one"},
00105    {062 , "two"},
00106    {063 , "three"},
00107    {064 , "four"},
00108    {065 , "five"},
00109    {066 , "six"},
00110    {067 , "seven"},
00111    {070 , "eight"},
00112    {071 , "nine"},
00113    {072 , "colon"},
00114    {073 , "semicolon"},
00115    {074 , "less"},
00116    {075 , "equal"},
00117    {076 , "greater"},
00118    {077 , "question"},
00119    {0100 , "at"},
00120    {0101 , "A"},
00121    {0102 , "B"},
00122    {0103 , "C"},
00123    {0104 , "D"},
00124    {0105 , "E"},
00125    {0106 , "F"},
00126    {0107 , "G"},
00127    {0110 , "H"},
00128    {0111 , "I"},
00129    {0112 , "J"},
00130    {0113 , "K"},
00131    {0114 , "L"},
00132    {0115 , "M"},
00133    {0116 , "N"},
00134    {0117 , "O"},
00135    {0120 , "P"},
00136    {0121 , "Q"},
00137    {0122 , "R"},
00138    {0123 , "S"},
00139    {0124 , "T"},
00140    {0125 , "U"},
00141    {0126 , "V"},
00142    {0127 , "W"},
00143    {0130 , "X"},
00144    {0131 , "Y"},
00145    {0132 , "Z"},
00146    {0133 , "bracketleft"},
00147    {0134 , "backslash"},
00148    {0135 , "bracketright"},
00149    {0136 , "asciicircum"},
00150    {0137 , "underscore"},
00151    {0140 , "quoteleft"},
00152    {0141 , "a"},
00153    {0142 , "b"},
00154    {0143 , "c"},
00155    {0144 , "d"},
00156    {0145 , "e"},
00157    {0146 , "f"},
00158    {0147 , "g"},
00159    {0150 , "h"},
00160    {0151 , "i"},
00161    {0152 , "j"},
00162    {0153 , "k"},
00163    {0154 , "l"},
00164    {0155 , "m"},
00165    {0156 , "n"},
00166    {0157 , "o"},
00167    {0160 , "p"},
00168    {0161 , "q"},
00169    {0162 , "r"},
00170    {0163 , "s"},
00171    {0164 , "t"},
00172    {0165 , "u"},
00173    {0166 , "v"},
00174    {0167 , "w"},
00175    {0170 , "x"},
00176    {0171 , "y"},
00177    {0172 , "z"},
00178    {0173 , "braceleft"},
00179    {0174 , "bar"},
00180    {0175 , "braceright"},
00181    {0176 , "asciitilde"},
00182    {0241 , "exclamdown"},
00183    {0242 , "cent"},
00184    {0243 , "sterling"},
00185    {0244 , "fraction"},
00186    {0245 , "yen"},
00187    {0246 , "florin"},
00188    {0247 , "section"},
00189    {0250 , "currency"},
00190    {0251 , "quotesingle"},
00191    {0252 , "quotedblleft"},
00192    {0253 , "guillemotleft"},
00193    {0254 , "guilsinglleft"},
00194    {0255 , "guilsinglright"},
00195    {0256 , "fi"},
00196    {0257 , "fl"},
00197    {0261 , "endash"},
00198    {0262 , "dagger"},
00199    {0263 , "daggerdbl"},
00200    {0264 , "periodcentered"},
00201    {0266 , "paragraph"},
00202    {0267 , "bullet"},
00203    {0270 , "quotesinglbase"},
00204    {0271 , "quotedblbase"},
00205    {0272 , "quotedblright"},
00206    {0273 , "guillemotright"},
00207    {0274 , "ellipsis"},
00208    {0275 , "perthousand"},
00209    {0277 , "questiondown"},
00210    {0301 , "grave"},
00211    {0302 , "acute"},
00212    {0303 , "circumflex"},
00213    {0304 , "tilde"},
00214    {0305 , "macron"},
00215    {0306 , "breve"},
00216    {0307 , "dotaccent"},
00217    {0310 , "dieresis"},
00218    {0312 , "ring"},
00219    {0313 , "cedilla"},
00220    {0315 , "hungarumlaut"},
00221    {0316 , "ogonek"},
00222    {0317 , "caron"},
00223    {0320 , "emdash"},
00224    {0341 , "AE"},
00225    {0343 , "ordfeminine"},
00226    {0350 , "Lslash"},
00227    {0351 , "Oslash"},
00228    {0352 , "OE"},
00229    {0353 , "ordmasculine"},
00230    {0361 , "ae"},
00231    {0365 , "dotlessi"},
00232    {0370 , "lslash"},
00233    {0371 , "oslash"},
00234    {0372 , "oe"},
00235    {0373 , "germandbls"},
00236    { 0,  0 }
00237 };
00238 
00239 
00240 /* Encodings changed from static to global since they must be accessible
00241    by T1_LoadFont() when reallocating memory. */
00242 psobj *StdEncArrayP = NULL;
00243 
00244 
00245 static psobj *MakeEncodingArrayP(encodingTable)
00246     EncodingTable *encodingTable;
00247 {
00248   int i;
00249   psobj *encodingArrayP;
00250  
00251   encodingArrayP = (psobj *)malloc(256*(sizeof(psobj)));
00252   if (!encodingArrayP)
00253       return NULL;
00254 
00255   /* initialize everything to .notdef */
00256   for (i=0; i<256;i++)
00257       objFormatName(&(encodingArrayP[i]),7, not_def);
00258 
00259   for (i=0; encodingTable[i].name; i++)
00260   {
00261     objFormatName(&(encodingArrayP[encodingTable[i].index]),
00262                 strlen(encodingTable[i].name),
00263                 encodingTable[i].name);
00264   }
00265 
00266   return(encodingArrayP);
00267 }
00268  
00269 boolean Init_BuiltInEncoding()
00270 {
00271   StdEncArrayP = MakeEncodingArrayP(StdEnc);
00272   if (StdEncArrayP==NULL)
00273     return( FALSE);
00274   else
00275     return( TRUE);
00276 }
00277  
00278 /********************************************************************/
00279 /***================================================================***/
00280 static int getNextValue(valueType)
00281     int valueType;
00282 {
00283   scan_token(inputP);
00284   if (tokenType != valueType) {
00285     return(SCAN_ERROR);
00286   }
00287   return(SCAN_OK);
00288  
00289 }
00290 /***================================================================***/
00291 /*  This routine will set the global rc if there is an error          */
00292 /***================================================================***/
00293 static int getInt()
00294 {
00295   scan_token(inputP);
00296   if (tokenType != TOKEN_INTEGER) {
00297     rc = SCAN_ERROR;
00298     return(0);
00299   }
00300   else {
00301     return( tokenValue.integer);
00302   }
00303  
00304 }
00305 /***================================================================***/
00306 /*
00307  * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
00308  * for parsing Encoding.
00309  */
00310 static int getEncoding(arrayP)
00311     psobj *arrayP;
00312 {
00313 
00314   scan_token(inputP);
00315   if ((tokenType == TOKEN_NAME) &&
00316       ((tokenLength==16) && (!strncmp(tokenStartP,"StandardEncoding",16))) 
00317       )
00318     {
00319       /* Adobe Standard Encoding */
00320 
00321       if (tokenLength == 16)
00322          arrayP->data.valueP = (char *) StdEncArrayP;
00323       else
00324        return(SCAN_ERROR);
00325       
00326 
00327       arrayP->len = 256;
00328       return(SCAN_OK);
00329   }
00330   else if ( (tokenType == TOKEN_LEFT_BRACE) ||
00331        (tokenType == TOKEN_LEFT_BRACKET) )
00332   {
00333       /* Array of literal names */
00334 
00335       psobj *objP;
00336       int i;
00337 
00338       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
00339       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00340 
00341       arrayP->data.valueP = (char *) objP;
00342       arrayP->len = 256;
00343 
00344       for (i=0; i<256; i++, objP++)
00345       {
00346          scan_token(inputP);
00347          
00348          if (tokenType != TOKEN_LITERAL_NAME)
00349              return(SCAN_ERROR);
00350 
00351          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
00352          objFormatName(objP,tokenLength,tokenStartP);
00353       }
00354 
00355       scan_token(inputP);
00356       if ( (tokenType == TOKEN_RIGHT_BRACE) ||
00357          (tokenType == TOKEN_RIGHT_BRACKET) )
00358          return(SCAN_OK);
00359   }
00360   else
00361   {
00362       /* Must be sequences of ``dup <index> <charactername> put" */
00363 
00364       psobj *objP;
00365       int i;
00366 
00367       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
00368       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00369 
00370       arrayP->data.valueP = (char *) objP;
00371       arrayP->len = 256;
00372 
00373       for (i=0; i<256; i++)
00374          objFormatName(objP + i, 7, not_def);
00375 
00376       while (TRUE)
00377       {
00378          scan_token(inputP);
00379 
00380          switch (tokenType)
00381          {
00382          case TOKEN_NAME:
00383              if (tokenLength == 3)
00384              {
00385                 if (strncmp(tokenStartP,"dup",3) == 0)
00386                 {
00387                     /* get <index> */
00388                     scan_token(inputP);
00389                     if (tokenType != TOKEN_INTEGER ||
00390                        tokenValue.integer < 0 ||
00391                        tokenValue.integer > 255)
00392                        return (SCAN_ERROR);
00393                     i = tokenValue.integer;
00394 
00395                     /* get <characer_name> */
00396                     scan_token(inputP);
00397                     if (tokenType != TOKEN_LITERAL_NAME)
00398                        return(SCAN_ERROR);
00399 
00400                     if (!(vm_alloc(tokenLength)) )
00401                        return(SCAN_OUT_OF_MEMORY);
00402                     objFormatName(objP + i,tokenLength,tokenStartP);
00403 
00404                     /* get "put" */
00405                     scan_token(inputP);
00406                     if (tokenType != TOKEN_NAME)
00407                        return(SCAN_ERROR);
00408                 }
00409                 else if (strncmp(tokenStartP,"def",3) == 0)
00410                     return (SCAN_OK);
00411              }
00412              break;
00413          case TOKEN_EOF:
00414          case TOKEN_NONE:
00415          case TOKEN_INVALID:
00416              return (SCAN_ERROR);
00417          }
00418       }
00419   }
00420 
00421   return (SCAN_ERROR);
00422 }
00423 /***================================================================***/
00424 static int getArray(arrayP)
00425     psobj *arrayP;
00426 {
00427   int N;   /* count the items in the array */
00428   psobj *objP;
00429   
00430  
00431   scan_token(inputP);
00432   if ( (tokenType != TOKEN_LEFT_BRACE) &&
00433        (tokenType != TOKEN_LEFT_BRACKET) ) {
00434     return(SCAN_ERROR);
00435   }
00436   /* format the array in memory, save pointer to the beginning */
00437   arrayP->data.valueP = tokenStartP;
00438   /* loop, picking up next object, until right BRACE or BRACKET */
00439   N = 0;
00440   do {
00441     scan_token(inputP);
00442     if ( (tokenType == TOKEN_RIGHT_BRACE) ||
00443          (tokenType == TOKEN_RIGHT_BRACKET) ) {
00444       /* save then number of items in the array */
00445       arrayP->len = N;
00446       return(SCAN_OK);
00447     }
00448      /* allocate the space for the object */
00449     objP = (psobj *)vm_alloc(sizeof(psobj));
00450     if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00451  
00452     /* array is an array of numbers, (real or integer)  */
00453     if (tokenType == TOKEN_REAL) {
00454       objFormatReal(objP, tokenValue.real);
00455     }
00456     else
00457       if (tokenType == TOKEN_INTEGER) {
00458         objFormatInteger(objP, tokenValue.integer);
00459       }
00460       else return(SCAN_ERROR);
00461     N++;
00462   }  while ( 1>0 );
00463   /* NOTREACHED*/
00464 }
00465 /***================================================================***/
00466 /* is not needed */
00467 /*
00468   static int getName(nameP)
00469   char *nameP;
00470   {
00471   do { 
00472   scan_token(inputP);
00473   if (tokenType <= TOKEN_NONE) {
00474   if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
00475   return(SCAN_ERROR);
00476   }
00477   } while ((tokenType != TOKEN_NAME) ||
00478   (0 != strncmp(tokenStartP,nameP,strlen(nameP))) );
00479   
00480   return(SCAN_OK);
00481   }
00482 */
00483 
00484 /***================================================================***/
00485 static int getNbytes(N)
00486     int N;
00487 {
00488   int I;
00489  
00490   if (N > vm_free_bytes()) {
00491     if (!vm_init()) return(SCAN_OUT_OF_MEMORY);
00492   }
00493   tokenStartP = vm_next_byte();
00494   I = fread(tokenStartP,1,N,inputP->data.fileP);
00495   if ( I != N )     return(SCAN_FILE_EOF);
00496   return(SCAN_OK);
00497 }
00498  
00499 /***================================================================***/
00500 /*  getLiteralName(nameObjP)                                          */
00501 /*     scan for next literal.                                         */
00502 /*  if we encounter the name 'end' then terminate and say ok.         */
00503 /*    It means that the CharStrings does not have as many characters  */
00504 /*    as the dictionary said it would and that is ok.                 */
00505 /***================================================================***/
00506 static int getLiteralName(nameObjP)
00507     psobj *nameObjP;
00508 {
00509   do {
00510     scan_token(inputP);
00511     if (tokenType <= TOKEN_NONE) {
00512       if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
00513       return(SCAN_ERROR);
00514     }
00515     if (tokenType == TOKEN_NAME) {
00516       if (0 == strncmp(tokenStartP,"end",3) ) {
00517         return(SCAN_END);
00518       }
00519     }
00520   } while  (tokenType != TOKEN_LITERAL_NAME) ;
00521   nameObjP->len = tokenLength;
00522   /* allocate all the names in the CharStrings Structure */
00523   if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
00524   nameObjP->data.valueP =  tokenStartP;
00525   /* found */
00526   return(SCAN_OK);
00527 }
00528  
00529 /***================================================================***/
00530 /*
00531  *   BuildSubrs routine 
00532  */
00533 /***================================================================***/
00534  
00535 static int BuildSubrs(FontP)
00536     psfont *FontP;
00537 {
00538    int N;   /* number of values in Subrs */
00539    int I;   /* index into Subrs */
00540    int i;   /* loop thru  Subrs */
00541    int J;   /* length of Subrs entry */
00542    psobj *arrayP;
00543  
00544    /* next token should be a positive int */
00545    /* note: rc is set by getInt. */
00546    N = getInt();
00547    if (rc) return(rc);
00548    if (N < 0 ) return(SCAN_ERROR);
00549    /* if we already have a Subrs, then skip the second one */
00550    /* The second one is for hiresolution devices.          */
00551    if (FontP->Subrs.data.arrayP != NULL) {
00552      TwoSubrs = TRUE;
00553      /* process all the Subrs, but do not update anything */
00554      /* can not just skip them because of the binary data */
00555      for (i=0;i<N;i++) {
00556        /* look for "dup" or "ND" or "|-" or (noaccess) "def". If one of
00557          the latter three token appears, we are done even if still i < N-1.
00558          in this case, there arenīt as much subroutines as fields in the
00559          array which is allowed (Fix thanks to Derek B. Noonburg) */
00560        do {
00561         rc = getNextValue(TOKEN_NAME);
00562         if ( rc != SCAN_OK ) return(rc);
00563         if (!strncmp(tokenStartP, "ND", 2) ||
00564             !strncmp(tokenStartP, "|-", 2) ||
00565             !strncmp(tokenStartP, "def", 3)) {
00566           return SCAN_OK;
00567         }
00568        } while (strncmp(tokenStartP, "dup", 3));
00569        if (rc) return(rc);
00570        /* get 2 integers */
00571        I = getInt();
00572        if (rc) return(rc);
00573        J = getInt();
00574        if (rc) return(rc);
00575        if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
00576        /* get the next token, it should be RD or -|, either is ok */
00577        rc = getNextValue(TOKEN_NAME);
00578        if ( rc != SCAN_OK ) return(rc);
00579        rc = getNbytes(J);
00580        if (rc) return(rc);
00581      }
00582      return(SCAN_OK);
00583    }
00584  
00585    arrayP = (psobj *)vm_alloc(N*sizeof(psobj));
00586    if (!(arrayP) ) return(SCAN_OUT_OF_MEMORY);
00587    /* explicitly resetting the array is not necessary since the pointer
00588       as well as the subroutines both are located in VM and we can
00589       assume that only define subroutines are referenced. */
00590    FontP->Subrs.len = N;
00591    FontP->Subrs.data.arrayP =  arrayP;
00592    /* get N values for Subrs */
00593    for (i=0;i<N;i++) {
00594      /* look for "dup" or "ND" or "|-" or (noaccess) "def". If one of
00595        the latter three token appears, we are done even if still i < N-1.
00596        in this case, there arenīt as much subroutines as fields in the
00597        array which is allowed (Fix thanks to Derek B. Noonburg) */
00598      do {
00599        rc = getNextValue(TOKEN_NAME);
00600        if ( rc != SCAN_OK ) return(rc);
00601        if (!strncmp(tokenStartP, "ND", 2) ||
00602           !strncmp(tokenStartP, "|-", 2) ||
00603           !strncmp(tokenStartP, "def", 3)) {
00604         return SCAN_OK;
00605        }
00606      } while (strncmp(tokenStartP, "dup", 3));
00607      /* get 2 integers */
00608      I = getInt();       /* index into array of Subroutines */
00609      if (rc) return(rc); 
00610      J = getInt();       /* number of binary bytes that follow */
00611      if (rc) return(rc);
00612      if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
00613      arrayP[I].len = J;
00614      /* get the next token, it should be RD or -|, either is ok */
00615      rc = getNextValue(TOKEN_NAME);
00616      if ( rc != SCAN_OK ) return(rc);
00617      rc = getNbytes(J);
00618      if (rc == SCAN_OK) {
00619        arrayP[I].data.valueP = tokenStartP;
00620        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
00621      }
00622      else return(rc);
00623    }
00624    return(SCAN_OK);
00625  
00626 }
00627 
00628 
00629 /***================================================================***/
00630 /***================================================================***/
00631 /*
00632  *   BuildCharStrings routine
00633  */
00634 /***================================================================***/
00635  
00636 static int BuildCharStrings(FontP)
00637     psfont   *FontP;
00638 {
00639    int N;   /* number of values in CharStrings */
00640    int i;   /* loop thru  Subrs */
00641    int J;   /* length of Subrs entry */
00642    psdict  *dictP;
00643  
00644    /* next token should be a positive int */
00645    N = getInt();
00646    if (rc) {
00647      /* check if file had TwoSubrs, hi resolution stuff is in file*/
00648      if (TwoSubrs) {
00649        do {
00650          scan_token(inputP);
00651          if (tokenType <= TOKEN_NONE) {
00652            if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
00653            return(SCAN_ERROR);
00654          }
00655        } while (tokenType != TOKEN_INTEGER);
00656        N = tokenValue.integer;
00657      }
00658      else return(rc);  /* if next token was not an Int */
00659    }
00660    if (N<=0) return(SCAN_ERROR);
00661    /* save number of entries in the dictionary */
00662  
00663    dictP = (psdict *)vm_alloc((N+1)*sizeof(psdict));
00664    if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
00665    FontP->CharStringsP = dictP;
00666    dictP[0].key.len = N;
00667    /* get N values for CharStrings */
00668    for (i=1;i<=N;i++) {
00669      /* look for next literal name  */
00670      rc = getLiteralName(&(dictP[i].key));
00671      /* If rc=SCAN_END, the end of file has been reached. This means
00672        there were less than N charstrings. This is perfectly valid. */
00673      if (rc) return(rc);
00674      /* get 1 integer */
00675      J = getInt();
00676      if (rc) return(rc);  /* if next token was not an Int */
00677      if (J<0) return (SCAN_ERROR);
00678      dictP[i].value.len = J;
00679      /* get the next token, it should be RD or -|, either is ok */
00680      rc = getNextValue(TOKEN_NAME);
00681      if ( rc != SCAN_OK ) return(rc);
00682      rc = getNbytes(J);
00683      if (rc == SCAN_OK) {
00684        dictP[i].value.data.valueP = tokenStartP;
00685        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
00686      }
00687      else {
00688        return(rc);
00689      }
00690      
00691    }
00692    return(SCAN_OK);
00693  
00694 }
00695 /***================================================================***/
00696 /***================================================================***/
00697 /*
00698  *   BuildFontInfo Dictionary
00699  */
00700 /***================================================================***/
00701 static int BuildFontInfo(fontP)
00702     psfont *fontP;
00703 {
00704   psdict *dictP;
00705   
00706   /* allocate the private dictionary */
00707   dictP = (psdict *)vm_alloc(20*sizeof(psdict));
00708   if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
00709  
00710   fontP->fontInfoP = dictP;
00711   fontP->fontInfoP[0].key.len = 17;  /* number of actual entries */
00712   objFormatName(&(dictP[FONTNAME].key),8,"FontName");
00713   objFormatName(&(dictP[FONTNAME].value),0,NULL);
00714   objFormatName(&(dictP[PAINTTYPE].key),9,"PaintType");
00715   objFormatInteger(&(dictP[PAINTTYPE].value),0);
00716   objFormatName(&(dictP[FONTTYPENUM].key),8,"FontType");
00717   objFormatInteger(&(dictP[FONTTYPENUM].value),0);
00718   objFormatName(&(dictP[FONTMATRIX].key),10,"FontMatrix");
00719   objFormatArray(&(dictP[FONTMATRIX].value),0,NULL);
00720   objFormatName(&(dictP[FONTBBOX].key),8,"FontBBox");
00721   objFormatArray(&(dictP[FONTBBOX].value),0,NULL);
00722   objFormatName(&(dictP[ENCODING].key),8,"Encoding");
00723   objFormatEncoding(&(dictP[ENCODING].value),0,NULL);
00724   objFormatName(&(dictP[UNIQUEID].key),8,"UniqueID");
00725   objFormatInteger(&(dictP[UNIQUEID].value),0);
00726   objFormatName(&(dictP[STROKEWIDTH].key),11,"StrokeWidth");
00727   objFormatReal(&(dictP[STROKEWIDTH].value),0.0);
00728   objFormatName(&(dictP[VERSION].key),7,"version");
00729   objFormatString(&(dictP[VERSION].value),0,NULL);
00730   objFormatName(&(dictP[NOTICE].key),6,"Notice");
00731   objFormatString(&(dictP[NOTICE].value),0,NULL);
00732   objFormatName(&(dictP[FULLNAME].key),8,"FullName");
00733   objFormatString(&(dictP[FULLNAME].value),0,NULL);
00734   objFormatName(&(dictP[FAMILYNAME].key),10,"FamilyName");
00735   objFormatString(&(dictP[FAMILYNAME].value),0,NULL);
00736   objFormatName(&(dictP[WEIGHT].key),6,"Weight");
00737   objFormatString(&(dictP[WEIGHT].value),0,NULL);
00738   objFormatName(&(dictP[ITALICANGLE].key),11,"ItalicAngle");
00739   objFormatReal(&(dictP[ITALICANGLE].value),0.0);
00740   objFormatName(&(dictP[ISFIXEDPITCH].key),12,"isFixedPitch");
00741   objFormatBoolean(&(dictP[ISFIXEDPITCH].value),FALSE);
00742   objFormatName(&(dictP[UNDERLINEPOSITION].key),17,"UnderlinePosition");
00743   objFormatReal(&(dictP[UNDERLINEPOSITION].value),0.0);
00744   objFormatName(&(dictP[UNDERLINETHICKNESS].key),18,"UnderlineThickness");
00745   objFormatReal(&(dictP[UNDERLINETHICKNESS].value),0.0);
00746   return(SCAN_OK);
00747 }
00748 /***================================================================***/
00749 /*
00750  *   BuildPrivate Dictionary
00751  */
00752 /* "LenIV" corrected to be "lenIV", otherwise fonts with some specific
00753    lenIV value could not be decrypted. (RMz, Author of t1lib, 06/03/1998)*/
00754 /***================================================================***/
00755 static int BuildPrivate(fontP)
00756     psfont *fontP;
00757 {
00758   psdict *Private;
00759  
00760   /* allocate the private dictionary */
00761   Private = (psdict *)vm_alloc(20*sizeof(psdict));
00762  
00763   if (!(Private)) return(SCAN_OUT_OF_MEMORY);
00764  
00765   fontP->Private = Private;
00766   fontP->Private[0].key.len = 16;  /* number of actual entries */
00767  
00768   objFormatName(&(Private[BLUEVALUES].key),10,"BlueValues");
00769   objFormatArray(&(Private[BLUEVALUES].value),0,NULL);
00770   objFormatName(&(Private[OTHERBLUES].key),10,"OtherBlues");
00771   objFormatArray(&(Private[OTHERBLUES].value),0,NULL);
00772   objFormatName(&(Private[FAMILYBLUES].key),11,"FamilyBlues");
00773   objFormatArray(&(Private[FAMILYBLUES].value),0,NULL);
00774   objFormatName(&(Private[FAMILYOTHERBLUES].key),16,"FamilyOtherBlues");
00775   objFormatArray(&(Private[FAMILYOTHERBLUES].value),0,NULL);
00776   objFormatName(&(Private[BLUESCALE].key),9,"BlueScale");
00777   objFormatReal(&(Private[BLUESCALE].value),DEFAULTBLUESCALE);
00778   objFormatName(&(Private[BLUESHIFT].key),9,"BlueShift");
00779   objFormatInteger(&(Private[BLUESHIFT].value),DEFAULTBLUESHIFT);
00780   objFormatName(&(Private[BLUEFUZZ].key),8,"BlueFuzz");
00781   objFormatInteger(&(Private[BLUEFUZZ].value),DEFAULTBLUEFUZZ);
00782   objFormatName(&(Private[STDHW].key),5,"StdHW");
00783   objFormatArray(&(Private[STDHW].value),0,NULL);
00784   objFormatName(&(Private[STDVW].key),5,"StdVW");
00785   objFormatArray(&(Private[STDVW].value),0,NULL);
00786   objFormatName(&(Private[STEMSNAPH].key),9,"StemSnapH");
00787   objFormatArray(&(Private[STEMSNAPH].value),0,NULL);
00788   objFormatName(&(Private[STEMSNAPV].key),9,"StemSnapV");
00789   objFormatArray(&(Private[STEMSNAPV].value),0,NULL);
00790   objFormatName(&(Private[FORCEBOLD].key),9,"ForceBold");
00791   objFormatBoolean(&(Private[FORCEBOLD].value),DEFAULTFORCEBOLD);
00792   objFormatName(&(Private[LANGUAGEGROUP].key),13,"LanguageGroup");
00793   objFormatInteger(&(Private[LANGUAGEGROUP].value),DEFAULTLANGUAGEGROUP);
00794   objFormatName(&(Private[LENIV].key),5,"lenIV"); 
00795   objFormatInteger(&(Private[LENIV].value),DEFAULTLENIV);
00796   objFormatName(&(Private[RNDSTEMUP].key),9,"RndStemUp");
00797   objFormatBoolean(&(Private[RNDSTEMUP].value),DEFAULTRNDSTEMUP);
00798   objFormatName(&(Private[EXPANSIONFACTOR].key),9,"ExpansionFactor");
00799   objFormatReal(&(Private[EXPANSIONFACTOR].value),
00800                           DEFAULTEXPANSIONFACTOR);
00801   return(SCAN_OK);
00802 }
00803 /***================================================================***/
00804 /**********************************************************************/
00805 /*     GetType1Blues(fontP)                                           */
00806 /*                                                                    */
00807 /*   Routine to support font-level hints.                             */
00808 /*                                                                    */
00809 /*         Gets all the Blues information from the Private dictionary */
00810 /*         for the font.                                              */
00811 /*                                                                    */
00812 /*                                                                    */
00813 /**********************************************************************/
00814 static int GetType1Blues(fontP)
00815     psfont *fontP;
00816 {
00817   psdict *PrivateDictP;   /* the Private dict relating to hints */
00818   struct blues_struct *blues;  /* ptr for the blues struct we will allocate */
00819   int i;
00820   psobj *HintEntryP;
00821  
00822  
00823  
00824   /* get the Private dictionary pointer */
00825   PrivateDictP = fontP->Private;
00826  
00827   /* allocate the memory for the blues structure */
00828   blues = (struct blues_struct *) vm_alloc(sizeof(struct blues_struct));
00829  
00830   if (!blues)  return(SCAN_OUT_OF_MEMORY);
00831  
00832   /* Make fontP's blues ptr point to this newly allocated structure. */
00833   fontP->BluesP = blues;
00834  
00835   /* fill in the BlueValues array */
00836   HintEntryP = &(PrivateDictP[BLUEVALUES].value);
00837   /* check to see if the entry exists and if it's an array */
00838   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00839       blues->numBlueValues = 0;
00840   else {
00841       /* get the number of values in the array */
00842       if (HintEntryP->len > NUMBLUEVALUES) {
00843           blues->numBlueValues = NUMBLUEVALUES;
00844       } else
00845           blues->numBlueValues = HintEntryP->len;
00846       for (i = 0; i<= blues->numBlueValues-1; ++i) {
00847           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00848               blues->BlueValues[i] =
00849                   HintEntryP->data.arrayP[i].data.integer;
00850           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00851               blues->BlueValues[i] =
00852                   HintEntryP->data.arrayP[i].data.real;
00853           else
00854               blues->BlueValues[i] = 0;
00855       }
00856   }
00857  
00858   /* fill in the OtherBlues array */
00859   HintEntryP =  &(PrivateDictP[OTHERBLUES].value);
00860   /* check to see if the entry exists and if it's an array */
00861   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00862       blues->numOtherBlues = 0;
00863   else {
00864       /* get the number of values in the array */
00865       if (HintEntryP->len > NUMOTHERBLUES) {
00866           blues->numOtherBlues = NUMOTHERBLUES;
00867       } else
00868           blues->numOtherBlues = HintEntryP->len;
00869       for (i = 0; i<= blues->numOtherBlues-1; ++i) {
00870           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00871               blues->OtherBlues[i] =
00872                   HintEntryP->data.arrayP[i].data.integer;
00873           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00874               blues->OtherBlues[i] =
00875                   HintEntryP->data.arrayP[i].data.real;
00876           else
00877               blues->OtherBlues[i] = 0;
00878       }
00879   }
00880  
00881   /* fill in the FamilyBlues array */
00882   HintEntryP =  &(PrivateDictP[FAMILYBLUES].value);
00883   /* check to see if the entry exists and if it's an array */
00884   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00885       blues->numFamilyBlues = 0;
00886   else {
00887       /* get the number of values in the array */
00888       if (HintEntryP->len > NUMFAMILYBLUES) {
00889           blues->numFamilyBlues = NUMFAMILYBLUES;
00890       } else
00891           blues->numFamilyBlues = HintEntryP->len;
00892       for (i = 0; i<= blues->numFamilyBlues-1; ++i) {
00893           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00894               blues->FamilyBlues[i] =
00895                   HintEntryP->data.arrayP[i].data.integer;
00896           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00897               blues->FamilyBlues[i] =
00898                   HintEntryP->data.arrayP[i].data.real;
00899           else
00900               blues->FamilyBlues[i] = 0;
00901       }
00902   }
00903  
00904   /* fill in the FamilyOtherBlues array */
00905   HintEntryP =  &(PrivateDictP[FAMILYOTHERBLUES].value);
00906   /* check to see if the entry exists and if it's an array */
00907   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00908       blues->numFamilyOtherBlues = 0;
00909   else {
00910       /* get the number of values in the array */
00911       if (HintEntryP->len > NUMFAMILYOTHERBLUES) {
00912           blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
00913       } else
00914           blues->numFamilyOtherBlues = HintEntryP->len;
00915       for (i = 0; i<= blues->numFamilyOtherBlues-1; ++i) {
00916           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00917               blues->FamilyOtherBlues[i] =
00918                   HintEntryP->data.arrayP[i].data.integer;
00919           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00920               blues->FamilyOtherBlues[i] =
00921                   HintEntryP->data.arrayP[i].data.real;
00922           else
00923               blues->FamilyOtherBlues[i] = 0;
00924       }
00925   }
00926  
00927   /* fill in the StemSnapH array */
00928   HintEntryP =  &(PrivateDictP[STEMSNAPH].value);
00929   /* check to see if the entry exists and if it's an array */
00930   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00931       blues->numStemSnapH = 0;
00932   else {
00933       /* get the number of values in the array */
00934       if (HintEntryP->len > NUMSTEMSNAPH) {
00935           blues->numStemSnapH = NUMSTEMSNAPH;
00936       } else
00937           blues->numStemSnapH = HintEntryP->len;
00938       for (i = 0; i<= blues->numStemSnapH-1; ++i) {
00939           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00940               blues->StemSnapH[i] =
00941                   HintEntryP->data.arrayP[i].data.integer;
00942           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00943               blues->StemSnapH[i] =
00944                   HintEntryP->data.arrayP[i].data.real;
00945           else
00946               blues->StemSnapH[i] = 0;
00947       }
00948   }
00949  
00950   /* fill in the StemSnapV array */
00951   HintEntryP =  &(PrivateDictP[STEMSNAPV].value);
00952   /* check to see if the entry exists and if it's an array */
00953   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00954       blues->numStemSnapV = 0;
00955   else {
00956       /* get the number of values in the array */
00957       if (HintEntryP->len > NUMSTEMSNAPV) {
00958           blues->numStemSnapV = NUMSTEMSNAPV;
00959       } else
00960           blues->numStemSnapV = HintEntryP->len;
00961       for (i = 0; i<= blues->numStemSnapV-1; ++i) {
00962           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00963               blues->StemSnapV[i] =
00964                   HintEntryP->data.arrayP[i].data.integer;
00965           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00966               blues->StemSnapV[i] =
00967                   HintEntryP->data.arrayP[i].data.real;
00968           else
00969               blues->StemSnapV[i] = 0;
00970       }
00971   }
00972  
00973   /* fill in the StdVW array */
00974   HintEntryP =  &(PrivateDictP[STDVW].value);
00975   /* check to see if the entry exists and if it's an array */
00976   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00977       /* a value of zero signifies no entry */
00978       blues->StdVW = 0.0;
00979   else {
00980       if (HintEntryP->len > NUMSTDVW) {
00981       }
00982       if (objPIsInteger(&HintEntryP->data.arrayP[0]))
00983           blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
00984       else if (objPIsReal(&HintEntryP->data.arrayP[0]))
00985           blues->StdVW = HintEntryP->data.arrayP[0].data.real;
00986       else
00987           blues->StdVW = 0.0;
00988   }
00989  
00990   /* fill in the StdHW array */
00991   HintEntryP =  &(PrivateDictP[STDHW].value);
00992   /* check to see if the entry exists and if it's an array */
00993   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00994       /* a value of zero signifies no entry */
00995       blues->StdHW = 0;
00996   else {
00997       if (HintEntryP->len > NUMSTDHW) {
00998       }
00999           if (objPIsInteger(&HintEntryP->data.arrayP[0]))
01000              blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
01001           else if (objPIsReal(&HintEntryP->data.arrayP[0]))
01002              blues->StdHW = HintEntryP->data.arrayP[0].data.real;
01003           else
01004              blues->StdHW = 0;
01005   }
01006  
01007  
01008   /* get the ptr to the BlueScale entry */
01009   HintEntryP =  &(PrivateDictP[BLUESCALE].value);
01010   /* put the BlueScale in the blues structure */
01011   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01012       blues->BlueScale = HintEntryP->data.integer;
01013   else if (objPIsReal(HintEntryP)) /* Error? */
01014       blues->BlueScale = HintEntryP->data.real;
01015   else
01016       blues->BlueScale = DEFAULTBLUESCALE;
01017  
01018   /* get the ptr to the BlueShift entry */
01019   HintEntryP =  &(PrivateDictP[BLUESHIFT].value);
01020   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01021       blues->BlueShift = HintEntryP->data.integer;
01022   else if (objPIsReal(HintEntryP)) /* Error? */
01023       blues->BlueShift = HintEntryP->data.real;
01024   else
01025       blues->BlueShift = DEFAULTBLUESHIFT;
01026  
01027   /* get the ptr to the BlueFuzz entry */
01028   HintEntryP =  &(PrivateDictP[BLUEFUZZ].value);
01029   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01030       blues->BlueFuzz = HintEntryP->data.integer;
01031   else if (objPIsReal(HintEntryP)) /* Error? */
01032       blues->BlueFuzz = HintEntryP->data.real;
01033   else
01034       blues->BlueFuzz = DEFAULTBLUEFUZZ;
01035  
01036   /* get the ptr to the ForceBold entry */
01037   HintEntryP =  &(PrivateDictP[FORCEBOLD].value);
01038   if (objPIsBoolean(HintEntryP))  /* Must be integer! */
01039       blues->ForceBold = HintEntryP->data.boolean;
01040   else
01041       blues->ForceBold = DEFAULTFORCEBOLD;
01042  
01043   /* get the ptr to the LanguageGroup entry */
01044   HintEntryP =  &(PrivateDictP[LANGUAGEGROUP].value);
01045   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01046       blues->LanguageGroup = HintEntryP->data.integer;
01047   else
01048       blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
01049  
01050   /* get the ptr to the RndStemUp entry */
01051   HintEntryP =  &(PrivateDictP[RNDSTEMUP].value);
01052   if (objPIsBoolean(HintEntryP)) /* Must be integer! */
01053       blues->RndStemUp = HintEntryP->data.boolean;
01054   else
01055       blues->RndStemUp = DEFAULTRNDSTEMUP;
01056  
01057   /* get the ptr to the lenIV entry */
01058   HintEntryP =  &(PrivateDictP[LENIV].value);
01059   if (objPIsInteger(HintEntryP)) {/* Must be integer! */
01060     blues->lenIV = HintEntryP->data.integer;
01061   }
01062   else{
01063     blues->lenIV = DEFAULTLENIV;
01064   }
01065   
01066  
01067   /* get the ptr to the ExpansionFactor entry */
01068   HintEntryP =  &(PrivateDictP[EXPANSIONFACTOR].value);
01069   if (objPIsInteger(HintEntryP))
01070       blues->ExpansionFactor = HintEntryP->data.integer;
01071   else if (objPIsReal(HintEntryP))
01072       blues->ExpansionFactor = HintEntryP->data.real;
01073   else
01074       blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
01075   return(SCAN_OK);
01076 }
01077 /**********************************************************************/
01078 /*   GetType1CharString(fontP,code)                                   */
01079 /*                                                                    */
01080 /*          Look up code in the standard encoding vector and return   */
01081 /*          the charstring associated with the character name.        */
01082 /*                                                                    */
01083 /*   fontP  is the psfont structure.                                  */
01084 /*                                                                    */
01085 /*   Returns a psobj (string)                                         */
01086 /**********************************************************************/
01087 psobj *GetType1CharString(fontP, code)
01088 psfont *fontP;
01089 unsigned char code;
01090 {
01091   int  N;           /* the 'Nth' entry in the CharStrings       */
01092   psobj *charnameP; /* points to psobj that is name of character*/
01093  
01094   psdict *CharStringsDictP; /* dictionary with char strings     */
01095   psobj  *theStringP;  /* the definition for the code */
01096   
01097   
01098   if (StdEncArrayP == NULL) {
01099     return(NULL);
01100   }
01101   /* use the code to index into the standard encoding vector  */
01102   charnameP = &(StdEncArrayP[code]);
01103   
01104   /* test if the encoding array points to a name */
01105   if (!(objPIsName(charnameP)) ) {
01106     return(NULL);
01107   }
01108 
01109   /* Now that we have the character name out of the standardencoding */
01110   /* get the character definition out of the current font */
01111   CharStringsDictP =  fontP->CharStringsP;
01112  
01113   /* search the chars string for this charname as key */
01114   N = SearchDictName(CharStringsDictP,charnameP);
01115   if (N<=0) {
01116     return(NULL);
01117   }
01118 
01119   /* OK, the nth item is the psobj that is the string for this char */
01120   theStringP = &(CharStringsDictP[N].value);
01121  
01122   return(theStringP);
01123 }
01124  
01125 /***================================================================***/
01126 /*
01127  *   FindDictValue
01128  */
01129 /***================================================================***/
01130  
01131 static int FindDictValue(dictP)
01132     psdict    *dictP;
01133 {
01134    psobj LitName;
01135    int   N;
01136    int   V;
01137  
01138    /* we have just scanned a token and it is a literal name */
01139    /* need to check if that name is in Private dictionary */
01140    objFormatName(&LitName,tokenLength,tokenStartP);
01141    /* is it in the dictP */
01142    N = SearchDictName(dictP,&LitName);
01143    /* if found */
01144    if ( N > 0 ) {
01145      /* what type */
01146      switch (dictP[N].value.type) {
01147        case OBJ_ENCODING:
01148          V = getEncoding(&(dictP[N].value));
01149          if ( V != SCAN_OK ) return(V);
01150          break;
01151        case OBJ_ARRAY:
01152          V = getArray(&(dictP[N].value));
01153          if ( V != SCAN_OK ) return(V);
01154          break;
01155        case OBJ_INTEGER:
01156          /* next value in integer */
01157          dictP[N].value.data.integer = getInt();
01158          if (rc) return(rc);  /* if next token was not an Int */
01159          break;
01160        case OBJ_REAL:
01161          /* next value must be real or int, store as a real */
01162          scan_token(inputP);
01163          if (tokenType == TOKEN_REAL) {
01164            dictP[N].value.data.real = tokenValue.real;
01165          }
01166          else
01167            if (tokenType == TOKEN_INTEGER) {
01168              dictP[N].value.data.real = tokenValue.integer;
01169            }
01170          else return(SCAN_ERROR);
01171          break;
01172        case OBJ_NAME:
01173          V = getNextValue(TOKEN_LITERAL_NAME);
01174          if ( V != SCAN_OK ) return(V);
01175          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
01176          objFormatName(&(dictP[N].value),tokenLength,tokenStartP);
01177          break;
01178        case OBJ_STRING:
01179          V = getNextValue(TOKEN_STRING);
01180          if ( V != SCAN_OK ) return(V);
01181          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
01182          objFormatString(&(dictP[N].value),tokenLength,tokenStartP);
01183          break;
01184        case OBJ_BOOLEAN:
01185          scan_token(inputP);
01186          if (tokenType != TOKEN_NAME) {
01187            return(SCAN_ERROR);
01188          }
01189          if (0 == strncmp(tokenStartP,"true",4) ) {
01190            dictP[N].value.data.boolean =TRUE;
01191          }
01192          else
01193            if (0 == strncmp(tokenStartP,"false",5) ) {
01194              dictP[N].value.data.boolean =FALSE;
01195            }
01196            else return(SCAN_ERROR);
01197          break;
01198  
01199        default:
01200          return(SCAN_ERROR);
01201          break;
01202      }
01203    }
01204    /* Name is not in dictionary.  That is ok. */
01205    return(SCAN_OK);
01206  
01207 }
01208 /***================================================================***/
01209  
01210 /*
01211  * -------------------------------------------------------------------
01212  *  Scan the next token and convert it into an object
01213  *  Result is placed on the Operand Stack as next object
01214  * -------------------------------------------------------------------
01215  */
01216 int scan_font(FontP)
01217   psfont *FontP;
01218 {
01219  
01220  
01221   char   filename[MAXPATHLEN];
01222   FILE   *fileP;
01223   char   *nameP;
01224   int    namelen;
01225  
01226     /* copy the filename and remove leading or trailing blanks */
01227     /* point to name and search for leading blanks */
01228     nameP= FontP->FontFileName.data.nameP;
01229     namelen  = FontP->FontFileName.len;
01230     while (nameP[0] == ' ') {
01231         nameP++;
01232         namelen--;
01233     }
01234     /* now remove any trailing blanks */
01235     while ((namelen>0) && ( nameP[namelen-1] == ' ')) {
01236       namelen--;
01237     }
01238     if ( namelen >= MAXPATHLEN ) {
01239       /* Hopefully, this will lead to a file open error */
01240       namelen = MAXPATHLEN - 1; /* - 1 added by SU */
01241     }
01242     strncpy(filename,nameP,namelen);
01243     filename[namelen] = '\0';
01244     /* file name is now constructed */
01245     inputFile.data.fileP = NULL;
01246     filterFile.data.fileP = NULL;
01247  
01248     inputP = &inputFile;
01249     if ((fileP = fopen(filename,"rb"))!=NULL) {
01250       objFormatFile(inputP,fileP);
01251     }
01252     else {
01253       return(SCAN_FILE_OPEN_ERROR);
01254     };
01255  
01256   WantFontInfo  = TRUE;
01257   InPrivateDict = FALSE;
01258   TwoSubrs      = FALSE;
01259   rc = BuildFontInfo(FontP);
01260 #ifdef DEBUG_SCANFONT
01261   printf("BuildFontInfo(): retval=%d\n", rc);
01262 #endif
01263   if (rc != 0) return(rc);
01264  
01265   /* Assume everything will be OK */
01266   rc       = 0;
01267  
01268   /* Loop until complete font is read  */
01269   do {
01270     /* Scan the next token */
01271     scan_token(inputP);
01272 
01273     /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
01274     /* now set */
01275  
01276     switch (tokenType) {
01277       case TOKEN_EOF:
01278       case TOKEN_NONE:
01279       case TOKEN_INVALID:
01280         /* in this case we are done */
01281         if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
01282         rc = SCAN_ERROR;
01283         break;
01284       case TOKEN_LITERAL_NAME:
01285             /* Look up the name */
01286             tokenStartP[tokenLength] = '\0';
01287            /* At this point we check for the font not being a
01288               Multiple Master Font. If it is, we return an error.
01289               (RMz, 01/29/1999) */
01290            if (strncmp(tokenStartP, "BlendAxisTypes", 14)==0){
01291              rc=SCAN_MMFONT;
01292              break;
01293            }
01294             if (InPrivateDict ) {
01295               if (0== strncmp(tokenStartP,"Subrs",5) ) {
01296                 rc = BuildSubrs(FontP);
01297 #ifdef DEBUG_SCANFONT
01298               printf("BuildSubrs(): retval=%d\n", rc);
01299 #endif
01300                 break;
01301               }
01302               if (0== strncmp(tokenStartP,"CharStrings",11) ) {
01303                 rc = BuildCharStrings(FontP);
01304 #ifdef DEBUG_SCANFONT
01305               printf("BuildCharstrings(): retval=%d\n", rc);
01306 #endif
01307                 if ( (rc == SCAN_OK) ||(rc == SCAN_END) ) {
01308                   fclose(inputP->data.fileP);
01309                   /* Build the Blues Structure */
01310                 rc = GetType1Blues(FontP);
01311 #ifdef DEBUG_SCANFONT
01312                 printf("GetType1Blues(): retval=%d\n", rc);
01313 #endif
01314                   /* whatever the return code, return it */
01315                   /* all the work is done. This is the normal exit.*/
01316                   return(rc);
01317                 }
01318                 break;
01319               }
01320               rc = FindDictValue(FontP->Private);
01321               /* we are not going to report errors */
01322               /* Sometimes the font file may test a value such as */
01323               /* testing to see if the font is alreadly loaded with */
01324               /* same UniqueID.  We would faile on /UniqueID get  */
01325               /* because we are expecting a int to follow UniqueID*/
01326               /* If the correct object type does not follow a Name*/
01327               /* then we will skip over it without reporting error*/
01328               rc = SCAN_OK;
01329               break;
01330             }   /* end of reading Private dictionary */
01331             else
01332               if (0== strncmp(tokenStartP,"Private",7) ) {
01333                 InPrivateDict = TRUE;
01334                 rc = BuildPrivate(FontP);
01335                 break;
01336               }
01337               else
01338                 if (WantFontInfo) {
01339                   rc = FindDictValue(FontP->fontInfoP);
01340                   /* we are not going to report errors */
01341                   rc = SCAN_OK;
01342                   break;
01343                 }
01344         break;
01345       case TOKEN_NAME:
01346             if (0 == strncmp(tokenStartP,"eexec",5) ) {
01347              /* We check for the pfb-headers in I/O-module */ 
01348              filterFile.data.fileP = T1eexec(inputP->data.fileP);
01349              if (filterFile.data.fileP == NULL) {
01350               fclose(inputFile.data.fileP);
01351               /* SCAN_FILE_OPEN_ERROR replaced because at this point
01352                  a portion of the file has already been read successfully.
01353                  We hence have encountered a premature end of file
01354                  (2002-08-17, RMz). */
01355               return SCAN_FILE_EOF;
01356              }
01357              inputP = &filterFile;
01358              
01359              WantFontInfo = FALSE;
01360             }
01361         break;
01362     }
01363  
01364   }
01365   while (rc ==0);
01366   fclose(inputP->data.fileP);
01367   if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
01368   return(rc);
01369 }
01370