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 "types.h"
00034 
00035 #include "t1stdio.h"
00036 #include "util.h"
00037 #include "token.h"
00038 #include "fontfcn.h"
00039 #include "blues.h"
00040  
00041  
00042 #ifdef HAVE_PROTOTYPES
00043 extern void objFormatInteger(psobj *,int);
00044 extern void objFormatReal(psobj *, float);
00045 extern void objFormatBoolean(psobj *, boolean);
00046 extern void objFormatEncoding(psobj *, int, psobj *);
00047 extern void objFormatArray(psobj *, int, psobj *);
00048 extern void objFormatString(psobj *, int, char *);
00049 extern void objFormatName(psobj *, int, char *);
00050 extern void objFormatFile(psobj *, FILE *);
00051 extern int SearchDictName(psdict *, psobj *);
00052 extern int T1Getc(struct F_FILE *f);
00053 extern int T1Ungetc(int c,struct F_FILE *f);
00054 #endif
00055  
00056 static int rc;
00057 static boolean InPrivateDict;
00058 static boolean WantFontInfo;
00059 static boolean TwoSubrs;
00060 static psobj inputFile;
00061 static psobj filterFile;
00062 static psobj *inputP;
00063  
00064  
00065 /**********************************************************************/
00066 /*   Init_BuiltInEncoding()                                           */
00067 /*                                                                    */
00068 /*     Initializes the StandardEncoding and ISOLatin1Encoding vector. */
00069 /*                                                                    */
00070 /**********************************************************************/
00071 typedef struct                            /* Builtin Standard Encoding */
00072 {
00073    int  index;
00074    char *name;
00075 } EncodingTable;
00076 
00077 static EncodingTable StdEnc[] = {
00078    040 , "space",
00079    041 , "exclam",
00080    042 , "quotedbl",
00081    043 , "numbersign",
00082    044 , "dollar",
00083    045 , "percent",
00084    046 , "ampersand",
00085    047 , "quoteright",
00086    050 , "parenleft",
00087    051 , "parenright",
00088    052 , "asterisk",
00089    053 , "plus",
00090    054 , "comma",
00091    055 , "hyphen",
00092    056 , "period",
00093    057 , "slash",
00094    060 , "zero",
00095    061 , "one",
00096    062 , "two",
00097    063 , "three",
00098    064 , "four",
00099    065 , "five",
00100    066 , "six",
00101    067 , "seven",
00102    070 , "eight",
00103    071 , "nine",
00104    072 , "colon",
00105    073 , "semicolon",
00106    074 , "less",
00107    075 , "equal",
00108    076 , "greater",
00109    077 , "question",
00110   0100 , "at",
00111   0101 , "A",
00112   0102 , "B",
00113   0103 , "C",
00114   0104 , "D",
00115   0105 , "E",
00116   0106 , "F",
00117   0107 , "G",
00118   0110 , "H",
00119   0111 , "I",
00120   0112 , "J",
00121   0113 , "K",
00122   0114 , "L",
00123   0115 , "M",
00124   0116 , "N",
00125   0117 , "O",
00126   0120 , "P",
00127   0121 , "Q",
00128   0122 , "R",
00129   0123 , "S",
00130   0124 , "T",
00131   0125 , "U",
00132   0126 , "V",
00133   0127 , "W",
00134   0130 , "X",
00135   0131 , "Y",
00136   0132 , "Z",
00137   0133 , "bracketleft",
00138   0134 , "backslash",
00139   0135 , "bracketright",
00140   0136 , "asciicircum",
00141   0137 , "underscore",
00142   0140 , "quoteleft",
00143   0141 , "a",
00144   0142 , "b",
00145   0143 , "c",
00146   0144 , "d",
00147   0145 , "e",
00148   0146 , "f",
00149   0147 , "g",
00150   0150 , "h",
00151   0151 , "i",
00152   0152 , "j",
00153   0153 , "k",
00154   0154 , "l",
00155   0155 , "m",
00156   0156 , "n",
00157   0157 , "o",
00158   0160 , "p",
00159   0161 , "q",
00160   0162 , "r",
00161   0163 , "s",
00162   0164 , "t",
00163   0165 , "u",
00164   0166 , "v",
00165   0167 , "w",
00166   0170 , "x",
00167   0171 , "y",
00168   0172 , "z",
00169   0173 , "braceleft",
00170   0174 , "bar",
00171   0175 , "braceright",
00172   0176 , "asciitilde",
00173   0241 , "exclamdown",
00174   0242 , "cent",
00175   0243 , "sterling",
00176   0244 , "fraction",
00177   0245 , "yen",
00178   0246 , "florin",
00179   0247 , "section",
00180   0250 , "currency",
00181   0251 , "quotesingle",
00182   0252 , "quotedblleft",
00183   0253 , "guillemotleft",
00184   0254 , "guilsinglleft",
00185   0255 , "guilsinglright",
00186   0256 , "fi",
00187   0257 , "fl",
00188   0261 , "endash",
00189   0262 , "dagger",
00190   0263 , "daggerdbl",
00191   0264 , "periodcentered",
00192   0266 , "paragraph",
00193   0267 , "bullet",
00194   0270 , "quotesinglbase",
00195   0271 , "quotedblbase",
00196   0272 , "quotedblright",
00197   0273 , "guillemotright",
00198   0274 , "ellipsis",
00199   0275 , "perthousand",
00200   0277 , "questiondown",
00201   0301 , "grave",
00202   0302 , "acute",
00203   0303 , "circumflex",
00204   0304 , "tilde",
00205   0305 , "macron",
00206   0306 , "breve",
00207   0307 , "dotaccent",
00208   0310 , "dieresis",
00209   0312 , "ring",
00210   0313 , "cedilla",
00211   0315 , "hungarumlaut",
00212   0316 , "ogonek",
00213   0317 , "caron",
00214   0320 , "emdash",
00215   0341 , "AE",
00216   0343 , "ordfeminine",
00217   0350 , "Lslash",
00218   0351 , "Oslash",
00219   0352 , "OE",
00220   0353 , "ordmasculine",
00221   0361 , "ae",
00222   0365 , "dotlessi",
00223   0370 , "lslash",
00224   0371 , "oslash",
00225   0372 , "oe",
00226   0373 , "germandbls",
00227     0,      0
00228 };
00229 
00230 static EncodingTable ISO8859Enc[] = {
00231   32, "space",
00232   33, "exclam",
00233   34, "quotedbl",
00234   35, "numbersign",
00235   36, "dollar",
00236   37, "percent",
00237   38, "ampersand",
00238   39, "quoteright",
00239   40, "parenleft",
00240   41, "parenright",
00241   42, "asterisk",
00242   43, "plus",
00243   44, "comma",
00244   45, "minus",
00245   46, "period",
00246   47, "slash",
00247   48, "zero",
00248   49, "one",
00249   50, "two",
00250   51, "three",
00251   52, "four",
00252   53, "five",
00253   54, "six",
00254   55, "seven",
00255   56, "eight",
00256   57, "nine",
00257   58, "colon",
00258   59, "semicolon",
00259   60, "less",
00260   61, "equal",
00261   62, "greater",
00262   63, "question",
00263   64, "at",
00264   65, "A",
00265   66, "B",
00266   67, "C",
00267   68, "D",
00268   69, "E",
00269   70, "F",
00270   71, "G",
00271   72, "H",
00272   73, "I",
00273   74, "J",
00274   75, "K",
00275   76, "L",
00276   77, "M",
00277   78, "N",
00278   79, "O",
00279   80, "P",
00280   81, "Q",
00281   82, "R",
00282   83, "S",
00283   84, "T",
00284   85, "U",
00285   86, "V",
00286   87, "W",
00287   88, "X",
00288   89, "Y",
00289   90, "Z",
00290   91, "bracketleft",
00291   92, "backslash",
00292   93, "bracketright",
00293   94, "asciicircum",
00294   95, "underscore",
00295   96, "quoteleft",
00296   97, "a",
00297   98, "b",
00298   99, "c",
00299  100, "d",
00300  101, "e",
00301  102, "f",
00302  103, "g",
00303  104, "h",
00304  105, "i",
00305  106, "j",
00306  107, "k",
00307  108, "l",
00308  109, "m",
00309  110, "n",
00310  111, "o",
00311  112, "p",
00312  113, "q",
00313  114, "r",
00314  115, "s",
00315  116, "t",
00316  117, "u",
00317  118, "v",
00318  119, "w",
00319  120, "x",
00320  121, "y",
00321  122, "z",
00322  123, "braceleft",
00323  124, "bar",
00324  125, "braceright",
00325  126, "asciitilde",
00326  161, "exclamdown",
00327  162, "cent",
00328  163, "sterling",
00329  164, "currency",
00330  165, "yen",
00331  166, "brokenbar",
00332  167, "section",
00333  168, "dieresis",
00334  169, "copyright",
00335  170, "ordfeminine",
00336  171, "guillemotleft",
00337  172, "logicalnot",
00338  173, "hyphen",
00339  174, "registered",
00340  175, "macron",
00341  176, "degree",
00342  177, "plusminus",
00343  178, "twosuperior",
00344  179, "threesuperior",
00345  180, "acute",
00346  181, "mu",
00347  182, "paragraph",
00348  183, "periodcentered",
00349  184, "cedilla",
00350  185, "onesuperior",
00351  186, "ordmasculine",
00352  187, "guillemotright",
00353  188, "onequarter",
00354  189, "onehalf",
00355  190, "threequarters",
00356  191, "questiondown",
00357  192, "Agrave",
00358  193, "Aacute",
00359  194, "Acircumflex",
00360  195, "Atilde",
00361  196, "Adieresis",
00362  197, "Aring",
00363  198, "AE",
00364  199, "Ccedilla",
00365  200, "Egrave",
00366  201, "Eacute",
00367  202, "Ecircumflex",
00368  203, "Edieresis",
00369  204, "Igrave",
00370  205, "Iacute",
00371  206, "Icircumflex",
00372  207, "Idieresis",
00373  208, "Eth",
00374  209, "Ntilde",
00375  210, "Ograve",
00376  211, "Oacute",
00377  212, "Ocircumflex",
00378  213, "Otilde",
00379  214, "Odieresis",
00380  215, "multiply",
00381  216, "Oslash",
00382  217, "Ugrave",
00383  218, "Uacute",
00384  219, "Ucircumflex",
00385  220, "Udieresis",
00386  221, "Yacute",
00387  222, "Thorn",
00388  223, "germandbls",
00389  224, "agrave",
00390  225, "aacute",
00391  226, "acircumflex",
00392  227, "atilde",
00393  228, "adieresis",
00394  229, "aring",
00395  230, "ae",
00396  231, "ccedilla",
00397  232, "egrave",
00398  233, "eacute",
00399  234, "ecircumflex",
00400  235, "edieresis",
00401  236, "igrave",
00402  237, "iacute",
00403  238, "icircumflex",
00404  239, "idieresis",
00405  240, "eth",
00406  241, "ntilde",
00407  242, "ograve",
00408  243, "oacute",
00409  244, "ocircumflex",
00410  245, "otilde",
00411  246, "odieresis",
00412  247, "divide",
00413  248, "oslash",
00414  249, "ugrave",
00415  250, "uacute",
00416  251, "ucircumflex",
00417  252, "udieresis",
00418  253, "yacute",
00419  254, "thorn",
00420  255, "ydieresis",
00421     0,      0
00422 };
00423 
00424 static psobj *StdEncArrayP = NULL;
00425 psobj *ISOLatin1EncArrayP = NULL; 
00426  
00427 static psobj *MakeEncodingArrayP(encodingTable)
00428     EncodingTable *encodingTable;
00429 {
00430   int i;
00431   psobj *encodingArrayP;
00432  
00433   encodingArrayP = (psobj *)vm_alloc(256*(sizeof(psobj)));
00434   if (!encodingArrayP)
00435       return NULL;
00436 
00437   /* initialize everything to .notdef */
00438   for (i=0; i<256;i++)
00439       objFormatName(&(encodingArrayP[i]),7, ".notdef");
00440 
00441   for (i=0; encodingTable[i].name; i++)
00442   {
00443       objFormatName(&(encodingArrayP[encodingTable[i].index]),
00444                   strlen(encodingTable[i].name),
00445                   encodingTable[i].name);
00446   }
00447 
00448   return(encodingArrayP);
00449 }
00450  
00451 boolean Init_BuiltInEncoding()
00452 {
00453     StdEncArrayP = MakeEncodingArrayP(StdEnc);
00454     ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
00455     return (StdEncArrayP && ISOLatin1EncArrayP);
00456 }
00457  
00458 /********************************************************************/
00459 /***================================================================***/
00460 static int getNextValue(valueType)
00461     int valueType;
00462 {
00463   scan_token(inputP);
00464   if (tokenType != valueType) {
00465     return(SCAN_ERROR);
00466   }
00467   return(SCAN_OK);
00468  
00469 }
00470 /***================================================================***/
00471 /*  This routine will set the global rc if there is an error          */
00472 /***================================================================***/
00473 static int getInt()
00474 {
00475   scan_token(inputP);
00476   if (tokenType != TOKEN_INTEGER) {
00477     rc = SCAN_ERROR;
00478     return(0);
00479   }
00480   else {
00481     return( tokenValue.integer);
00482   }
00483  
00484 }
00485 /***================================================================***/
00486 /*
00487  * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
00488  * for parsing Encoding.
00489  */
00490 static int getEncoding(arrayP)
00491     psobj *arrayP;
00492 {
00493 
00494   scan_token(inputP);
00495   if ((tokenType == TOKEN_NAME)
00496                 &&
00497      (((tokenLength==16) && (!strncmp(tokenStartP,"StandardEncoding",16))) ||
00498       (((tokenLength==17) && (!strncmp(tokenStartP,"ISOLatin1Encoding",17))))))
00499   {
00500       /* Adobe Standard Encoding */
00501 
00502       if (tokenLength == 16)
00503          arrayP->data.valueP = (char *) StdEncArrayP;
00504       else
00505          arrayP->data.valueP = (char *) ISOLatin1EncArrayP;
00506 
00507       arrayP->len = 256;
00508       return(SCAN_OK);
00509   }
00510   else if ( (tokenType == TOKEN_LEFT_BRACE) ||
00511        (tokenType == TOKEN_LEFT_BRACKET) )
00512   {
00513       /* Array of literal names */
00514 
00515       psobj *objP;
00516       int i;
00517 
00518       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
00519       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00520 
00521       arrayP->data.valueP = (char *) objP;
00522       arrayP->len = 256;
00523 
00524       for (i=0; i<256; i++, objP++)
00525       {
00526          scan_token(inputP);
00527          
00528          if (tokenType != TOKEN_LITERAL_NAME)
00529              return(SCAN_ERROR);
00530 
00531          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
00532          objFormatName(objP,tokenLength,tokenStartP);
00533       }
00534 
00535       scan_token(inputP);
00536       if ( (tokenType == TOKEN_RIGHT_BRACE) ||
00537          (tokenType == TOKEN_RIGHT_BRACKET) )
00538          return(SCAN_OK);
00539   }
00540   else
00541   {
00542       /* Must be sequences of ``dup <index> <charactername> put" */
00543 
00544       psobj *objP;
00545       int i;
00546 
00547       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
00548       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00549 
00550       arrayP->data.valueP = (char *) objP;
00551       arrayP->len = 256;
00552 
00553       for (i=0; i<256; i++)
00554          objFormatName(objP + i, 7, ".notdef");
00555 
00556       while (TRUE)
00557       {
00558          scan_token(inputP);
00559 
00560          switch (tokenType)
00561          {
00562          case TOKEN_NAME:
00563              if (tokenLength == 3)
00564              {
00565                 if (strncmp(tokenStartP,"dup",3) == 0)
00566                 {
00567                     /* get <index> */
00568                     scan_token(inputP);
00569                     if (tokenType != TOKEN_INTEGER ||
00570                        tokenValue.integer < 0 ||
00571                        tokenValue.integer > 255)
00572                        return (SCAN_ERROR);
00573                     i = tokenValue.integer;
00574 
00575                     /* get <characer_name> */
00576                     scan_token(inputP);
00577                     if (tokenType != TOKEN_LITERAL_NAME)
00578                        return(SCAN_ERROR);
00579 
00580                     if (!(vm_alloc(tokenLength)) )
00581                        return(SCAN_OUT_OF_MEMORY);
00582                     objFormatName(objP + i,tokenLength,tokenStartP);
00583 
00584                     /* get "put" */
00585                     scan_token(inputP);
00586                     if (tokenType != TOKEN_NAME)
00587                        return(SCAN_ERROR);
00588                 }
00589                 else if (strncmp(tokenStartP,"def",3) == 0)
00590                     return (SCAN_OK);
00591              }
00592              break;
00593          case TOKEN_EOF:
00594          case TOKEN_NONE:
00595          case TOKEN_INVALID:
00596              return (SCAN_ERROR);
00597          }
00598       }
00599   }
00600 
00601   return (SCAN_ERROR);
00602 }
00603 /***================================================================***/
00604 static int getArray(arrayP)
00605     psobj *arrayP;
00606 {
00607   int N;   /* count the items in the array */
00608   psobj *objP;
00609  
00610  
00611   scan_token(inputP);
00612   if ( (tokenType != TOKEN_LEFT_BRACE) &&
00613        (tokenType != TOKEN_LEFT_BRACKET) ) {
00614     return(SCAN_ERROR);
00615   }
00616   /* format the array in memory, save pointer to the beginning */
00617   arrayP->data.valueP = tokenStartP;
00618   /* loop, picking up next object, until right BRACE or BRACKET */
00619   N = 0;
00620   do {
00621     scan_token(inputP);
00622     if ( (tokenType == TOKEN_RIGHT_BRACE) ||
00623          (tokenType == TOKEN_RIGHT_BRACKET) ) {
00624       /* save then number of items in the array */
00625       arrayP->len = N;
00626       return(SCAN_OK);
00627     }
00628      /* allocate the space for the object */
00629     objP = (psobj *)vm_alloc(sizeof(psobj));
00630     if (!(objP)) return(SCAN_OUT_OF_MEMORY);
00631  
00632     /* array is an array of numbers, (real or integer)  */
00633     if (tokenType == TOKEN_REAL) {
00634       objFormatReal(objP, tokenValue.real);
00635     }
00636     else
00637       if (tokenType == TOKEN_INTEGER) {
00638         objFormatInteger(objP, tokenValue.integer);
00639       }
00640       else return(SCAN_ERROR);
00641     N++;
00642   }  while ( 1>0 );
00643   /* NOTREACHED*/
00644 }
00645 /***================================================================***/
00646 static int getName(nameP)
00647     char *nameP;
00648 {
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_NAME) ||
00656     (0 != strncmp(tokenStartP,nameP,strlen(nameP))) );
00657   /* found */
00658   return(SCAN_OK);
00659 }
00660 /***================================================================***/
00661 static int getNbytes(N)
00662     int N;
00663 {
00664   int I;
00665  
00666   if (N > vm_free_bytes()) {
00667     if (!vm_init()) return(SCAN_OUT_OF_MEMORY);
00668   }
00669   tokenStartP = vm_next_byte();
00670   I = fread(tokenStartP,1,N,inputP->data.fileP);
00671   if ( I != N )     return(SCAN_FILE_EOF);
00672   return(SCAN_OK);
00673 }
00674  
00675 /***================================================================***/
00676 /*  getLiteralName(nameObjP)                                          */
00677 /*     scan for next literal.                                         */
00678 /*  if we encounter the name 'end' then terminate and say ok.         */
00679 /*    It means that the CharStrings does not have as many characters  */
00680 /*    as the dictionary said it would and that is ok.                 */
00681 /***================================================================***/
00682 static int getLiteralName(nameObjP)
00683     psobj *nameObjP;
00684 {
00685   do {
00686     scan_token(inputP);
00687     if (tokenType <= TOKEN_NONE) {
00688       if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
00689       return(SCAN_ERROR);
00690     }
00691     if (tokenType == TOKEN_NAME) {
00692       if (0 == strncmp(tokenStartP,"end",3) ) {
00693         return(SCAN_END);
00694       }
00695     }
00696   } while  (tokenType != TOKEN_LITERAL_NAME) ;
00697   nameObjP->len = tokenLength;
00698   /* allocate all the names in the CharStrings Structure */
00699   if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
00700   nameObjP->data.valueP =  tokenStartP;
00701   /* found */
00702   return(SCAN_OK);
00703 }
00704  
00705 /***================================================================***/
00706 /*
00707  *   BuildSubrs routine
00708  */
00709 /***================================================================***/
00710  
00711 static int BuildSubrs(FontP)
00712     psfont *FontP;
00713 {
00714    int N;   /* number of values in Subrs */
00715    int I;   /* index into Subrs */
00716    int i;   /* loop thru  Subrs */
00717    int J;   /* length of Subrs entry */
00718    psobj *arrayP;
00719  
00720    /* next token should be a positive int */
00721    /* note: rc is set by getInt. */
00722    N = getInt();
00723    if (rc) return(rc);
00724    if (N < 0 ) return(SCAN_ERROR);
00725    /* if we already have a Subrs, then skip the second one */
00726    /* The second one is for hiresolution devices.          */
00727    if (FontP->Subrs.data.arrayP != NULL) {
00728      TwoSubrs = TRUE;
00729      /* process all the Subrs, but do not update anything */
00730      /* can not just skip them because of the binary data */
00731      for (i=0;i<N;i++) {
00732        /* look for dup */
00733        rc = getName("dup");
00734        if (rc) return(rc);
00735        /* get 2 integers */
00736        I = getInt();
00737        if (rc) return(rc);
00738        J = getInt();
00739        if (rc) return(rc);
00740        if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
00741        /* get the next token, it should be RD or -|, either is ok */
00742        rc = getNextValue(TOKEN_NAME);
00743        if ( rc != SCAN_OK ) return(rc);
00744        rc = getNbytes(J);
00745        if (rc) return(rc);
00746      }
00747      return(SCAN_OK);
00748    }
00749  
00750    arrayP = (psobj *)vm_alloc(N*sizeof(psobj));
00751    if (!(arrayP) ) return(SCAN_OUT_OF_MEMORY);
00752    FontP->Subrs.len = N;
00753    FontP->Subrs.data.arrayP =  arrayP;
00754    /* get N values for Subrs */
00755    for (i=0;i<N;i++) {
00756      /* look for dup */
00757      rc = getName("dup");
00758      if (rc) return(rc);
00759      /* get 2 integers */
00760      I = getInt();
00761      if (rc) return(rc);
00762      J = getInt();
00763      if (rc) return(rc);
00764      if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
00765      arrayP[I].len = J;
00766      /* get the next token, it should be RD or -|, either is ok */
00767      rc = getNextValue(TOKEN_NAME);
00768      if ( rc != SCAN_OK ) return(rc);
00769      rc = getNbytes(J);
00770      if (rc == SCAN_OK) {
00771        arrayP[I].data.valueP = tokenStartP;
00772        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
00773      }
00774      else return(rc);
00775    }
00776    return(SCAN_OK);
00777  
00778 }
00779 /***================================================================***/
00780 /***================================================================***/
00781 /*
00782  *   BuildCharStrings routine
00783  */
00784 /***================================================================***/
00785  
00786 static int BuildCharStrings(FontP)
00787     psfont   *FontP;
00788 {
00789    int N;   /* number of values in CharStrings */
00790    int i;   /* loop thru  Subrs */
00791    int J;   /* length of Subrs entry */
00792    psdict  *dictP;
00793  
00794    /* next token should be a positive int */
00795    N = getInt();
00796    if (rc) {
00797      /* check if file had TwoSubrs, hi resolution stuff is in file*/
00798      if (TwoSubrs) {
00799        do {
00800          scan_token(inputP);
00801          if (tokenType <= TOKEN_NONE) {
00802            if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
00803            return(SCAN_ERROR);
00804          }
00805        } while (tokenType != TOKEN_INTEGER);
00806        N = tokenValue.integer;
00807      }
00808      else return(rc);  /* if next token was not an Int */
00809    }
00810    if (N<=0) return(SCAN_ERROR);
00811    /* save number of entries in the dictionary */
00812  
00813    dictP = (psdict *)vm_alloc((N+1)*sizeof(psdict));
00814    if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
00815    FontP->CharStringsP = dictP;
00816    dictP[0].key.len = N;
00817    /* get N values for CharStrings */
00818    for (i=1;i<=N;i++) {
00819      /* look for next literal name  */
00820      rc = getLiteralName(&(dictP[i].key));
00821      if (rc) return(rc);
00822      /* get 1 integer */
00823      J = getInt();
00824      if (rc) return(rc);  /* if next token was not an Int */
00825      if (J<0) return (SCAN_ERROR);
00826      dictP[i].value.len = J;
00827      /* get the next token, it should be RD or -|, either is ok */
00828      rc = getNextValue(TOKEN_NAME);
00829      if ( rc != SCAN_OK ) return(rc);
00830      rc = getNbytes(J);
00831      if (rc == SCAN_OK) {
00832        dictP[i].value.data.valueP = tokenStartP;
00833        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
00834      }
00835      else return(rc);
00836    }
00837    return(SCAN_OK);
00838  
00839 }
00840 /***================================================================***/
00841 /***================================================================***/
00842 /*
00843  *   BuildFontInfo Dictionary
00844  */
00845 /***================================================================***/
00846 static int BuildFontInfo(fontP)
00847     psfont *fontP;
00848 {
00849   psdict *dictP;
00850  
00851   /* allocate the private dictionary */
00852   dictP = (psdict *)vm_alloc(20*sizeof(psdict));
00853   if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
00854  
00855   fontP->fontInfoP = dictP;
00856   fontP->fontInfoP[0].key.len = 17;  /* number of actual entries */
00857   objFormatName(&(dictP[FONTNAME].key),8,"FontName");
00858   objFormatName(&(dictP[FONTNAME].value),0,NULL);
00859   objFormatName(&(dictP[PAINTTYPE].key),9,"PaintType");
00860   objFormatInteger(&(dictP[PAINTTYPE].value),0);
00861   objFormatName(&(dictP[FONTTYPENUM].key),8,"FontType");
00862   objFormatInteger(&(dictP[FONTTYPENUM].value),0);
00863   objFormatName(&(dictP[FONTMATRIX].key),10,"FontMatrix");
00864   objFormatArray(&(dictP[FONTMATRIX].value),0,NULL);
00865   objFormatName(&(dictP[FONTBBOX].key),8,"FontBBox");
00866   objFormatArray(&(dictP[FONTBBOX].value),0,NULL);
00867   objFormatName(&(dictP[ENCODING].key),8,"Encoding");
00868   objFormatEncoding(&(dictP[ENCODING].value),0,NULL);
00869   objFormatName(&(dictP[UNIQUEID].key),8,"UniqueID");
00870   objFormatInteger(&(dictP[UNIQUEID].value),0);
00871   objFormatName(&(dictP[STROKEWIDTH].key),11,"StrokeWidth");
00872   objFormatReal(&(dictP[STROKEWIDTH].value),0.0);
00873   objFormatName(&(dictP[VERSION].key),7,"version");
00874   objFormatString(&(dictP[VERSION].value),0,NULL);
00875   objFormatName(&(dictP[NOTICE].key),6,"Notice");
00876   objFormatString(&(dictP[NOTICE].value),0,NULL);
00877   objFormatName(&(dictP[FULLNAME].key),8,"FullName");
00878   objFormatString(&(dictP[FULLNAME].value),0,NULL);
00879   objFormatName(&(dictP[FAMILYNAME].key),10,"FamilyName");
00880   objFormatString(&(dictP[FAMILYNAME].value),0,NULL);
00881   objFormatName(&(dictP[WEIGHT].key),6,"Weight");
00882   objFormatString(&(dictP[WEIGHT].value),0,NULL);
00883   objFormatName(&(dictP[ITALICANGLE].key),11,"ItalicAngle");
00884   objFormatReal(&(dictP[ITALICANGLE].value),0.0);
00885   objFormatName(&(dictP[ISFIXEDPITCH].key),12,"isFixedPitch");
00886   objFormatBoolean(&(dictP[ISFIXEDPITCH].value),FALSE);
00887   objFormatName(&(dictP[UNDERLINEPOSITION].key),17,"UnderlinePosition");
00888   objFormatReal(&(dictP[UNDERLINEPOSITION].value),0.0);
00889   objFormatName(&(dictP[UNDERLINETHICKNESS].key),18,"UnderlineThickness");
00890   objFormatReal(&(dictP[UNDERLINETHICKNESS].value),0.0);
00891   return(SCAN_OK);
00892 }
00893 /***================================================================***/
00894 /*
00895  *   BuildPrivate Dictionary
00896  */
00897 /***================================================================***/
00898 static int BuildPrivate(fontP)
00899     psfont *fontP;
00900 {
00901   psdict *Private;
00902  
00903   /* allocate the private dictionary */
00904   Private = (psdict *)vm_alloc(20*sizeof(psdict));
00905  
00906   if (!(Private)) return(SCAN_OUT_OF_MEMORY);
00907  
00908   fontP->Private = Private;
00909   fontP->Private[0].key.len = 16;  /* number of actual entries */
00910  
00911   objFormatName(&(Private[BLUEVALUES].key),10,"BlueValues");
00912   objFormatArray(&(Private[BLUEVALUES].value),0,NULL);
00913   objFormatName(&(Private[OTHERBLUES].key),10,"OtherBlues");
00914   objFormatArray(&(Private[OTHERBLUES].value),0,NULL);
00915   objFormatName(&(Private[FAMILYBLUES].key),11,"FamilyBlues");
00916   objFormatArray(&(Private[FAMILYBLUES].value),0,NULL);
00917   objFormatName(&(Private[FAMILYOTHERBLUES].key),16,"FamilyOtherBlues");
00918   objFormatArray(&(Private[FAMILYOTHERBLUES].value),0,NULL);
00919   objFormatName(&(Private[BLUESCALE].key),9,"BlueScale");
00920   objFormatReal(&(Private[BLUESCALE].value),DEFAULTBLUESCALE);
00921   objFormatName(&(Private[BLUESHIFT].key),9,"BlueShift");
00922   objFormatInteger(&(Private[BLUESHIFT].value),DEFAULTBLUESHIFT);
00923   objFormatName(&(Private[BLUEFUZZ].key),8,"BlueFuzz");
00924   objFormatInteger(&(Private[BLUEFUZZ].value),DEFAULTBLUEFUZZ);
00925   objFormatName(&(Private[STDHW].key),5,"StdHW");
00926   objFormatArray(&(Private[STDHW].value),0,NULL);
00927   objFormatName(&(Private[STDVW].key),5,"StdVW");
00928   objFormatArray(&(Private[STDVW].value),0,NULL);
00929   objFormatName(&(Private[STEMSNAPH].key),9,"StemSnapH");
00930   objFormatArray(&(Private[STEMSNAPH].value),0,NULL);
00931   objFormatName(&(Private[STEMSNAPV].key),9,"StemSnapV");
00932   objFormatArray(&(Private[STEMSNAPV].value),0,NULL);
00933   objFormatName(&(Private[FORCEBOLD].key),9,"ForceBold");
00934   objFormatBoolean(&(Private[FORCEBOLD].value),DEFAULTFORCEBOLD);
00935   objFormatName(&(Private[LANGUAGEGROUP].key),13,"LanguageGroup");
00936   objFormatInteger(&(Private[LANGUAGEGROUP].value),DEFAULTLANGUAGEGROUP);
00937   objFormatName(&(Private[LENIV].key),5,"LenIV");
00938   objFormatInteger(&(Private[LENIV].value),DEFAULTLENIV);
00939   objFormatName(&(Private[RNDSTEMUP].key),9,"RndStemUp");
00940   objFormatBoolean(&(Private[RNDSTEMUP].value),DEFAULTRNDSTEMUP);
00941   objFormatName(&(Private[EXPANSIONFACTOR].key),9,"ExpansionFactor");
00942   objFormatReal(&(Private[EXPANSIONFACTOR].value),
00943                           DEFAULTEXPANSIONFACTOR);
00944   return(SCAN_OK);
00945 }
00946 /***================================================================***/
00947 /**********************************************************************/
00948 /*     GetType1Blues(fontP)                                           */
00949 /*                                                                    */
00950 /*   Routine to support font-level hints.                             */
00951 /*                                                                    */
00952 /*         Gets all the Blues information from the Private dictionary */
00953 /*         for the font.                                              */
00954 /*                                                                    */
00955 /*                                                                    */
00956 /**********************************************************************/
00957 static int GetType1Blues(fontP)
00958     psfont *fontP;
00959 {
00960   psdict *PrivateDictP;   /* the Private dict relating to hints */
00961   struct blues_struct *blues;  /* ptr for the blues struct we will allocate */
00962   int i;
00963   psobj *HintEntryP;
00964  
00965  
00966  
00967   /* get the Private dictionary pointer */
00968   PrivateDictP = fontP->Private;
00969  
00970   /* allocate the memory for the blues structure */
00971   blues = (struct blues_struct *) vm_alloc(sizeof(struct blues_struct));
00972  
00973   if (!blues)  return(SCAN_OUT_OF_MEMORY);
00974  
00975   /* Make fontP's blues ptr point to this newly allocated structure. */
00976   fontP->BluesP = blues;
00977  
00978   /* fill in the BlueValues array */
00979   HintEntryP = &(PrivateDictP[BLUEVALUES].value);
00980   /* check to see if the entry exists and if it's an array */
00981   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
00982       blues->numBlueValues = 0;
00983   else {
00984       /* get the number of values in the array */
00985       if (HintEntryP->len > NUMBLUEVALUES) {
00986           blues->numBlueValues = NUMBLUEVALUES;
00987       } else
00988           blues->numBlueValues = HintEntryP->len;
00989       for (i = 0; i<= blues->numBlueValues-1; ++i) {
00990           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
00991               blues->BlueValues[i] =
00992                   HintEntryP->data.arrayP[i].data.integer;
00993           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
00994               blues->BlueValues[i] =
00995                   HintEntryP->data.arrayP[i].data.real;
00996           else
00997               blues->BlueValues[i] = 0;
00998       }
00999   }
01000  
01001   /* fill in the OtherBlues array */
01002   HintEntryP =  &(PrivateDictP[OTHERBLUES].value);
01003   /* check to see if the entry exists and if it's an array */
01004   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01005       blues->numOtherBlues = 0;
01006   else {
01007       /* get the number of values in the array */
01008       if (HintEntryP->len > NUMOTHERBLUES) {
01009           blues->numOtherBlues = NUMOTHERBLUES;
01010       } else
01011           blues->numOtherBlues = HintEntryP->len;
01012       for (i = 0; i<= blues->numOtherBlues-1; ++i) {
01013           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
01014               blues->OtherBlues[i] =
01015                   HintEntryP->data.arrayP[i].data.integer;
01016           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
01017               blues->OtherBlues[i] =
01018                   HintEntryP->data.arrayP[i].data.real;
01019           else
01020               blues->OtherBlues[i] = 0;
01021       }
01022   }
01023  
01024   /* fill in the FamilyBlues array */
01025   HintEntryP =  &(PrivateDictP[FAMILYBLUES].value);
01026   /* check to see if the entry exists and if it's an array */
01027   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01028       blues->numFamilyBlues = 0;
01029   else {
01030       /* get the number of values in the array */
01031       if (HintEntryP->len > NUMFAMILYBLUES) {
01032           blues->numFamilyBlues = NUMFAMILYBLUES;
01033       } else
01034           blues->numFamilyBlues = HintEntryP->len;
01035       for (i = 0; i<= blues->numFamilyBlues-1; ++i) {
01036           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
01037               blues->FamilyBlues[i] =
01038                   HintEntryP->data.arrayP[i].data.integer;
01039           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
01040               blues->FamilyBlues[i] =
01041                   HintEntryP->data.arrayP[i].data.real;
01042           else
01043               blues->FamilyBlues[i] = 0;
01044       }
01045   }
01046  
01047   /* fill in the FamilyOtherBlues array */
01048   HintEntryP =  &(PrivateDictP[FAMILYOTHERBLUES].value);
01049   /* check to see if the entry exists and if it's an array */
01050   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01051       blues->numFamilyOtherBlues = 0;
01052   else {
01053       /* get the number of values in the array */
01054       if (HintEntryP->len > NUMFAMILYOTHERBLUES) {
01055           blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
01056       } else
01057           blues->numFamilyOtherBlues = HintEntryP->len;
01058       for (i = 0; i<= blues->numFamilyOtherBlues-1; ++i) {
01059           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
01060               blues->FamilyOtherBlues[i] =
01061                   HintEntryP->data.arrayP[i].data.integer;
01062           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
01063               blues->FamilyOtherBlues[i] =
01064                   HintEntryP->data.arrayP[i].data.real;
01065           else
01066               blues->FamilyOtherBlues[i] = 0;
01067       }
01068   }
01069  
01070   /* fill in the StemSnapH array */
01071   HintEntryP =  &(PrivateDictP[STEMSNAPH].value);
01072   /* check to see if the entry exists and if it's an array */
01073   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01074       blues->numStemSnapH = 0;
01075   else {
01076       /* get the number of values in the array */
01077       if (HintEntryP->len > NUMSTEMSNAPH) {
01078           blues->numStemSnapH = NUMSTEMSNAPH;
01079       } else
01080           blues->numStemSnapH = HintEntryP->len;
01081       for (i = 0; i<= blues->numStemSnapH-1; ++i) {
01082           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
01083               blues->StemSnapH[i] =
01084                   HintEntryP->data.arrayP[i].data.integer;
01085           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
01086               blues->StemSnapH[i] =
01087                   HintEntryP->data.arrayP[i].data.real;
01088           else
01089               blues->StemSnapH[i] = 0;
01090       }
01091   }
01092  
01093   /* fill in the StemSnapV array */
01094   HintEntryP =  &(PrivateDictP[STEMSNAPV].value);
01095   /* check to see if the entry exists and if it's an array */
01096   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01097       blues->numStemSnapV = 0;
01098   else {
01099       /* get the number of values in the array */
01100       if (HintEntryP->len > NUMSTEMSNAPV) {
01101           blues->numStemSnapV = NUMSTEMSNAPV;
01102       } else
01103           blues->numStemSnapV = HintEntryP->len;
01104       for (i = 0; i<= blues->numStemSnapV-1; ++i) {
01105           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
01106               blues->StemSnapV[i] =
01107                   HintEntryP->data.arrayP[i].data.integer;
01108           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
01109               blues->StemSnapV[i] =
01110                   HintEntryP->data.arrayP[i].data.real;
01111           else
01112               blues->StemSnapV[i] = 0;
01113       }
01114   }
01115  
01116   /* fill in the StdVW array */
01117   HintEntryP =  &(PrivateDictP[STDVW].value);
01118   /* check to see if the entry exists and if it's an array */
01119   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01120       /* a value of zero signifies no entry */
01121       blues->StdVW = 0;
01122   else {
01123       if (HintEntryP->len > NUMSTDVW) {
01124       }
01125       if (objPIsInteger(&HintEntryP->data.arrayP[0]))
01126           blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
01127       else if (objPIsReal(&HintEntryP->data.arrayP[0]))
01128           blues->StdVW = HintEntryP->data.arrayP[0].data.real;
01129       else
01130           blues->StdVW = 0;
01131   }
01132  
01133   /* fill in the StdHW array */
01134   HintEntryP =  &(PrivateDictP[STDHW].value);
01135   /* check to see if the entry exists and if it's an array */
01136   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
01137       /* a value of zero signifies no entry */
01138       blues->StdHW = 0;
01139   else {
01140       if (HintEntryP->len > NUMSTDHW) {
01141       }
01142           if (objPIsInteger(&HintEntryP->data.arrayP[0]))
01143              blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
01144           else if (objPIsReal(&HintEntryP->data.arrayP[0]))
01145              blues->StdHW = HintEntryP->data.arrayP[0].data.real;
01146           else
01147              blues->StdHW = 0;
01148   }
01149  
01150  
01151   /* get the ptr to the BlueScale entry */
01152   HintEntryP =  &(PrivateDictP[BLUESCALE].value);
01153   /* put the BlueScale in the blues structure */
01154   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01155       blues->BlueScale = HintEntryP->data.integer;
01156   else if (objPIsReal(HintEntryP)) /* Error? */
01157       blues->BlueScale = HintEntryP->data.real;
01158   else
01159       blues->BlueScale = DEFAULTBLUESCALE;
01160  
01161   /* get the ptr to the BlueShift entry */
01162   HintEntryP =  &(PrivateDictP[BLUESHIFT].value);
01163   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01164       blues->BlueShift = HintEntryP->data.integer;
01165   else if (objPIsReal(HintEntryP)) /* Error? */
01166       blues->BlueShift = HintEntryP->data.real;
01167   else
01168       blues->BlueShift = DEFAULTBLUESHIFT;
01169  
01170   /* get the ptr to the BlueFuzz entry */
01171   HintEntryP =  &(PrivateDictP[BLUEFUZZ].value);
01172   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01173       blues->BlueFuzz = HintEntryP->data.integer;
01174   else if (objPIsReal(HintEntryP)) /* Error? */
01175       blues->BlueFuzz = HintEntryP->data.real;
01176   else
01177       blues->BlueFuzz = DEFAULTBLUEFUZZ;
01178  
01179   /* get the ptr to the ForceBold entry */
01180   HintEntryP =  &(PrivateDictP[FORCEBOLD].value);
01181   if (objPIsBoolean(HintEntryP))  /* Must be integer! */
01182       blues->ForceBold = HintEntryP->data.boolean;
01183   else
01184       blues->ForceBold = DEFAULTFORCEBOLD;
01185  
01186   /* get the ptr to the LanguageGroup entry */
01187   HintEntryP =  &(PrivateDictP[LANGUAGEGROUP].value);
01188   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01189       blues->LanguageGroup = HintEntryP->data.integer;
01190   else
01191       blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
01192  
01193   /* get the ptr to the RndStemUp entry */
01194   HintEntryP =  &(PrivateDictP[RNDSTEMUP].value);
01195   if (objPIsBoolean(HintEntryP)) /* Must be integer! */
01196       blues->RndStemUp = HintEntryP->data.boolean;
01197   else
01198       blues->RndStemUp = DEFAULTRNDSTEMUP;
01199  
01200   /* get the ptr to the lenIV entry */
01201   HintEntryP =  &(PrivateDictP[LENIV].value);
01202   if (objPIsInteger(HintEntryP)) /* Must be integer! */
01203       blues->lenIV = HintEntryP->data.integer;
01204   else
01205       blues->lenIV = DEFAULTLENIV;
01206  
01207   /* get the ptr to the ExpansionFactor entry */
01208   HintEntryP =  &(PrivateDictP[EXPANSIONFACTOR].value);
01209   if (objPIsInteger(HintEntryP))
01210       blues->ExpansionFactor = HintEntryP->data.integer;
01211   else if (objPIsReal(HintEntryP))
01212       blues->ExpansionFactor = HintEntryP->data.real;
01213   else
01214       blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
01215   return(SCAN_OK);
01216 }
01217 /**********************************************************************/
01218 /*   GetType1CharString(fontP,code)                                   */
01219 /*                                                                    */
01220 /*          Look up code in the standard encoding vector and return   */
01221 /*          the charstring associated with the character name.        */
01222 /*                                                                    */
01223 /*   fontP  is the psfont structure.                                  */
01224 /*                                                                    */
01225 /*   Returns a psobj (string)                                         */
01226 /**********************************************************************/
01227 psobj *GetType1CharString(fontP, code)
01228 psfont *fontP;
01229 unsigned char code;
01230 {
01231   int  N;           /* the 'Nth' entry in the CharStrings       */
01232   psobj *charnameP; /* points to psobj that is name of character*/
01233  
01234   psdict *CharStringsDictP; /* dictionary with char strings     */
01235   psobj  *theStringP;  /* the definition for the code */
01236  
01237  
01238  
01239   if (StdEncArrayP == NULL) {
01240     return(NULL);
01241   }
01242   /* use the code to index into the standard encoding vector  */
01243   charnameP = &(StdEncArrayP[code]);
01244  
01245   /* test if the encoding array points to a name */
01246   if (!(objPIsName(charnameP)) ) {
01247     return(NULL);
01248   }
01249  
01250   /* Now that we have the character name out of the standardencoding */
01251   /* get the character definition out of the current font */
01252   CharStringsDictP =  fontP->CharStringsP;
01253  
01254   /* search the chars string for this charname as key */
01255   N = SearchDictName(CharStringsDictP,charnameP);
01256   if (N<=0) {
01257     return(NULL);
01258   }
01259   /* OK, the nth item is the psobj that is the string for this char */
01260   theStringP = &(CharStringsDictP[N].value);
01261  
01262   return(theStringP);
01263 }
01264  
01265 /***================================================================***/
01266 /*
01267  *   FindDictValue
01268  */
01269 /***================================================================***/
01270  
01271 static int FindDictValue(dictP)
01272     psdict    *dictP;
01273 {
01274    psobj LitName;
01275    int   N;
01276    int   V;
01277  
01278    /* we have just scanned a token and it is a literal name */
01279    /* need to check if that name is in Private dictionary */
01280    objFormatName(&LitName,tokenLength,tokenStartP);
01281    /* is it in the dictP */
01282    N = SearchDictName(dictP,&LitName);
01283    /* if found */
01284    if ( N > 0 ) {
01285      /* what type */
01286      switch (dictP[N].value.type) {
01287        case OBJ_ENCODING:
01288          V = getEncoding(&(dictP[N].value));
01289          if ( V != SCAN_OK ) return(V);
01290          break;
01291        case OBJ_ARRAY:
01292          V = getArray(&(dictP[N].value));
01293          if ( V != SCAN_OK ) return(V);
01294          break;
01295        case OBJ_INTEGER:
01296          /* next value in integer */
01297          dictP[N].value.data.integer = getInt();
01298          if (rc) return(rc);  /* if next token was not an Int */
01299          break;
01300        case OBJ_REAL:
01301          /* next value must be real or int, store as a real */
01302          scan_token(inputP);
01303          if (tokenType == TOKEN_REAL) {
01304            dictP[N].value.data.real = tokenValue.real;
01305          }
01306          else
01307            if (tokenType == TOKEN_INTEGER) {
01308              dictP[N].value.data.real = tokenValue.integer;
01309            }
01310          else return(SCAN_ERROR);
01311          break;
01312        case OBJ_NAME:
01313          V = getNextValue(TOKEN_LITERAL_NAME);
01314          if ( V != SCAN_OK ) return(V);
01315          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
01316          objFormatName(&(dictP[N].value),tokenLength,tokenStartP);
01317          break;
01318        case OBJ_STRING:
01319          V = getNextValue(TOKEN_STRING);
01320          if ( V != SCAN_OK ) return(V);
01321          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
01322          objFormatString(&(dictP[N].value),tokenLength,tokenStartP);
01323          break;
01324        case OBJ_BOOLEAN:
01325          scan_token(inputP);
01326          if (tokenType != TOKEN_NAME) {
01327            return(SCAN_ERROR);
01328          }
01329          if (0 == strncmp(tokenStartP,"true",4) ) {
01330            dictP[N].value.data.boolean =TRUE;
01331          }
01332          else
01333            if (0 == strncmp(tokenStartP,"false",5) ) {
01334              dictP[N].value.data.boolean =FALSE;
01335            }
01336            else return(SCAN_ERROR);
01337          break;
01338  
01339        default:
01340          return(SCAN_ERROR);
01341          break;
01342      }
01343    }
01344    /* Name is not in dictionary.  That is ok. */
01345    return(SCAN_OK);
01346  
01347 }
01348 /***================================================================***/
01349  
01350 /*
01351  * -------------------------------------------------------------------
01352  *  Scan the next token and convert it into an object
01353  *  Result is placed on the Operand Stack as next object
01354  * -------------------------------------------------------------------
01355  */
01356 int scan_font(FontP)
01357   psfont *FontP;
01358 {
01359  
01360  
01361   char   filename[128];
01362   char   filetype[3];
01363   FILE   *fileP;
01364   char   *nameP;
01365   int    namelen;
01366   int    V;
01367   int    i;
01368   boolean starthex80;
01369  
01370     starthex80 = FALSE;
01371     filetype[0] = 'r';
01372     filetype[1] = 'b';
01373     filetype[2] = '\0';
01374     /* copy the filename and remove leading or trailing blanks */
01375     /* point to name and search for leading blanks */
01376     nameP= FontP->FontFileName.data.nameP;
01377     namelen  = FontP->FontFileName.len;
01378     while (nameP[0] == ' ') {
01379         nameP++;
01380         namelen--;
01381     }
01382     /* now remove any trailing blanks */
01383     while ((namelen>0) && ( nameP[namelen-1] == ' ')) {
01384       namelen--;
01385     }
01386     strncpy(filename,nameP,namelen);
01387     filename[namelen] = '\0';
01388     /* file name is now constructed */
01389     inputFile.data.fileP = NULL;
01390     filterFile.data.fileP = NULL;
01391  
01392     inputP = &inputFile;
01393     if (fileP = fopen(filename,filetype)) {
01394       /* get the first byte of file */
01395       V = getc(fileP);
01396       /* if file starts with x'80' then skip next 5 bytes */
01397       if ( V == 0X80 ) {
01398         for (i=0;i<5;i++) V = getc(fileP);
01399         starthex80 = TRUE;
01400       }
01401       else ungetc(V,fileP);
01402       objFormatFile(inputP,fileP);
01403     }
01404     else {
01405       return(SCAN_FILE_OPEN_ERROR);
01406     };
01407  
01408   WantFontInfo  = TRUE;
01409   InPrivateDict = FALSE;
01410   TwoSubrs      = FALSE;
01411   rc = BuildFontInfo(FontP);
01412   if (rc != 0) return(rc);
01413  
01414   /* Assume everything will be OK */
01415   rc       = 0;
01416  
01417   /* Loop until complete font is read  */
01418   do {
01419     /* Scan the next token */
01420     scan_token(inputP);
01421  
01422     /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
01423     /* now set */
01424  
01425     switch (tokenType) {
01426       case TOKEN_EOF:
01427       case TOKEN_NONE:
01428       case TOKEN_INVALID:
01429         /* in this case we are done */
01430         if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
01431         rc = SCAN_ERROR;
01432         break;
01433       case TOKEN_LITERAL_NAME:
01434             /* Look up the name */
01435             tokenStartP[tokenLength] = '\0';
01436             if (InPrivateDict ) {
01437               if (0== strncmp(tokenStartP,"Subrs",5) ) {
01438                 rc = BuildSubrs(FontP);
01439                 break;
01440               }
01441               if (0== strncmp(tokenStartP,"CharStrings",11) ) {
01442                 rc = BuildCharStrings(FontP);
01443                 if ( (rc == SCAN_OK) ||(rc == SCAN_END) ) {
01444                   fclose(inputP->data.fileP);
01445                   /* Build the Blues Structure */
01446                   rc = GetType1Blues(FontP);
01447                   /* whatever the return code, return it */
01448                   /* all the work is done. This is the normal exit.*/
01449                   return(rc);
01450                 }
01451                 break;
01452               }
01453               rc = FindDictValue(FontP->Private);
01454               /* we are not going to report errors */
01455               /* Sometimes the font file may test a value such as */
01456               /* testing to see if the font is alreadly loaded with */
01457               /* same UniqueID.  We would faile on /UniqueID get  */
01458               /* because we are expecting a int to follow UniqueID*/
01459               /* If the correct object type does not follow a Name*/
01460               /* then we will skip over it without reporting error*/
01461               rc = SCAN_OK;
01462               break;
01463             }   /* end of reading Private dictionary */
01464             else
01465               if (0== strncmp(tokenStartP,"Private",7) ) {
01466                 InPrivateDict = TRUE;
01467                 rc = BuildPrivate(FontP);
01468                 break;
01469               }
01470               else
01471                 if (WantFontInfo) {
01472                   rc = FindDictValue(FontP->fontInfoP);
01473                   /* we are not going to report errors */
01474                   rc = SCAN_OK;
01475                   break;
01476                 }
01477         break;
01478       case TOKEN_NAME:
01479             if (0 == strncmp(tokenStartP,"eexec",5) ) {
01480                /* if file started with x'80', check next 5 bytes */
01481                if (starthex80) {
01482                  V = getc(fileP);
01483                  if ( V == 0X80 ) {
01484                    for (i=0;i<5;i++) V = getc(fileP);
01485                  }
01486                  else ungetc(V,fileP);
01487                }
01488                filterFile.data.fileP = T1eexec(inputP->data.fileP);
01489                if (filterFile.data.fileP == NULL) {
01490                  fclose(inputFile.data.fileP);
01491                  return(SCAN_FILE_OPEN_ERROR);
01492                }
01493                inputP = &filterFile;
01494  
01495                WantFontInfo = FALSE;
01496             }
01497         break;
01498     }
01499  
01500   }
01501   while (rc ==0);
01502   fclose(inputP->data.fileP);
01503   if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
01504   return(rc);
01505 }
01506