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
MakeEncodingArrayP(encodingTable)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
Init_BuiltInEncoding()436 boolean Init_BuiltInEncoding()
437 {
438 StdEncArrayP = MakeEncodingArrayP(StdEnc);
439 ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
440 return (StdEncArrayP && ISOLatin1EncArrayP);
441 }
442
443 /********************************************************************/
444 /***================================================================***/
getNextValue(valueType)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 /***================================================================***/
getInt()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 */
getEncoding(arrayP)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 /***================================================================***/
getArray(arrayP)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 /***================================================================***/
getName(nameP)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 /***================================================================***/
getNbytes(N)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 /***================================================================***/
getLiteralName(nameObjP)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
BuildSubrs(FontP)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
BuildCharStrings(FontP)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 /***================================================================***/
BuildFontInfo(fontP)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 /***================================================================***/
BuildPrivate(fontP)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 /**********************************************************************/
GetType1Blues(fontP)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 /**********************************************************************/
GetType1CharString(fontP,code)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
FindDictValue(dictP)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 */
scan_font(FontP)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
1515