1 /* $TOG: scanfont.c /main/11 1997/06/09 13:27:16 barstow $ */
2 /* Copyright International Business Machines,Corp. 1991
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.
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
30 /* Author: Katherine A. Hitchcock IBM Almaden Research Laboratory */
42 static boolean InPrivateDict;
43 static boolean WantFontInfo;
44 static boolean TwoSubrs;
45 static psobj inputFile;
46 static psobj filterFile;
50 /**********************************************************************/
51 /* Init_BuiltInEncoding() */
53 /* Initializes the StandardEncoding and ISOLatin1Encoding vector. */
55 /**********************************************************************/
56 typedef struct /* Builtin Standard Encoding */
62 static EncodingTable StdEnc[] = {
122 0133 , "bracketleft",
124 0135 , "bracketright",
125 0136 , "asciicircum",
166 0251 , "quotesingle",
167 0252 , "quotedblleft",
168 0253 , "guillemotleft",
169 0254 , "guilsinglleft",
170 0255 , "guilsinglright",
176 0264 , "periodcentered",
179 0270 , "quotesinglbase",
180 0271 , "quotedblbase",
181 0272 , "quotedblright",
182 0273 , "guillemotright",
184 0275 , "perthousand",
185 0277 , "questiondown",
196 0315 , "hungarumlaut",
201 0343 , "ordfeminine",
205 0353 , "ordmasculine",
215 static EncodingTable ISO8859Enc[] = {
321 171, "guillemotleft",
329 179, "threesuperior",
333 183, "periodcentered",
337 187, "guillemotright",
340 190, "threequarters",
409 static psobj *StdEncArrayP = NULL;
410 psobj *ISOLatin1EncArrayP = NULL;
412 static psobj *MakeEncodingArrayP(encodingTable)
413 EncodingTable *encodingTable;
416 psobj *encodingArrayP;
418 encodingArrayP = (psobj *)vm_alloc(256*(sizeof(psobj)));
422 /* initialize everything to .notdef */
424 objFormatName(&(encodingArrayP[i]),7, ".notdef");
426 for (i=0; encodingTable[i].name; i++)
428 objFormatName(&(encodingArrayP[encodingTable[i].index]),
429 strlen(encodingTable[i].name),
430 encodingTable[i].name);
433 return(encodingArrayP);
436 boolean Init_BuiltInEncoding()
438 StdEncArrayP = MakeEncodingArrayP(StdEnc);
439 ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
440 return (StdEncArrayP && ISOLatin1EncArrayP);
443 /********************************************************************/
444 /***================================================================***/
445 static int getNextValue(valueType)
449 if (tokenType != valueType) {
455 /***================================================================***/
456 /* This routine will set the global rc if there is an error */
457 /***================================================================***/
461 if (tokenType != TOKEN_INTEGER) {
466 return( tokenValue.integer);
470 /***================================================================***/
472 * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
473 * for parsing Encoding.
475 static int getEncoding(arrayP)
480 if ((tokenType == TOKEN_NAME)
482 (((tokenLength==16) && (!strncmp(tokenStartP,"StandardEncoding",16))) ||
483 (((tokenLength==17) && (!strncmp(tokenStartP,"ISOLatin1Encoding",17))))))
485 /* Adobe Standard Encoding */
487 if (tokenLength == 16)
488 arrayP->data.valueP = (char *) StdEncArrayP;
490 arrayP->data.valueP = (char *) ISOLatin1EncArrayP;
495 else if ( (tokenType == TOKEN_LEFT_BRACE) ||
496 (tokenType == TOKEN_LEFT_BRACKET) )
498 /* Array of literal names */
503 objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
504 if (!(objP)) return(SCAN_OUT_OF_MEMORY);
506 arrayP->data.valueP = (char *) objP;
509 for (i=0; i<256; i++, objP++)
513 if (tokenType != TOKEN_LITERAL_NAME)
516 if (!(vm_alloc(tokenLength)) ) return(SCAN_OUT_OF_MEMORY);
517 objFormatName(objP,tokenLength,tokenStartP);
521 if ( (tokenType == TOKEN_RIGHT_BRACE) ||
522 (tokenType == TOKEN_RIGHT_BRACKET) )
527 /* Must be sequences of ``dup <index> <charactername> put" */
532 objP = (psobj *)vm_alloc(256*(sizeof(psobj)));
533 if (!(objP)) return(SCAN_OUT_OF_MEMORY);
535 arrayP->data.valueP = (char *) objP;
538 for (i=0; i<256; i++)
539 objFormatName(objP + i, 7, ".notdef");
548 if (tokenLength == 3)
550 if (strncmp(tokenStartP,"dup",3) == 0)
554 if (tokenType != TOKEN_INTEGER ||
555 tokenValue.integer < 0 ||
556 tokenValue.integer > 255)
558 i = tokenValue.integer;
560 /* get <characer_name> */
562 if (tokenType != TOKEN_LITERAL_NAME)
565 if (!(vm_alloc(tokenLength)) )
566 return(SCAN_OUT_OF_MEMORY);
567 objFormatName(objP + i,tokenLength,tokenStartP);
571 if (tokenType != TOKEN_NAME)
574 else if (strncmp(tokenStartP,"def",3) == 0)
588 /***================================================================***/
589 static int getArray(arrayP)
592 int N; /* count the items in the array */
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.
601 strncpy (tmp, tokenStartP, sizeof (tmp));
602 tmp [sizeof (tmp) - 1] = '\0';
608 case TOKEN_LEFT_BRACE:
609 case TOKEN_LEFT_BRACKET:
612 case TOKEN_LITERAL_NAME:
613 tokenStartP[tokenLength] = '\0';
614 if (strcmp (tokenStartP, tmp) == 0)
616 /* Ok, We see /foo/foo. Let's restart. */
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 */
629 if ( (tokenType == TOKEN_RIGHT_BRACE) ||
630 (tokenType == TOKEN_RIGHT_BRACKET) ) {
631 /* save then number of items in the array */
635 /* allocate the space for the object */
636 objP = (psobj *)vm_alloc(sizeof(psobj));
637 if (!(objP)) return(SCAN_OUT_OF_MEMORY);
639 /* array is an array of numbers, (real or integer) */
640 if (tokenType == TOKEN_REAL) {
641 objFormatReal(objP, tokenValue.real);
644 if (tokenType == TOKEN_INTEGER) {
645 objFormatInteger(objP, tokenValue.integer);
647 else return(SCAN_ERROR);
652 /***================================================================***/
653 static int getName(nameP)
658 if (tokenType <= TOKEN_NONE) {
659 if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
662 } while ((tokenType != TOKEN_NAME) ||
663 (0 != strncmp(tokenStartP,nameP,strlen(nameP))) );
667 /***================================================================***/
668 static int getNbytes(N)
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);
679 I = fread(tokenStartP,1,N,inputP->data.fileP);
680 if ( I != N ) return(SCAN_FILE_EOF);
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)
696 if (tokenType <= TOKEN_NONE) {
697 if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
700 if (tokenType == TOKEN_NAME) {
701 if (0 == strncmp(tokenStartP,"end",3) ) {
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;
714 /***================================================================***/
718 /***================================================================***/
720 static int BuildSubrs(FontP)
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 */
729 /* next token should be a positive int */
730 /* note: rc is set by getInt. */
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) {
738 /* process all the Subrs, but do not update anything */
739 /* can not just skip them because of the binary data */
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);
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 */
773 if ( (I < 0) || (J < 0 ) ) return (SCAN_ERROR);
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);
780 arrayP[I].data.valueP = tokenStartP;
781 if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
788 /***================================================================***/
789 /***================================================================***/
791 * BuildCharStrings routine
793 /***================================================================***/
795 static int BuildCharStrings(FontP)
798 int N; /* number of values in CharStrings */
799 int i; /* loop thru Subrs */
800 int J; /* length of Subrs entry */
803 /* next token should be a positive int */
806 /* check if file had TwoSubrs, hi resolution stuff is in file*/
810 if (tokenType <= TOKEN_NONE) {
811 if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
814 } while (tokenType != TOKEN_INTEGER);
815 N = tokenValue.integer;
817 else return(rc); /* if next token was not an Int */
819 if (N<=0) return(SCAN_ERROR);
820 /* save number of entries in the dictionary */
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 */
828 /* look for next literal name */
829 rc = getLiteralName(&(dictP[i].key));
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);
841 dictP[i].value.data.valueP = tokenStartP;
842 if ( !(vm_alloc(J)) ) return(SCAN_OUT_OF_MEMORY);
849 /***================================================================***/
850 /***================================================================***/
852 * BuildFontInfo Dictionary
854 /***================================================================***/
855 static int BuildFontInfo(fontP)
860 /* allocate the private dictionary */
861 dictP = (psdict *)vm_alloc(20*sizeof(psdict));
862 if (!(dictP)) return(SCAN_OUT_OF_MEMORY);
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);
902 /***================================================================***/
904 * BuildPrivate Dictionary
906 /***================================================================***/
907 static int BuildPrivate(fontP)
912 /* allocate the private dictionary */
913 Private = (psdict *)vm_alloc(20*sizeof(psdict));
915 if (!(Private)) return(SCAN_OUT_OF_MEMORY);
917 fontP->Private = Private;
918 fontP->Private[0].key.len = 16; /* number of actual entries */
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);
955 /***================================================================***/
956 /**********************************************************************/
957 /* GetType1Blues(fontP) */
959 /* Routine to support font-level hints. */
961 /* Gets all the Blues information from the Private dictionary */
965 /**********************************************************************/
966 static int GetType1Blues(fontP)
969 psdict *PrivateDictP; /* the Private dict relating to hints */
970 struct blues_struct *blues; /* ptr for the blues struct we will allocate */
976 /* get the Private dictionary pointer */
977 PrivateDictP = fontP->Private;
979 /* allocate the memory for the blues structure */
980 blues = (struct blues_struct *) vm_alloc(sizeof(struct blues_struct));
982 if (!blues) return(SCAN_OUT_OF_MEMORY);
984 /* Make fontP's blues ptr point to this newly allocated structure. */
985 fontP->BluesP = blues;
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;
993 /* get the number of values in the array */
994 if (HintEntryP->len > NUMBLUEVALUES) {
995 blues->numBlueValues = NUMBLUEVALUES;
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;
1006 blues->BlueValues[i] = 0;
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;
1016 /* get the number of values in the array */
1017 if (HintEntryP->len > NUMOTHERBLUES) {
1018 blues->numOtherBlues = NUMOTHERBLUES;
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;
1029 blues->OtherBlues[i] = 0;
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;
1039 /* get the number of values in the array */
1040 if (HintEntryP->len > NUMFAMILYBLUES) {
1041 blues->numFamilyBlues = NUMFAMILYBLUES;
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;
1052 blues->FamilyBlues[i] = 0;
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;
1062 /* get the number of values in the array */
1063 if (HintEntryP->len > NUMFAMILYOTHERBLUES) {
1064 blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
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;
1075 blues->FamilyOtherBlues[i] = 0;
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;
1085 /* get the number of values in the array */
1086 if (HintEntryP->len > NUMSTEMSNAPH) {
1087 blues->numStemSnapH = NUMSTEMSNAPH;
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;
1098 blues->StemSnapH[i] = 0;
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;
1108 /* get the number of values in the array */
1109 if (HintEntryP->len > NUMSTEMSNAPV) {
1110 blues->numStemSnapV = NUMSTEMSNAPV;
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;
1121 blues->StemSnapV[i] = 0;
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 */
1132 if (HintEntryP->len > NUMSTDVW) {
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;
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 */
1149 if (HintEntryP->len > NUMSTDHW) {
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;
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;
1168 blues->BlueScale = DEFAULTBLUESCALE;
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;
1177 blues->BlueShift = DEFAULTBLUESHIFT;
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;
1186 blues->BlueFuzz = DEFAULTBLUEFUZZ;
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;
1193 blues->ForceBold = DEFAULTFORCEBOLD;
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;
1200 blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
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;
1207 blues->RndStemUp = DEFAULTRNDSTEMUP;
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;
1214 blues->lenIV = DEFAULTLENIV;
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;
1223 blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
1226 /**********************************************************************/
1227 /* GetType1CharString(fontP,code) */
1229 /* Look up code in the standard encoding vector and return */
1230 /* the charstring associated with the character name. */
1232 /* fontP is the psfont structure. */
1234 /* Returns a psobj (string) */
1235 /**********************************************************************/
1236 psobj *GetType1CharString(fontP, code)
1240 int N; /* the 'Nth' entry in the CharStrings */
1241 psobj *charnameP; /* points to psobj that is name of character*/
1243 psdict *CharStringsDictP; /* dictionary with char strings */
1244 psobj *theStringP; /* the definition for the code */
1248 if (StdEncArrayP == NULL) {
1251 /* use the code to index into the standard encoding vector */
1252 charnameP = &(StdEncArrayP[code]);
1254 /* test if the encoding array points to a name */
1255 if (!(objPIsName(charnameP)) ) {
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;
1263 /* search the chars string for this charname as key */
1264 N = SearchDictName(CharStringsDictP,charnameP);
1268 /* OK, the nth item is the psobj that is the string for this char */
1269 theStringP = &(CharStringsDictP[N].value);
1274 /***================================================================***/
1278 /***================================================================***/
1280 static int FindDictValue(dictP)
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);
1295 switch (dictP[N].value.type) {
1297 V = getEncoding(&(dictP[N].value));
1298 if ( V != SCAN_OK ) return(V);
1301 V = getArray(&(dictP[N].value));
1302 if ( V != SCAN_OK ) return(V);
1305 /* next value in integer */
1306 dictP[N].value.data.integer = getInt();
1307 if (rc) return(rc); /* if next token was not an Int */
1310 /* next value must be real or int, store as a real */
1312 if (tokenType == TOKEN_REAL) {
1313 dictP[N].value.data.real = tokenValue.real;
1316 if (tokenType == TOKEN_INTEGER) {
1317 dictP[N].value.data.real = tokenValue.integer;
1319 else return(SCAN_ERROR);
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);
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);
1335 if (tokenType != TOKEN_NAME) {
1338 if (0 == strncmp(tokenStartP,"true",4) ) {
1339 dictP[N].value.data.boolean =TRUE;
1342 if (0 == strncmp(tokenStartP,"false",5) ) {
1343 dictP[N].value.data.boolean =FALSE;
1345 else return(SCAN_ERROR);
1352 /* Name is not in dictionary. That is ok. */
1356 /***================================================================***/
1359 * -------------------------------------------------------------------
1360 * Scan the next token and convert it into an object
1361 * Result is placed on the Operand Stack as next object
1362 * -------------------------------------------------------------------
1364 int scan_font(FontP)
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] == ' ') {
1390 /* now remove any trailing blanks */
1391 while ((namelen>0) && ( nameP[namelen-1] == ' ')) {
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;
1400 inputP = &inputFile;
1401 if (fileP = fopen(filename,filetype)) {
1402 /* get the first byte of file */
1404 /* if file starts with x'80' then skip next 5 bytes */
1406 for (i=0;i<5;i++) V = getc(fileP);
1409 else ungetc(V,fileP);
1410 objFormatFile(inputP,fileP);
1413 return(SCAN_FILE_OPEN_ERROR);
1416 WantFontInfo = TRUE;
1417 InPrivateDict = FALSE;
1419 rc = BuildFontInfo(FontP);
1420 if (rc != 0) return(rc);
1422 /* Assume everything will be OK */
1425 /* Loop until complete font is read */
1427 /* Scan the next token */
1430 /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
1433 switch (tokenType) {
1437 /* in this case we are done */
1438 if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);
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);
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.*/
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*/
1471 } /* end of reading Private dictionary */
1473 if (0== strncmp(tokenStartP,"Private",7) ) {
1474 InPrivateDict = TRUE;
1475 rc = BuildPrivate(FontP);
1480 rc = FindDictValue(FontP->fontInfoP);
1481 /* we are not going to report errors */
1487 if (0 == strncmp(tokenStartP,"eexec",5) ) {
1488 /* if file started with x'80', check next 5 bytes */
1492 for (i=0;i<5;i++) V = getc(fileP);
1494 else ungetc(V,fileP);
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);
1501 inputP = &filterFile;
1503 WantFontInfo = FALSE;
1510 fclose(inputP->data.fileP);
1511 if (tokenTooLong) return(SCAN_OUT_OF_MEMORY);