]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/Type1/scanfont.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / lib / font / Type1 / scanfont.c
1 /* $TOG: scanfont.c /main/11 1997/06/09 13:27:16 barstow $ */
2 /* Copyright International Business Machines,Corp. 1991
3  * All Rights Reserved
4  *
5  * License to use, copy, modify, and distribute this software
6  * and its documentation for any purpose and without fee is
7  * hereby granted, provided that the above copyright notice
8  * appear in all copies and that both that copyright notice and
9  * this permission notice appear in supporting documentation,
10  * and that the name of IBM not be used in advertising or
11  * publicity pertaining to distribution of the software without
12  * specific, written prior permission.
13  *
14  * IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
15  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
16  * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
18  * THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE QUALITY AND
19  * PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
20  * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF
21  * THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
22  * THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN
23  * NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
25  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
26  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
27  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28  * SOFTWARE.
29  */
30 /* Author: Katherine A. Hitchcock    IBM Almaden Research Laboratory */
31  
32 #include <string.h>
33 #include "t1stdio.h"
34 #include "util.h"
35 #include "token.h"
36 #include "fontfcn.h"
37 #include "blues.h"
38  
39  
40  
41 static int rc;
42 static boolean InPrivateDict;
43 static boolean WantFontInfo;
44 static boolean TwoSubrs;
45 static psobj inputFile;
46 static psobj filterFile;
47 static psobj *inputP;
48  
49  
50 /**********************************************************************/
51 /*   Init_BuiltInEncoding()                                           */
52 /*                                                                    */
53 /*     Initializes the StandardEncoding and ISOLatin1Encoding vector. */
54 /*                                                                    */
55 /**********************************************************************/
56 typedef struct                          /* Builtin Standard Encoding */
57 {
58    int  index;
59    char *name;
60 } EncodingTable;
61
62 static EncodingTable StdEnc[] = {
63    040 , "space",
64    041 , "exclam",
65    042 , "quotedbl",
66    043 , "numbersign",
67    044 , "dollar",
68    045 , "percent",
69    046 , "ampersand",
70    047 , "quoteright",
71    050 , "parenleft",
72    051 , "parenright",
73    052 , "asterisk",
74    053 , "plus",
75    054 , "comma",
76    055 , "hyphen",
77    056 , "period",
78    057 , "slash",
79    060 , "zero",
80    061 , "one",
81    062 , "two",
82    063 , "three",
83    064 , "four",
84    065 , "five",
85    066 , "six",
86    067 , "seven",
87    070 , "eight",
88    071 , "nine",
89    072 , "colon",
90    073 , "semicolon",
91    074 , "less",
92    075 , "equal",
93    076 , "greater",
94    077 , "question",
95   0100 , "at",
96   0101 , "A",
97   0102 , "B",
98   0103 , "C",
99   0104 , "D",
100   0105 , "E",
101   0106 , "F",
102   0107 , "G",
103   0110 , "H",
104   0111 , "I",
105   0112 , "J",
106   0113 , "K",
107   0114 , "L",
108   0115 , "M",
109   0116 , "N",
110   0117 , "O",
111   0120 , "P",
112   0121 , "Q",
113   0122 , "R",
114   0123 , "S",
115   0124 , "T",
116   0125 , "U",
117   0126 , "V",
118   0127 , "W",
119   0130 , "X",
120   0131 , "Y",
121   0132 , "Z",
122   0133 , "bracketleft",
123   0134 , "backslash",
124   0135 , "bracketright",
125   0136 , "asciicircum",
126   0137 , "underscore",
127   0140 , "quoteleft",
128   0141 , "a",
129   0142 , "b",
130   0143 , "c",
131   0144 , "d",
132   0145 , "e",
133   0146 , "f",
134   0147 , "g",
135   0150 , "h",
136   0151 , "i",
137   0152 , "j",
138   0153 , "k",
139   0154 , "l",
140   0155 , "m",
141   0156 , "n",
142   0157 , "o",
143   0160 , "p",
144   0161 , "q",
145   0162 , "r",
146   0163 , "s",
147   0164 , "t",
148   0165 , "u",
149   0166 , "v",
150   0167 , "w",
151   0170 , "x",
152   0171 , "y",
153   0172 , "z",
154   0173 , "braceleft",
155   0174 , "bar",
156   0175 , "braceright",
157   0176 , "asciitilde",
158   0241 , "exclamdown",
159   0242 , "cent",
160   0243 , "sterling",
161   0244 , "fraction",
162   0245 , "yen",
163   0246 , "florin",
164   0247 , "section",
165   0250 , "currency",
166   0251 , "quotesingle",
167   0252 , "quotedblleft",
168   0253 , "guillemotleft",
169   0254 , "guilsinglleft",
170   0255 , "guilsinglright",
171   0256 , "fi",
172   0257 , "fl",
173   0261 , "endash",
174   0262 , "dagger",
175   0263 , "daggerdbl",
176   0264 , "periodcentered",
177   0266 , "paragraph",
178   0267 , "bullet",
179   0270 , "quotesinglbase",
180   0271 , "quotedblbase",
181   0272 , "quotedblright",
182   0273 , "guillemotright",
183   0274 , "ellipsis",
184   0275 , "perthousand",
185   0277 , "questiondown",
186   0301 , "grave",
187   0302 , "acute",
188   0303 , "circumflex",
189   0304 , "tilde",
190   0305 , "macron",
191   0306 , "breve",
192   0307 , "dotaccent",
193   0310 , "dieresis",
194   0312 , "ring",
195   0313 , "cedilla",
196   0315 , "hungarumlaut",
197   0316 , "ogonek",
198   0317 , "caron",
199   0320 , "emdash",
200   0341 , "AE",
201   0343 , "ordfeminine",
202   0350 , "Lslash",
203   0351 , "Oslash",
204   0352 , "OE",
205   0353 , "ordmasculine",
206   0361 , "ae",
207   0365 , "dotlessi",
208   0370 , "lslash",
209   0371 , "oslash",
210   0372 , "oe",
211   0373 , "germandbls",
212     0,      0
213 };
214
215 static EncodingTable ISO8859Enc[] = {
216   32, "space",
217   33, "exclam",
218   34, "quotedbl",
219   35, "numbersign",
220   36, "dollar",
221   37, "percent",
222   38, "ampersand",
223   39, "quoteright",
224   40, "parenleft",
225   41, "parenright",
226   42, "asterisk",
227   43, "plus",
228   44, "comma",
229   45, "minus",
230   46, "period",
231   47, "slash",
232   48, "zero",
233   49, "one",
234   50, "two",
235   51, "three",
236   52, "four",
237   53, "five",
238   54, "six",
239   55, "seven",
240   56, "eight",
241   57, "nine",
242   58, "colon",
243   59, "semicolon",
244   60, "less",
245   61, "equal",
246   62, "greater",
247   63, "question",
248   64, "at",
249   65, "A",
250   66, "B",
251   67, "C",
252   68, "D",
253   69, "E",
254   70, "F",
255   71, "G",
256   72, "H",
257   73, "I",
258   74, "J",
259   75, "K",
260   76, "L",
261   77, "M",
262   78, "N",
263   79, "O",
264   80, "P",
265   81, "Q",
266   82, "R",
267   83, "S",
268   84, "T",
269   85, "U",
270   86, "V",
271   87, "W",
272   88, "X",
273   89, "Y",
274   90, "Z",
275   91, "bracketleft",
276   92, "backslash",
277   93, "bracketright",
278   94, "asciicircum",
279   95, "underscore",
280   96, "quoteleft",
281   97, "a",
282   98, "b",
283   99, "c",
284  100, "d",
285  101, "e",
286  102, "f",
287  103, "g",
288  104, "h",
289  105, "i",
290  106, "j",
291  107, "k",
292  108, "l",
293  109, "m",
294  110, "n",
295  111, "o",
296  112, "p",
297  113, "q",
298  114, "r",
299  115, "s",
300  116, "t",
301  117, "u",
302  118, "v",
303  119, "w",
304  120, "x",
305  121, "y",
306  122, "z",
307  123, "braceleft",
308  124, "bar",
309  125, "braceright",
310  126, "asciitilde",
311  161, "exclamdown",
312  162, "cent",
313  163, "sterling",
314  164, "currency",
315  165, "yen",
316  166, "brokenbar",
317  167, "section",
318  168, "dieresis",
319  169, "copyright",
320  170, "ordfeminine",
321  171, "guillemotleft",
322  172, "logicalnot",
323  173, "hyphen",
324  174, "registered",
325  175, "macron",
326  176, "degree",
327  177, "plusminus",
328  178, "twosuperior",
329  179, "threesuperior",
330  180, "acute",
331  181, "mu",
332  182, "paragraph",
333  183, "periodcentered",
334  184, "cedilla",
335  185, "onesuperior",
336  186, "ordmasculine",
337  187, "guillemotright",
338  188, "onequarter",
339  189, "onehalf",
340  190, "threequarters",
341  191, "questiondown",
342  192, "Agrave",
343  193, "Aacute",
344  194, "Acircumflex",
345  195, "Atilde",
346  196, "Adieresis",
347  197, "Aring",
348  198, "AE",
349  199, "Ccedilla",
350  200, "Egrave",
351  201, "Eacute",
352  202, "Ecircumflex",
353  203, "Edieresis",
354  204, "Igrave",
355  205, "Iacute",
356  206, "Icircumflex",
357  207, "Idieresis",
358  208, "Eth",
359  209, "Ntilde",
360  210, "Ograve",
361  211, "Oacute",
362  212, "Ocircumflex",
363  213, "Otilde",
364  214, "Odieresis",
365  215, "multiply",
366  216, "Oslash",
367  217, "Ugrave",
368  218, "Uacute",
369  219, "Ucircumflex",
370  220, "Udieresis",
371  221, "Yacute",
372  222, "Thorn",
373  223, "germandbls",
374  224, "agrave",
375  225, "aacute",
376  226, "acircumflex",
377  227, "atilde",
378  228, "adieresis",
379  229, "aring",
380  230, "ae",
381  231, "ccedilla",
382  232, "egrave",
383  233, "eacute",
384  234, "ecircumflex",
385  235, "edieresis",
386  236, "igrave",
387  237, "iacute",
388  238, "icircumflex",
389  239, "idieresis",
390  240, "eth",
391  241, "ntilde",
392  242, "ograve",
393  243, "oacute",
394  244, "ocircumflex",
395  245, "otilde",
396  246, "odieresis",
397  247, "divide",
398  248, "oslash",
399  249, "ugrave",
400  250, "uacute",
401  251, "ucircumflex",
402  252, "udieresis",
403  253, "yacute",
404  254, "thorn",
405  255, "ydieresis",
406     0,      0
407 };
408
409 static psobj *StdEncArrayP = NULL;
410 psobj *ISOLatin1EncArrayP = NULL; 
411  
412 static psobj *MakeEncodingArrayP(encodingTable)
413     EncodingTable *encodingTable;
414 {
415   int i;
416   psobj *encodingArrayP;
417  
418   encodingArrayP = (psobj *)vm_alloc(256*(sizeof(psobj)));
419   if (!encodingArrayP)
420       return NULL;
421
422   /* initialize everything to .notdef */
423   for (i=0; i<256;i++)
424       objFormatName(&(encodingArrayP[i]),7, ".notdef");
425
426   for (i=0; encodingTable[i].name; i++)
427   {
428       objFormatName(&(encodingArrayP[encodingTable[i].index]),
429                     strlen(encodingTable[i].name),
430                     encodingTable[i].name);
431   }
432
433   return(encodingArrayP);
434 }
435  
436 boolean Init_BuiltInEncoding()
437 {
438     StdEncArrayP = MakeEncodingArrayP(StdEnc);
439     ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
440     return (StdEncArrayP && ISOLatin1EncArrayP);
441 }
442  
443 /********************************************************************/
444 /***================================================================***/
445 static int getNextValue(valueType)
446     int valueType;
447 {
448   scan_token(inputP);
449   if (tokenType != valueType) {
450     return(SCAN_ERROR);
451   }
452   return(SCAN_OK);
453  
454 }
455 /***================================================================***/
456 /*  This routine will set the global rc if there is an error          */
457 /***================================================================***/
458 static int getInt()
459 {
460   scan_token(inputP);
461   if (tokenType != TOKEN_INTEGER) {
462     rc = SCAN_ERROR;
463     return(0);
464   }
465   else {
466     return( tokenValue.integer);
467   }
468  
469 }
470 /***================================================================***/
471 /*
472  * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
473  * for parsing Encoding.
474  */
475 static int getEncoding(arrayP)
476     psobj *arrayP;
477 {
478
479   scan_token(inputP);
480   if ((tokenType == TOKEN_NAME)
481                 &&
482      (((tokenLength==16) && (!strncmp(tokenStartP,"StandardEncoding",16))) ||
483       (((tokenLength==17) && (!strncmp(tokenStartP,"ISOLatin1Encoding",17))))))
484   {
485       /* Adobe Standard Encoding */
486
487       if (tokenLength == 16)
488           arrayP->data.valueP = (char *) StdEncArrayP;
489       else
490           arrayP->data.valueP = (char *) ISOLatin1EncArrayP;
491
492       arrayP->len = 256;
493       return(SCAN_OK);
494   }
495   else if ( (tokenType == TOKEN_LEFT_BRACE) ||
496        (tokenType == TOKEN_LEFT_BRACKET) )
497   {
498       /* Array of literal names */
499
500       psobj *objP;
501       int i;
502
503       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
504       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
505
506       arrayP->data.valueP = (char *) objP;
507       arrayP->len = 256;
508
509       for (i=0; i<256; i++, objP++)
510       {
511           scan_token(inputP);
512           
513           if (tokenType != TOKEN_LITERAL_NAME)
514               return(SCAN_ERROR);
515
516           if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
517           objFormatName(objP,tokenLength,tokenStartP);
518       }
519
520       scan_token(inputP);
521       if ( (tokenType == TOKEN_RIGHT_BRACE) ||
522           (tokenType == TOKEN_RIGHT_BRACKET) )
523           return(SCAN_OK);
524   }
525   else
526   {
527       /* Must be sequences of ``dup <index> <charactername> put" */
528
529       psobj *objP;
530       int i;
531
532       objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
533       if (!(objP)) return(SCAN_OUT_OF_MEMORY);
534
535       arrayP->data.valueP = (char *) objP;
536       arrayP->len = 256;
537
538       for (i=0; i<256; i++)
539           objFormatName(objP + i, 7, ".notdef");
540
541       while (TRUE)
542       {
543           scan_token(inputP);
544
545           switch (tokenType)
546           {
547           case TOKEN_NAME:
548               if (tokenLength == 3)
549               {
550                   if (strncmp(tokenStartP,"dup",3) == 0)
551                   {
552                       /* get <index> */
553                       scan_token(inputP);
554                       if (tokenType != TOKEN_INTEGER ||
555                           tokenValue.integer < 0 ||
556                           tokenValue.integer > 255)
557                           return (SCAN_ERROR);
558                       i = tokenValue.integer;
559
560                       /* get <characer_name> */
561                       scan_token(inputP);
562                       if (tokenType != TOKEN_LITERAL_NAME)
563                           return(SCAN_ERROR);
564
565                       if (!(vm_alloc(tokenLength)) )
566                           return(SCAN_OUT_OF_MEMORY);
567                       objFormatName(objP + i,tokenLength,tokenStartP);
568
569                       /* get "put" */
570                       scan_token(inputP);
571                       if (tokenType != TOKEN_NAME)
572                           return(SCAN_ERROR);
573                   }
574                   else if (strncmp(tokenStartP,"def",3) == 0)
575                       return (SCAN_OK);
576               }
577               break;
578           case TOKEN_EOF:
579           case TOKEN_NONE:
580           case TOKEN_INVALID:
581               return (SCAN_ERROR);
582           }
583       }
584   }
585
586   return (SCAN_ERROR);
587 }
588 /***================================================================***/
589 static int getArray(arrayP)
590     psobj *arrayP;
591 {
592   int N;   /* count the items in the array */
593   psobj *objP;
594
595   /* That is totally a kludge. If some stupid font file has
596    *    /foo/foo        # ftp://ftp.cdrom.com/pub/os2/fonts/future.zip
597    * we will treat it as /foo.
598    *  H.J. */
599   char tmp [1024];
600
601   strncpy (tmp, tokenStartP, sizeof (tmp));
602   tmp [sizeof (tmp) - 1] = '\0';
603
604 restart: 
605   scan_token(inputP);
606   switch (tokenType)
607   {
608   case TOKEN_LEFT_BRACE:
609   case TOKEN_LEFT_BRACKET:
610     break;
611
612   case TOKEN_LITERAL_NAME:
613     tokenStartP[tokenLength] = '\0';
614     if (strcmp (tokenStartP, tmp) == 0)
615     {
616       /* Ok, We see /foo/foo. Let's restart. */
617       goto restart;
618     }
619
620   default:
621     return(SCAN_ERROR);
622   }
623   /* format the array in memory, save pointer to the beginning */
624   arrayP->data.valueP = tokenStartP;
625   /* loop, picking up next object, until right BRACE or BRACKET */
626   N = 0;
627   do {
628     scan_token(inputP);
629     if ( (tokenType == TOKEN_RIGHT_BRACE) ||
630          (tokenType == TOKEN_RIGHT_BRACKET) ) {
631       /* save then number of items in the array */
632       arrayP->len = N;
633       return(SCAN_OK);
634     }
635      /* allocate the space for the object */
636     objP = (psobj *)vm_alloc(sizeof(psobj));
637     if (!(objP)) return(SCAN_OUT_OF_MEMORY);
638  
639     /* array is an array of numbers, (real or integer)  */
640     if (tokenType == TOKEN_REAL) {
641       objFormatReal(objP, tokenValue.real);
642     }
643     else
644       if (tokenType == TOKEN_INTEGER) {
645         objFormatInteger(objP, tokenValue.integer);
646       }
647       else return(SCAN_ERROR);
648     N++;
649   }  while ( 1>0 );
650   /* NOTREACHED*/
651 }
652 /***================================================================***/
653 static int getName(nameP)
654     char *nameP;
655 {
656   do {
657     scan_token(inputP);
658     if (tokenType <= TOKEN_NONE) {
659       if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
660       return(SCAN_ERROR);
661     }
662   } while ((tokenType != TOKEN_NAME) ||
663     (0 != strncmp(tokenStartP,nameP,strlen(nameP))) );
664   /* found */
665   return(SCAN_OK);
666 }
667 /***================================================================***/
668 static int getNbytes(N)
669     int N;
670 {
671   int I;
672  
673  
674   tokenStartP = vm_next_byte();
675   tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
676   if (N > vm_free_bytes()) {
677     return(SCAN_OUT_OF_MEMORY);
678   }
679   I = fread(tokenStartP,1,N,inputP->data.fileP);
680   if ( I != N )     return(SCAN_FILE_EOF);
681   return(SCAN_OK);
682 }
683  
684 /***================================================================***/
685 /*  getLiteralName(nameObjP)                                          */
686 /*     scan for next literal.                                         */
687 /*  if we encounter the name 'end' then terminate and say ok.         */
688 /*    It means that the CharStrings does not have as many characters  */
689 /*    as the dictionary said it would and that is ok.                 */
690 /***================================================================***/
691 static int getLiteralName(nameObjP)
692     psobj *nameObjP;
693 {
694   do {
695     scan_token(inputP);
696     if (tokenType <= TOKEN_NONE) {
697       if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
698       return(SCAN_ERROR);
699     }
700     if (tokenType == TOKEN_NAME) {
701       if (0 == strncmp(tokenStartP,"end",3) ) {
702         return(SCAN_END);
703       }
704     }
705   } while  (tokenType != TOKEN_LITERAL_NAME) ;
706   nameObjP->len = tokenLength;
707   /* allocate all the names in the CharStrings Structure */
708   if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
709   nameObjP->data.valueP =  tokenStartP;
710   /* found */
711   return(SCAN_OK);
712 }
713  
714 /***================================================================***/
715 /*
716  *   BuildSubrs routine
717  */
718 /***================================================================***/
719  
720 static int BuildSubrs(FontP)
721     psfont *FontP;
722 {
723    int N;   /* number of values in Subrs */
724    int I;   /* index into Subrs */
725    int i;   /* loop thru  Subrs */
726    int J;   /* length of Subrs entry */
727    psobj *arrayP;
728  
729    /* next token should be a positive int */
730    /* note: rc is set by getInt. */
731    N = getInt();
732    if (rc) return(rc);
733    if (N < 0 ) return(SCAN_ERROR);
734    /* if we already have a Subrs, then skip the second one */
735    /* The second one is for hiresolution devices.          */
736    if (FontP->Subrs.data.arrayP != NULL) {
737      TwoSubrs = TRUE;
738      /* process all the Subrs, but do not update anything */
739      /* can not just skip them because of the binary data */
740      for (i=0;i<N;i++) {
741        /* look for dup */
742        rc = getName("dup");
743        if (rc) return(rc);
744        /* get 2 integers */
745        I = getInt();
746        if (rc) return(rc);
747        J = getInt();
748        if (rc) return(rc);
749        if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
750        /* get the next token, it should be RD or -|, either is ok */
751        rc = getNextValue(TOKEN_NAME);
752        if ( rc != SCAN_OK ) return(rc);
753        rc = getNbytes(J);
754        if (rc) return(rc);
755      }
756      return(SCAN_OK);
757    }
758  
759    arrayP = (psobj *)vm_alloc(N*sizeof(psobj));
760    if (!(arrayP) ) return(SCAN_OUT_OF_MEMORY);
761    FontP->Subrs.len = N;
762    FontP->Subrs.data.arrayP =  arrayP;
763    /* get N values for Subrs */
764    for (i=0;i<N;i++) {
765      /* look for dup */
766      rc = getName("dup");
767      if (rc) return(rc);
768      /* get 2 integers */
769      I = getInt();
770      if (rc) return(rc);
771      J = getInt();
772      if (rc) return(rc);
773      if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
774      arrayP[I].len = J;
775      /* get the next token, it should be RD or -|, either is ok */
776      rc = getNextValue(TOKEN_NAME);
777      if ( rc != SCAN_OK ) return(rc);
778      rc = getNbytes(J);
779      if (rc == SCAN_OK) {
780        arrayP[I].data.valueP = tokenStartP;
781        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
782      }
783      else return(rc);
784    }
785    return(SCAN_OK);
786  
787 }
788 /***================================================================***/
789 /***================================================================***/
790 /*
791  *   BuildCharStrings routine
792  */
793 /***================================================================***/
794  
795 static int BuildCharStrings(FontP)
796     psfont   *FontP;
797 {
798    int N;   /* number of values in CharStrings */
799    int i;   /* loop thru  Subrs */
800    int J;   /* length of Subrs entry */
801    psdict  *dictP;
802  
803    /* next token should be a positive int */
804    N = getInt();
805    if (rc) {
806      /* check if file had TwoSubrs, hi resolution stuff is in file*/
807      if (TwoSubrs) {
808        do {
809          scan_token(inputP);
810          if (tokenType <= TOKEN_NONE) {
811            if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
812            return(SCAN_ERROR);
813          }
814        } while (tokenType != TOKEN_INTEGER);
815        N = tokenValue.integer;
816      }
817      else return(rc);  /* if next token was not an Int */
818    }
819    if (N<=0) return(SCAN_ERROR);
820    /* save number of entries in the dictionary */
821  
822    dictP = (psdict *)vm_alloc((N+1)*sizeof(psdict));
823    if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
824    FontP->CharStringsP = dictP;
825    dictP[0].key.len = N;
826    /* get N values for CharStrings */
827    for (i=1;i<=N;i++) {
828      /* look for next literal name  */
829      rc = getLiteralName(&(dictP[i].key));
830      if (rc) return(rc);
831      /* get 1 integer */
832      J = getInt();
833      if (rc) return(rc);  /* if next token was not an Int */
834      if (J<0) return (SCAN_ERROR);
835      dictP[i].value.len = J;
836      /* get the next token, it should be RD or -|, either is ok */
837      rc = getNextValue(TOKEN_NAME);
838      if ( rc != SCAN_OK ) return(rc);
839      rc = getNbytes(J);
840      if (rc == SCAN_OK) {
841        dictP[i].value.data.valueP = tokenStartP;
842        if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
843      }
844      else return(rc);
845    }
846    return(SCAN_OK);
847  
848 }
849 /***================================================================***/
850 /***================================================================***/
851 /*
852  *   BuildFontInfo Dictionary
853  */
854 /***================================================================***/
855 static int BuildFontInfo(fontP)
856     psfont *fontP;
857 {
858   psdict *dictP;
859  
860   /* allocate the private dictionary */
861   dictP = (psdict *)vm_alloc(20*sizeof(psdict));
862   if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
863  
864   fontP->fontInfoP = dictP;
865   fontP->fontInfoP[0].key.len = 17;  /* number of actual entries */
866   objFormatName(&(dictP[FONTNAME].key),8,"FontName");
867   objFormatName(&(dictP[FONTNAME].value),0,NULL);
868   objFormatName(&(dictP[PAINTTYPE].key),9,"PaintType");
869   objFormatInteger(&(dictP[PAINTTYPE].value),0);
870   objFormatName(&(dictP[FONTTYPENUM].key),8,"FontType");
871   objFormatInteger(&(dictP[FONTTYPENUM].value),0);
872   objFormatName(&(dictP[FONTMATRIX].key),10,"FontMatrix");
873   objFormatArray(&(dictP[FONTMATRIX].value),0,NULL);
874   objFormatName(&(dictP[FONTBBOX].key),8,"FontBBox");
875   objFormatArray(&(dictP[FONTBBOX].value),0,NULL);
876   objFormatName(&(dictP[ENCODING].key),8,"Encoding");
877   objFormatEncoding(&(dictP[ENCODING].value),0,NULL);
878   objFormatName(&(dictP[UNIQUEID].key),8,"UniqueID");
879   objFormatInteger(&(dictP[UNIQUEID].value),0);
880   objFormatName(&(dictP[STROKEWIDTH].key),11,"StrokeWidth");
881   objFormatReal(&(dictP[STROKEWIDTH].value),0.0);
882   objFormatName(&(dictP[VERSION].key),7,"version");
883   objFormatString(&(dictP[VERSION].value),0,NULL);
884   objFormatName(&(dictP[NOTICE].key),6,"Notice");
885   objFormatString(&(dictP[NOTICE].value),0,NULL);
886   objFormatName(&(dictP[FULLNAME].key),8,"FullName");
887   objFormatString(&(dictP[FULLNAME].value),0,NULL);
888   objFormatName(&(dictP[FAMILYNAME].key),10,"FamilyName");
889   objFormatString(&(dictP[FAMILYNAME].value),0,NULL);
890   objFormatName(&(dictP[WEIGHT].key),6,"Weight");
891   objFormatString(&(dictP[WEIGHT].value),0,NULL);
892   objFormatName(&(dictP[ITALICANGLE].key),11,"ItalicAngle");
893   objFormatReal(&(dictP[ITALICANGLE].value),0.0);
894   objFormatName(&(dictP[ISFIXEDPITCH].key),12,"isFixedPitch");
895   objFormatBoolean(&(dictP[ISFIXEDPITCH].value),FALSE);
896   objFormatName(&(dictP[UNDERLINEPOSITION].key),17,"UnderlinePosition");
897   objFormatReal(&(dictP[UNDERLINEPOSITION].value),0.0);
898   objFormatName(&(dictP[UNDERLINETHICKNESS].key),18,"UnderlineThickness");
899   objFormatReal(&(dictP[UNDERLINETHICKNESS].value),0.0);
900   return(SCAN_OK);
901 }
902 /***================================================================***/
903 /*
904  *   BuildPrivate Dictionary
905  */
906 /***================================================================***/
907 static int BuildPrivate(fontP)
908     psfont *fontP;
909 {
910   psdict *Private;
911  
912   /* allocate the private dictionary */
913   Private = (psdict *)vm_alloc(20*sizeof(psdict));
914  
915   if (!(Private)) return(SCAN_OUT_OF_MEMORY);
916  
917   fontP->Private = Private;
918   fontP->Private[0].key.len = 16;  /* number of actual entries */
919  
920   objFormatName(&(Private[BLUEVALUES].key),10,"BlueValues");
921   objFormatArray(&(Private[BLUEVALUES].value),0,NULL);
922   objFormatName(&(Private[OTHERBLUES].key),10,"OtherBlues");
923   objFormatArray(&(Private[OTHERBLUES].value),0,NULL);
924   objFormatName(&(Private[FAMILYBLUES].key),11,"FamilyBlues");
925   objFormatArray(&(Private[FAMILYBLUES].value),0,NULL);
926   objFormatName(&(Private[FAMILYOTHERBLUES].key),16,"FamilyOtherBlues");
927   objFormatArray(&(Private[FAMILYOTHERBLUES].value),0,NULL);
928   objFormatName(&(Private[BLUESCALE].key),9,"BlueScale");
929   objFormatReal(&(Private[BLUESCALE].value),DEFAULTBLUESCALE);
930   objFormatName(&(Private[BLUESHIFT].key),9,"BlueShift");
931   objFormatInteger(&(Private[BLUESHIFT].value),DEFAULTBLUESHIFT);
932   objFormatName(&(Private[BLUEFUZZ].key),8,"BlueFuzz");
933   objFormatInteger(&(Private[BLUEFUZZ].value),DEFAULTBLUEFUZZ);
934   objFormatName(&(Private[STDHW].key),5,"StdHW");
935   objFormatArray(&(Private[STDHW].value),0,NULL);
936   objFormatName(&(Private[STDVW].key),5,"StdVW");
937   objFormatArray(&(Private[STDVW].value),0,NULL);
938   objFormatName(&(Private[STEMSNAPH].key),9,"StemSnapH");
939   objFormatArray(&(Private[STEMSNAPH].value),0,NULL);
940   objFormatName(&(Private[STEMSNAPV].key),9,"StemSnapV");
941   objFormatArray(&(Private[STEMSNAPV].value),0,NULL);
942   objFormatName(&(Private[FORCEBOLD].key),9,"ForceBold");
943   objFormatBoolean(&(Private[FORCEBOLD].value),DEFAULTFORCEBOLD);
944   objFormatName(&(Private[LANGUAGEGROUP].key),13,"LanguageGroup");
945   objFormatInteger(&(Private[LANGUAGEGROUP].value),DEFAULTLANGUAGEGROUP);
946   objFormatName(&(Private[LENIV].key),5,"lenIV");
947   objFormatInteger(&(Private[LENIV].value),DEFAULTLENIV);
948   objFormatName(&(Private[RNDSTEMUP].key),9,"RndStemUp");
949   objFormatBoolean(&(Private[RNDSTEMUP].value),DEFAULTRNDSTEMUP);
950   objFormatName(&(Private[EXPANSIONFACTOR].key),9,"ExpansionFactor");
951   objFormatReal(&(Private[EXPANSIONFACTOR].value),
952                           DEFAULTEXPANSIONFACTOR);
953   return(SCAN_OK);
954 }
955 /***================================================================***/
956 /**********************************************************************/
957 /*     GetType1Blues(fontP)                                           */
958 /*                                                                    */
959 /*   Routine to support font-level hints.                             */
960 /*                                                                    */
961 /*         Gets all the Blues information from the Private dictionary */
962 /*         for the font.                                              */
963 /*                                                                    */
964 /*                                                                    */
965 /**********************************************************************/
966 static int GetType1Blues(fontP)
967     psfont *fontP;
968 {
969   psdict *PrivateDictP;   /* the Private dict relating to hints */
970   struct blues_struct *blues;  /* ptr for the blues struct we will allocate */
971   int i;
972   psobj *HintEntryP;
973  
974  
975  
976   /* get the Private dictionary pointer */
977   PrivateDictP = fontP->Private;
978  
979   /* allocate the memory for the blues structure */
980   blues = (struct blues_struct *) vm_alloc(sizeof(struct blues_struct));
981  
982   if (!blues)  return(SCAN_OUT_OF_MEMORY);
983  
984   /* Make fontP's blues ptr point to this newly allocated structure. */
985   fontP->BluesP = blues;
986  
987   /* fill in the BlueValues array */
988   HintEntryP = &(PrivateDictP[BLUEVALUES].value);
989   /* check to see if the entry exists and if it's an array */
990   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
991       blues->numBlueValues = 0;
992   else {
993       /* get the number of values in the array */
994       if (HintEntryP->len > NUMBLUEVALUES) {
995           blues->numBlueValues = NUMBLUEVALUES;
996       } else
997           blues->numBlueValues = HintEntryP->len;
998       for (i = 0; i<= blues->numBlueValues-1; ++i) {
999           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1000               blues->BlueValues[i] =
1001                   HintEntryP->data.arrayP[i].data.integer;
1002           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1003               blues->BlueValues[i] =
1004                   HintEntryP->data.arrayP[i].data.real;
1005           else
1006               blues->BlueValues[i] = 0;
1007       }
1008   }
1009  
1010   /* fill in the OtherBlues array */
1011   HintEntryP =  &(PrivateDictP[OTHERBLUES].value);
1012   /* check to see if the entry exists and if it's an array */
1013   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1014       blues->numOtherBlues = 0;
1015   else {
1016       /* get the number of values in the array */
1017       if (HintEntryP->len > NUMOTHERBLUES) {
1018           blues->numOtherBlues = NUMOTHERBLUES;
1019       } else
1020           blues->numOtherBlues = HintEntryP->len;
1021       for (i = 0; i<= blues->numOtherBlues-1; ++i) {
1022           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1023               blues->OtherBlues[i] =
1024                   HintEntryP->data.arrayP[i].data.integer;
1025           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1026               blues->OtherBlues[i] =
1027                   HintEntryP->data.arrayP[i].data.real;
1028           else
1029               blues->OtherBlues[i] = 0;
1030       }
1031   }
1032  
1033   /* fill in the FamilyBlues array */
1034   HintEntryP =  &(PrivateDictP[FAMILYBLUES].value);
1035   /* check to see if the entry exists and if it's an array */
1036   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1037       blues->numFamilyBlues = 0;
1038   else {
1039       /* get the number of values in the array */
1040       if (HintEntryP->len > NUMFAMILYBLUES) {
1041           blues->numFamilyBlues = NUMFAMILYBLUES;
1042       } else
1043           blues->numFamilyBlues = HintEntryP->len;
1044       for (i = 0; i<= blues->numFamilyBlues-1; ++i) {
1045           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1046               blues->FamilyBlues[i] =
1047                   HintEntryP->data.arrayP[i].data.integer;
1048           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1049               blues->FamilyBlues[i] =
1050                   HintEntryP->data.arrayP[i].data.real;
1051           else
1052               blues->FamilyBlues[i] = 0;
1053       }
1054   }
1055  
1056   /* fill in the FamilyOtherBlues array */
1057   HintEntryP =  &(PrivateDictP[FAMILYOTHERBLUES].value);
1058   /* check to see if the entry exists and if it's an array */
1059   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1060       blues->numFamilyOtherBlues = 0;
1061   else {
1062       /* get the number of values in the array */
1063       if (HintEntryP->len > NUMFAMILYOTHERBLUES) {
1064           blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
1065       } else
1066           blues->numFamilyOtherBlues = HintEntryP->len;
1067       for (i = 0; i<= blues->numFamilyOtherBlues-1; ++i) {
1068           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1069               blues->FamilyOtherBlues[i] =
1070                   HintEntryP->data.arrayP[i].data.integer;
1071           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1072               blues->FamilyOtherBlues[i] =
1073                   HintEntryP->data.arrayP[i].data.real;
1074           else
1075               blues->FamilyOtherBlues[i] = 0;
1076       }
1077   }
1078  
1079   /* fill in the StemSnapH array */
1080   HintEntryP =  &(PrivateDictP[STEMSNAPH].value);
1081   /* check to see if the entry exists and if it's an array */
1082   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1083       blues->numStemSnapH = 0;
1084   else {
1085       /* get the number of values in the array */
1086       if (HintEntryP->len > NUMSTEMSNAPH) {
1087           blues->numStemSnapH = NUMSTEMSNAPH;
1088       } else
1089           blues->numStemSnapH = HintEntryP->len;
1090       for (i = 0; i<= blues->numStemSnapH-1; ++i) {
1091           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1092               blues->StemSnapH[i] =
1093                   HintEntryP->data.arrayP[i].data.integer;
1094           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1095               blues->StemSnapH[i] =
1096                   HintEntryP->data.arrayP[i].data.real;
1097           else
1098               blues->StemSnapH[i] = 0;
1099       }
1100   }
1101  
1102   /* fill in the StemSnapV array */
1103   HintEntryP =  &(PrivateDictP[STEMSNAPV].value);
1104   /* check to see if the entry exists and if it's an array */
1105   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1106       blues->numStemSnapV = 0;
1107   else {
1108       /* get the number of values in the array */
1109       if (HintEntryP->len > NUMSTEMSNAPV) {
1110           blues->numStemSnapV = NUMSTEMSNAPV;
1111       } else
1112           blues->numStemSnapV = HintEntryP->len;
1113       for (i = 0; i<= blues->numStemSnapV-1; ++i) {
1114           if (objPIsInteger(&HintEntryP->data.arrayP[i]))
1115               blues->StemSnapV[i] =
1116                   HintEntryP->data.arrayP[i].data.integer;
1117           else if (objPIsReal(&HintEntryP->data.arrayP[i]))
1118               blues->StemSnapV[i] =
1119                   HintEntryP->data.arrayP[i].data.real;
1120           else
1121               blues->StemSnapV[i] = 0;
1122       }
1123   }
1124  
1125   /* fill in the StdVW array */
1126   HintEntryP =  &(PrivateDictP[STDVW].value);
1127   /* check to see if the entry exists and if it's an array */
1128   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1129       /* a value of zero signifies no entry */
1130       blues->StdVW = 0;
1131   else {
1132       if (HintEntryP->len > NUMSTDVW) {
1133       }
1134       if (objPIsInteger(&HintEntryP->data.arrayP[0]))
1135           blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
1136       else if (objPIsReal(&HintEntryP->data.arrayP[0]))
1137           blues->StdVW = HintEntryP->data.arrayP[0].data.real;
1138       else
1139           blues->StdVW = 0;
1140   }
1141  
1142   /* fill in the StdHW array */
1143   HintEntryP =  &(PrivateDictP[STDHW].value);
1144   /* check to see if the entry exists and if it's an array */
1145   if ( !objPIsArray(HintEntryP) || (HintEntryP->len == 0 ))
1146       /* a value of zero signifies no entry */
1147       blues->StdHW = 0;
1148   else {
1149       if (HintEntryP->len > NUMSTDHW) {
1150       }
1151           if (objPIsInteger(&HintEntryP->data.arrayP[0]))
1152              blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
1153           else if (objPIsReal(&HintEntryP->data.arrayP[0]))
1154              blues->StdHW = HintEntryP->data.arrayP[0].data.real;
1155           else
1156              blues->StdHW = 0;
1157   }
1158  
1159  
1160   /* get the ptr to the BlueScale entry */
1161   HintEntryP =  &(PrivateDictP[BLUESCALE].value);
1162   /* put the BlueScale in the blues structure */
1163   if (objPIsInteger(HintEntryP)) /* Must be integer! */
1164       blues->BlueScale = HintEntryP->data.integer;
1165   else if (objPIsReal(HintEntryP)) /* Error? */
1166       blues->BlueScale = HintEntryP->data.real;
1167   else
1168       blues->BlueScale = DEFAULTBLUESCALE;
1169  
1170   /* get the ptr to the BlueShift entry */
1171   HintEntryP =  &(PrivateDictP[BLUESHIFT].value);
1172   if (objPIsInteger(HintEntryP)) /* Must be integer! */
1173       blues->BlueShift = HintEntryP->data.integer;
1174   else if (objPIsReal(HintEntryP)) /* Error? */
1175       blues->BlueShift = HintEntryP->data.real;
1176   else
1177       blues->BlueShift = DEFAULTBLUESHIFT;
1178  
1179   /* get the ptr to the BlueFuzz entry */
1180   HintEntryP =  &(PrivateDictP[BLUEFUZZ].value);
1181   if (objPIsInteger(HintEntryP)) /* Must be integer! */
1182       blues->BlueFuzz = HintEntryP->data.integer;
1183   else if (objPIsReal(HintEntryP)) /* Error? */
1184       blues->BlueFuzz = HintEntryP->data.real;
1185   else
1186       blues->BlueFuzz = DEFAULTBLUEFUZZ;
1187  
1188   /* get the ptr to the ForceBold entry */
1189   HintEntryP =  &(PrivateDictP[FORCEBOLD].value);
1190   if (objPIsBoolean(HintEntryP))  /* Must be integer! */
1191       blues->ForceBold = HintEntryP->data.boolean;
1192   else
1193       blues->ForceBold = DEFAULTFORCEBOLD;
1194  
1195   /* get the ptr to the LanguageGroup entry */
1196   HintEntryP =  &(PrivateDictP[LANGUAGEGROUP].value);
1197   if (objPIsInteger(HintEntryP)) /* Must be integer! */
1198       blues->LanguageGroup = HintEntryP->data.integer;
1199   else
1200       blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
1201  
1202   /* get the ptr to the RndStemUp entry */
1203   HintEntryP =  &(PrivateDictP[RNDSTEMUP].value);
1204   if (objPIsBoolean(HintEntryP)) /* Must be integer! */
1205       blues->RndStemUp = HintEntryP->data.boolean;
1206   else
1207       blues->RndStemUp = DEFAULTRNDSTEMUP;
1208  
1209   /* get the ptr to the lenIV entry */
1210   HintEntryP =  &(PrivateDictP[LENIV].value);
1211   if (objPIsInteger(HintEntryP)) /* Must be integer! */
1212       blues->lenIV = HintEntryP->data.integer;
1213   else
1214       blues->lenIV = DEFAULTLENIV;
1215  
1216   /* get the ptr to the ExpansionFactor entry */
1217   HintEntryP =  &(PrivateDictP[EXPANSIONFACTOR].value);
1218   if (objPIsInteger(HintEntryP))
1219       blues->ExpansionFactor = HintEntryP->data.integer;
1220   else if (objPIsReal(HintEntryP))
1221       blues->ExpansionFactor = HintEntryP->data.real;
1222   else
1223       blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
1224   return(SCAN_OK);
1225 }
1226 /**********************************************************************/
1227 /*   GetType1CharString(fontP,code)                                   */
1228 /*                                                                    */
1229 /*          Look up code in the standard encoding vector and return   */
1230 /*          the charstring associated with the character name.        */
1231 /*                                                                    */
1232 /*   fontP  is the psfont structure.                                  */
1233 /*                                                                    */
1234 /*   Returns a psobj (string)                                         */
1235 /**********************************************************************/
1236 psobj *GetType1CharString(fontP, code)
1237 psfont *fontP;
1238 unsigned char code;
1239 {
1240   int  N;           /* the 'Nth' entry in the CharStrings       */
1241   psobj *charnameP; /* points to psobj that is name of character*/
1242  
1243   psdict *CharStringsDictP; /* dictionary with char strings     */
1244   psobj  *theStringP;  /* the definition for the code */
1245  
1246  
1247  
1248   if (StdEncArrayP == NULL) {
1249     return(NULL);
1250   }
1251   /* use the code to index into the standard encoding vector  */
1252   charnameP = &(StdEncArrayP[code]);
1253  
1254   /* test if the encoding array points to a name */
1255   if (!(objPIsName(charnameP)) ) {
1256     return(NULL);
1257   }
1258  
1259   /* Now that we have the character name out of the standardencoding */
1260   /* get the character definition out of the current font */
1261   CharStringsDictP =  fontP->CharStringsP;
1262  
1263   /* search the chars string for this charname as key */
1264   N = SearchDictName(CharStringsDictP,charnameP);
1265   if (N<=0) {
1266     return(NULL);
1267   }
1268   /* OK, the nth item is the psobj that is the string for this char */
1269   theStringP = &(CharStringsDictP[N].value);
1270  
1271   return(theStringP);
1272 }
1273  
1274 /***================================================================***/
1275 /*
1276  *   FindDictValue
1277  */
1278 /***================================================================***/
1279  
1280 static int FindDictValue(dictP)
1281     psdict    *dictP;
1282 {
1283    psobj LitName;
1284    int   N;
1285    int   V;
1286  
1287    /* we have just scanned a token and it is a literal name */
1288    /* need to check if that name is in Private dictionary */
1289    objFormatName(&LitName,tokenLength,tokenStartP);
1290    /* is it in the dictP */
1291    N = SearchDictName(dictP,&LitName);
1292    /* if found */
1293    if ( N > 0 ) {
1294      /* what type */
1295      switch (dictP[N].value.type) {
1296        case OBJ_ENCODING:
1297          V = getEncoding(&(dictP[N].value));
1298          if ( V != SCAN_OK ) return(V);
1299          break;
1300        case OBJ_ARRAY:
1301          V = getArray(&(dictP[N].value));
1302          if ( V != SCAN_OK ) return(V);
1303          break;
1304        case OBJ_INTEGER:
1305          /* next value in integer */
1306          dictP[N].value.data.integer = getInt();
1307          if (rc) return(rc);  /* if next token was not an Int */
1308          break;
1309        case OBJ_REAL:
1310          /* next value must be real or int, store as a real */
1311          scan_token(inputP);
1312          if (tokenType == TOKEN_REAL) {
1313            dictP[N].value.data.real = tokenValue.real;
1314          }
1315          else
1316            if (tokenType == TOKEN_INTEGER) {
1317              dictP[N].value.data.real = tokenValue.integer;
1318            }
1319          else return(SCAN_ERROR);
1320          break;
1321        case OBJ_NAME:
1322          V = getNextValue(TOKEN_LITERAL_NAME);
1323          if ( V != SCAN_OK ) return(V);
1324          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
1325          objFormatName(&(dictP[N].value),tokenLength,tokenStartP);
1326          break;
1327        case OBJ_STRING:
1328          V = getNextValue(TOKEN_STRING);
1329          if ( V != SCAN_OK ) return(V);
1330          if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
1331          objFormatString(&(dictP[N].value),tokenLength,tokenStartP);
1332          break;
1333        case OBJ_BOOLEAN:
1334          scan_token(inputP);
1335          if (tokenType != TOKEN_NAME) {
1336            return(SCAN_ERROR);
1337          }
1338          if (0 == strncmp(tokenStartP,"true",4) ) {
1339            dictP[N].value.data.boolean =TRUE;
1340          }
1341          else
1342            if (0 == strncmp(tokenStartP,"false",5) ) {
1343              dictP[N].value.data.boolean =FALSE;
1344            }
1345            else return(SCAN_ERROR);
1346          break;
1347  
1348        default:
1349          return(SCAN_ERROR);
1350      }
1351    }
1352    /* Name is not in dictionary.  That is ok. */
1353    return(SCAN_OK);
1354  
1355 }
1356 /***================================================================***/
1357  
1358 /*
1359  * -------------------------------------------------------------------
1360  *  Scan the next token and convert it into an object
1361  *  Result is placed on the Operand Stack as next object
1362  * -------------------------------------------------------------------
1363  */
1364 int scan_font(FontP)
1365   psfont *FontP;
1366 {
1367  
1368  
1369   char   filename[128];
1370   char   filetype[3];
1371   FILE   *fileP;
1372   char   *nameP;
1373   int    namelen;
1374   int    V;
1375   int    i;
1376   boolean starthex80;
1377  
1378     starthex80 = FALSE;
1379     filetype[0] = 'r';
1380     filetype[1] = 'b';
1381     filetype[2] = '\0';
1382     /* copy the filename and remove leading or trailing blanks */
1383     /* point to name and search for leading blanks */
1384     nameP= FontP->FontFileName.data.nameP;
1385     namelen  = FontP->FontFileName.len;
1386     while (nameP[0] == ' ') {
1387         nameP++;
1388         namelen--;
1389     }
1390     /* now remove any trailing blanks */
1391     while ((namelen>0) && ( nameP[namelen-1] == ' ')) {
1392       namelen--;
1393     }
1394     strncpy(filename,nameP,namelen);
1395     filename[namelen] = '\0';
1396     /* file name is now constructed */
1397     inputFile.data.fileP = NULL;
1398     filterFile.data.fileP = NULL;
1399  
1400     inputP = &inputFile;
1401     if (fileP = fopen(filename,filetype)) {
1402       /* get the first byte of file */
1403       V = getc(fileP);
1404       /* if file starts with x'80' then skip next 5 bytes */
1405       if ( V == 0X80 ) {
1406         for (i=0;i<5;i++) V = getc(fileP);
1407         starthex80 = TRUE;
1408       }
1409       else ungetc(V,fileP);
1410       objFormatFile(inputP,fileP);
1411     }
1412     else {
1413       return(SCAN_FILE_OPEN_ERROR);
1414     };
1415  
1416   WantFontInfo  = TRUE;
1417   InPrivateDict = FALSE;
1418   TwoSubrs      = FALSE;
1419   rc = BuildFontInfo(FontP);
1420   if (rc != 0) return(rc);
1421  
1422   /* Assume everything will be OK */
1423   rc       = 0;
1424  
1425   /* Loop until complete font is read  */
1426   do {
1427     /* Scan the next token */
1428     scan_token(inputP);
1429  
1430     /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
1431     /* now set */
1432  
1433     switch (tokenType) {
1434       case TOKEN_EOF:
1435       case TOKEN_NONE:
1436       case TOKEN_INVALID:
1437         /* in this case we are done */
1438         if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
1439         rc = SCAN_ERROR;
1440         break;
1441       case TOKEN_LITERAL_NAME:
1442             /* Look up the name */
1443             tokenStartP[tokenLength] = '\0';
1444             if (InPrivateDict ) {
1445               if (0== strncmp(tokenStartP,"Subrs",5) ) {
1446                 rc = BuildSubrs(FontP);
1447                 break;
1448               }
1449               if (0== strncmp(tokenStartP,"CharStrings",11) ) {
1450                 rc = BuildCharStrings(FontP);
1451                 if ( (rc == SCAN_OK) ||(rc == SCAN_END) ) {
1452                   fclose(inputP->data.fileP);
1453                   /* Build the Blues Structure */
1454                   rc = GetType1Blues(FontP);
1455                   /* whatever the return code, return it */
1456                   /* all the work is done. This is the normal exit.*/
1457                   return(rc);
1458                 }
1459                 break;
1460               }
1461               rc = FindDictValue(FontP->Private);
1462               /* we are not going to report errors */
1463               /* Sometimes the font file may test a value such as */
1464               /* testing to see if the font is alreadly loaded with */
1465               /* same UniqueID.  We would faile on /UniqueID get  */
1466               /* because we are expecting a int to follow UniqueID*/
1467               /* If the correct object type does not follow a Name*/
1468               /* then we will skip over it without reporting error*/
1469               rc = SCAN_OK;
1470               break;
1471             }   /* end of reading Private dictionary */
1472             else
1473               if (0== strncmp(tokenStartP,"Private",7) ) {
1474                 InPrivateDict = TRUE;
1475                 rc = BuildPrivate(FontP);
1476                 break;
1477               }
1478               else
1479                 if (WantFontInfo) {
1480                   rc = FindDictValue(FontP->fontInfoP);
1481                   /* we are not going to report errors */
1482                   rc = SCAN_OK;
1483                   break;
1484                 }
1485         break;
1486       case TOKEN_NAME:
1487             if (0 == strncmp(tokenStartP,"eexec",5) ) {
1488                /* if file started with x'80', check next 5 bytes */
1489                if (starthex80) {
1490                  V = getc(fileP);
1491                  if ( V == 0X80 ) {
1492                    for (i=0;i<5;i++) V = getc(fileP);
1493                  }
1494                  else ungetc(V,fileP);
1495                }
1496                filterFile.data.fileP = T1eexec(inputP->data.fileP);
1497                if (filterFile.data.fileP == NULL) {
1498                  fclose(inputFile.data.fileP);
1499                  return(SCAN_FILE_OPEN_ERROR);
1500                }
1501                inputP = &filterFile;
1502  
1503                WantFontInfo = FALSE;
1504             }
1505         break;
1506     }
1507  
1508   }
1509   while (rc ==0);
1510   fclose(inputP->data.fileP);
1511   if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
1512   return(rc);
1513 }
1514