1
/*--------------------------------------------------------------------------
3
----- Author: Adobe Systems Inc., modifications by
4
Rainer Menzner (Rainer.Menzner@web.de)
6
----- Description: This file is part of the t1-library. It is the original
7
parseAFM.h modified at a few points, especially for
8
reading MSDOS-style AFM files..
9
----- Copyright: t1lib is copyrighted (c) Rainer Menzner, 1996-2001.
10
As of version 0.5, t1lib is distributed under the
11
GNU General Public Library Lincense. The
12
conditions can be found in the files LICENSE and
13
LGPL, which should reside in the toplevel
14
directory of the distribution. Please note that
15
there are parts of t1lib that are subject to
17
The parseAFM-package is copyrighted by Adobe Systems
19
The type1 rasterizer is copyrighted by IBM and the
21
----- Warranties: Of course, there's NO WARRANTY OF ANY KIND :-)
22
----- Credits: I want to thank IBM and the X11-consortium for making
23
their rasterizer freely available.
24
Also thanks to Piet Tutelaers for his ps2pk, from
25
which I took the rasterizer sources in a format
27
Thanks to all people who make free software living!
28
--------------------------------------------------------------------------*/
31
* (C) 1988, 1989, 1990 by Adobe Systems Incorporated. All rights reserved.
33
* This file may be freely copied and redistributed as long as:
34
* 1) This entire notice continues to be included in the file,
35
* 2) If the file has been modified in any way, a notice of such
36
* modification is conspicuously indicated.
38
* PostScript, Display PostScript, and Adobe are registered trademarks of
39
* Adobe Systems Incorporated.
41
* ************************************************************************
42
* THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
43
* NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
44
* INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
45
* LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
46
* KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
47
* AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
48
* FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
49
* ************************************************************************
54
* This file is used in conjuction with the parseAFM.h header file.
55
* This file contains several procedures that are used to parse AFM
56
* files. It is intended to work with an application program that needs
57
* font metric information. The program can be used as is by making a
58
* procedure call to "parseFile" (passing in the expected parameters)
59
* and having it fill in a data structure with the data from the
60
* AFM file, or an application developer may wish to customize this
63
* There is also a file, parseAFMclient.c, that is a sample application
64
* showing how to call the "parseFile" procedure and how to use the data
65
* after "parseFile" has returned.
67
* Please read the comments in parseAFM.h and parseAFMclient.c.
70
* original: DSM Thu Oct 20 17:39:59 PDT 1988
71
* modified: DSM Mon Jul 3 14:17:50 PDT 1989
72
* - added 'storageProblem' return code
73
* - fixed bug of not allocating extra byte for string duplication
75
* modified: DSM Tue Apr 3 11:18:34 PDT 1990
76
* - added free(ident) at end of parseFile routine
77
* modified: DSM Tue Jun 19 10:16:29 PDT 1990
78
* - changed (width == 250) to (width = 250) in initializeArray
84
#include <sys/types.h> /* this seems to be necessary on some SCO-systems */
85
#if !defined(_MSC_VER)
86
# include <sys/file.h>
92
#define lineterm EOL /* line terminating character */
93
#define normalEOF 1 /* return code from parsing routines used only */
95
#define Space "space" /* used in string comparison to look for the width */
96
/* of the space character to init the widths array */
97
#define False "false" /* used in string comparison to check the value of */
98
/* boolean keys (e.g. IsFixedPitch) */
100
#define MATCH(A,B) (strncmp((A),(B), MAX_NAME) == 0)
104
/* Note: The functions token and linetoken are extended to be able
105
to parse AFM files with DOS-style line-ends under UNIX. I don't know
106
why AFM files which according to Adobe are explicitly intended to
107
be used under UNIX have MSDOS-style line ends.
109
However, we parse the tokens based on the following atoms. This should
112
#define CR '\r' /* a carriage return */
113
#define LF '\n' /* a linefeed, which is a newline under UNIX */
114
#define CTRL_Z 0x1A /* some AFM files have this characters as an end
115
of file indicator. Who know why :) ? */
118
/*************************** GLOBALS ***********************/
120
static char *ident = NULL; /* storage buffer for keywords */
123
/* "shorts" for fast case statement
124
* The values of each of these enumerated items correspond to an entry in the
125
* table of strings defined below. Therefore, if you add a new string as
126
* new keyword into the keyStrings table, you must also add a corresponding
127
* parseKey AND it MUST be in the same position!
129
* IMPORTANT: since the sorting algorithm is a binary search, the strings of
130
* keywords must be placed in lexicographical order, below. [Therefore, the
131
* enumerated items are not necessarily in lexicographical order, depending
132
* on the name chosen. BUT, they must be placed in the same position as the
133
* corresponding key string.] The NOPE shall remain in the last position,
134
* since it does not correspond to any key string, and it is used in the
135
* "recognize" procedure to calculate how many possible keys there are.
139
ASCENDER, CHARBBOX, CODE, COMPCHAR, CAPHEIGHT, COMMENT,
140
DESCENDER, ENCODINGSCHEME, ENDCHARMETRICS, ENDCOMPOSITES,
141
ENDFONTMETRICS, ENDKERNDATA, ENDKERNPAIRS, ENDTRACKKERN,
142
FAMILYNAME, FONTBBOX, FONTNAME, FULLNAME, ISFIXEDPITCH,
143
ITALICANGLE, KERNPAIR, KERNPAIRXAMT, LIGATURE, CHARNAME,
144
NOTICE, COMPCHARPIECE, STARTCHARMETRICS, STARTCOMPOSITES,
145
STARTFONTMETRICS, STARTKERNDATA, STARTKERNPAIRS,
146
STARTTRACKKERN, TRACKKERN, UNDERLINEPOSITION,
147
UNDERLINETHICKNESS, VERSION, XYWIDTH, XWIDTH, WEIGHT, XHEIGHT,
151
/* keywords for the system:
152
* This a table of all of the current strings that are vaild AFM keys.
153
* Each entry can be referenced by the appropriate parseKey value (an
154
* enumerated data type defined above). If you add a new keyword here,
155
* a corresponding parseKey MUST be added to the enumerated data type
156
* defined above, AND it MUST be added in the same position as the
157
* string is in this table.
159
* IMPORTANT: since the sorting algorithm is a binary search, the keywords
160
* must be placed in lexicographical order. And, NULL should remain at the
164
static char *keyStrings[] = {
165
"Ascender", "B", "C", "CC", "CapHeight", "Comment",
166
"Descender", "EncodingScheme", "EndCharMetrics", "EndComposites",
167
"EndFontMetrics", "EndKernData", "EndKernPairs", "EndTrackKern",
168
"FamilyName", "FontBBox", "FontName", "FullName", "IsFixedPitch",
169
"ItalicAngle", "KP", "KPX", "L", "N",
170
"Notice", "PCC", "StartCharMetrics", "StartComposites",
171
"StartFontMetrics", "StartKernData", "StartKernPairs",
172
"StartTrackKern", "TrackKern", "UnderlinePosition",
173
"UnderlineThickness", "Version", "W", "WX", "Weight", "XHeight",
176
/*************************** PARSING ROUTINES **************/
178
/*************************** token *************************/
180
/* A "AFM File Conventions" tokenizer. That means that it will
181
* return the next token delimited by white space. See also
182
* the `linetoken' routine, which does a similar thing but
183
* reads all tokens until the next end-of-line.
185
static char *token(stream)
190
/* skip over white space, instead of the systems EOL-character we check
191
explicitly for CR and LF as well as for ^Z. */
192
while ((ch = fgetc(stream)) == ' ' || ch == CR || ch == LF || ch == CTRL_Z ||
193
ch == ',' || ch == '\t' || ch == ';');
197
while (ch != EOF && ch != ' ' && ch != CR && ch != LF &&
198
ch != CTRL_Z && ch != '\t' && ch != ':' && ch != ';'){
203
if (ch == EOF && idx < 1) {
204
return ((char *)NULL);
206
if (idx >= 1 && ch != ':' ) {
210
ident[idx++] = ch; /* single-character token */
214
return(ident); /* returns pointer to the token */
219
/*************************** linetoken *************************/
221
/* "linetoken" will get read all tokens until the EOL character from
222
* the given stream. This is used to get any arguments that can be
223
* more than one word (like Comment lines and FullName).
226
static char *linetoken(stream)
231
while ((ch = fgetc(stream)) == ' ' || ch == '\t' );
234
while (ch != EOF && ch != CR && ch != LF && ch != CTRL_Z)
243
return(ident); /* returns pointer to the token */
248
/*************************** recognize *************************/
250
/* This function tries to match a string to a known list of
251
* valid AFM entries (check the keyStrings array above).
252
* "ident" contains everything from white space through the
253
* next space, tab, or ":" character.
255
* The algorithm is a standard Knuth binary search.
258
static PARSEKEY recognize(ident)
259
register char *ident;
261
int lower = 0, upper = (int) NOPE, midpoint=NOPE, cmpvalue;
262
BOOL found = T1LIB_FALSE;
264
while ((upper >= lower) && !found)
266
midpoint = (lower + upper)/2;
267
if (keyStrings[midpoint] == NULL) break;
268
cmpvalue = strncmp(ident, keyStrings[midpoint], MAX_NAME);
269
if (cmpvalue == 0) found = T1LIB_TRUE;
270
else if (cmpvalue < 0) upper = midpoint - 1;
271
else lower = midpoint + 1;
274
if (found) return (PARSEKEY) midpoint;
280
/************************* parseGlobals *****************************/
282
/* This function is called by "parseFile". It will parse the AFM File
283
* up to the "StartCharMetrics" keyword, which essentially marks the
284
* end of the Global Font Information and the beginning of the character
285
* metrics information.
287
* If the caller of "parseFile" specified that it wanted the Global
288
* Font Information (as defined by the "AFM File Specification"
289
* document), then that information will be stored in the returned
292
* Any Global Font Information entries that are not found in a
293
* given file, will have the usual default initialization value
294
* for its type (i.e. entries of type int will be 0, etc).
296
* This function returns an error code specifying whether there was
297
* a premature EOF or a parsing error. This return value is used by
298
* parseFile to determine if there is more file to parse.
301
static BOOL parseGlobals(fp, gfi)
303
register GlobalFontInfo *gfi;
305
BOOL cont = T1LIB_TRUE, save = (gfi != NULL);
307
register char *keyword;
314
/* Have reached an early and unexpected EOF. */
315
/* Set flag and stop parsing */
318
break; /* get out of loop */
321
/* get tokens until the end of the Global Font info section */
322
/* without saving any of the data */
323
switch (recognize(keyword))
325
case STARTCHARMETRICS:
336
/* otherwise parse entire global font info section, */
337
/* saving the data */
338
switch(recognize(keyword))
340
case STARTFONTMETRICS:
342
gfi->afmVersion = (char *) malloc(strlen(keyword) + 1);
343
strcpy(gfi->afmVersion, keyword);
346
keyword = linetoken(fp);
349
keyword = linetoken(fp);
350
gfi->fontName = (char *) malloc(strlen(keyword) + 1);
351
strcpy(gfi->fontName, keyword);
354
keyword = linetoken(fp);
355
gfi->encodingScheme = (char *)
356
malloc(strlen(keyword) + 1);
357
strcpy(gfi->encodingScheme, keyword);
360
keyword = linetoken(fp);
361
gfi->fullName = (char *) malloc(strlen(keyword) + 1);
362
strcpy(gfi->fullName, keyword);
365
keyword = linetoken(fp);
366
gfi->familyName = (char *) malloc(strlen(keyword) + 1);
367
strcpy(gfi->familyName, keyword);
370
keyword = linetoken(fp);
371
gfi->weight = (char *) malloc(strlen(keyword) + 1);
372
strcpy(gfi->weight, keyword);
376
gfi->italicAngle = atof(keyword);
377
if (errno == ERANGE) error = parseError;
381
if (MATCH(keyword, False))
382
gfi->isFixedPitch = 0;
384
gfi->isFixedPitch = 1;
386
case UNDERLINEPOSITION:
388
gfi->underlinePosition = atoi(keyword);
390
case UNDERLINETHICKNESS:
392
gfi->underlineThickness = atoi(keyword);
395
keyword = linetoken(fp);
396
gfi->version = (char *) malloc(strlen(keyword) + 1);
397
strcpy(gfi->version, keyword);
400
keyword = linetoken(fp);
401
gfi->notice = (char *) malloc(strlen(keyword) + 1);
402
strcpy(gfi->notice, keyword);
406
gfi->fontBBox.llx = atoi(keyword);
408
gfi->fontBBox.lly = atoi(keyword);
410
gfi->fontBBox.urx = atoi(keyword);
412
gfi->fontBBox.ury = atoi(keyword);
416
gfi->capHeight = atoi(keyword);
420
gfi->xHeight = atoi(keyword);
424
gfi->descender = atoi(keyword);
428
gfi->ascender = atoi(keyword);
430
case STARTCHARMETRICS:
450
/************************* initializeArray ************************/
452
/* Unmapped character codes are (at Adobe Systems) assigned the
453
* width of the space character (if one exists) else they get the
454
* value of 250 ems. This function initializes all entries in the
455
* char widths array to have this value. Then any mapped character
456
* codes will be replaced with the width of the appropriate character
457
* when parsing the character metric section.
459
* This function parses the Character Metrics Section looking
460
* for a space character (by comparing character names). If found,
461
* the width of the space character will be used to initialize the
462
* values in the array of character widths.
464
* Before returning, the position of the read/write pointer of the
465
* file is reset to be where it was upon entering this function.
468
/* We comment out the following function since it is not needed in t1lib
469
and we don't want compiler warnings */
471
static int initializeArray(fp, cwi)
475
BOOL cont = T1LIB_TRUE, found = T1LIB_FALSE;
476
long opos = ftell(fp);
477
int code = 0, width = 0, i = 0, error = 0;
478
register char *keyword;
488
switch(recognize(keyword))
491
keyword = linetoken(fp);
494
code = atoi(token(fp));
497
width = atoi(token(fp));
501
if (MATCH(keyword, Space))
524
for (i = 0; i < 256; ++i)
534
/************************* parseCharWidths **************************/
536
/* This function is called by "parseFile". It will parse the AFM File
537
* up to the "EndCharMetrics" keyword. It will save the character
538
* width info (as opposed to all of the character metric information)
539
* if requested by the caller of parseFile. Otherwise, it will just
540
* parse through the section without saving any information.
542
* If data is to be saved, parseCharWidths is passed in a pointer
543
* to an array of widths that has already been initialized by the
544
* standard value for unmapped character codes. This function parses
545
* the Character Metrics section only storing the width information
546
* for the encoded characters into the array using the character code
547
* as the index into that array.
549
* This function returns an error code specifying whether there was
550
* a premature EOF or a parsing error. This return value is used by
551
* parseFile to determine if there is more file to parse.
554
static int parseCharWidths(fp, cwi)
558
BOOL cont = T1LIB_TRUE, save = (cwi != NULL);
559
int pos = 0, error = ok;
560
register char *keyword;
565
/* Have reached an early and unexpected EOF. */
566
/* Set flag and stop parsing */
570
break; /* get out of loop */
573
/* get tokens until the end of the Char Metrics section without */
574
/* saving any of the data*/
575
switch (recognize(keyword))
588
/* otherwise parse entire char metrics section, saving */
589
/* only the char x-width info */
590
switch(recognize(keyword))
593
keyword = linetoken(fp);
600
/* PROBLEM: Should be no Y-WIDTH when doing "quick & dirty" */
601
keyword = token(fp); keyword = token(fp); /* eat values */
606
if (pos >= 0) /* ignore unmapped chars */
607
cwi[pos] = atoi(keyword);
616
case CHARNAME: /* eat values (so doesn't cause parseError) */
620
keyword = token(fp); keyword = token(fp);
621
keyword = token(fp); keyword = token(fp);
624
keyword = token(fp); keyword = token(fp);
635
} /* parseCharWidths */
638
/************************* parseCharMetrics ************************/
640
/* This function is called by parseFile if the caller of parseFile
641
* requested that all character metric information be saved
642
* (as opposed to only the character width information).
644
* parseCharMetrics is passed in a pointer to an array of records
645
* to hold information on a per character basis. This function
646
* parses the Character Metrics section storing all character
647
* metric information for the ALL characters (mapped and unmapped)
650
* This function returns an error code specifying whether there was
651
* a premature EOF or a parsing error. This return value is used by
652
* parseFile to determine if there is more file to parse.
655
static int parseCharMetrics(fp, fi)
657
register FontInfo *fi;
659
BOOL cont = T1LIB_TRUE, firstTime = T1LIB_TRUE;
660
int error = ok, count = 0;
661
register CharMetricInfo *temp = fi->cmi;
662
register char *keyword;
670
break; /* get out of loop */
672
switch(recognize(keyword))
675
keyword = linetoken(fp);
678
if (count < fi->numOfChars)
680
if (firstTime) firstTime = T1LIB_FALSE;
682
temp->code = atoi(token(fp));
692
temp->wx = atoi(token(fp));
693
temp->wy = atoi(token(fp));
696
temp->wx = atoi(token(fp));
700
temp->name = (char *) malloc(strlen(keyword) + 1);
701
strcpy(temp->name, keyword);
704
temp->charBBox.llx = atoi(token(fp));
705
temp->charBBox.lly = atoi(token(fp));
706
temp->charBBox.urx = atoi(token(fp));
707
temp->charBBox.ury = atoi(token(fp));
710
Ligature **tail = &(temp->ligs);
711
Ligature *node = *tail;
715
while (node->next != NULL)
717
tail = &(node->next);
720
*tail = (Ligature *) calloc(1, sizeof(Ligature));
722
(*tail)->succ = (char *) malloc(strlen(keyword) + 1);
723
strcpy((*tail)->succ, keyword);
725
(*tail)->lig = (char *) malloc(strlen(keyword) + 1);
726
strcpy((*tail)->lig, keyword);
742
if ((error == ok) && (count != fi->numOfChars))
747
} /* parseCharMetrics */
751
/************************* parseTrackKernData ***********************/
753
/* This function is called by "parseFile". It will parse the AFM File
754
* up to the "EndTrackKern" or "EndKernData" keywords. It will save the
755
* track kerning data if requested by the caller of parseFile.
757
* parseTrackKernData is passed in a pointer to the FontInfo record.
758
* If data is to be saved, the FontInfo record will already contain
759
* a valid pointer to storage for the track kerning data.
761
* This function returns an error code specifying whether there was
762
* a premature EOF or a parsing error. This return value is used by
763
* parseFile to determine if there is more file to parse.
766
static int parseTrackKernData(fp, fi)
768
register FontInfo *fi;
770
BOOL cont = T1LIB_TRUE, save = (fi->tkd != NULL);
771
int pos = 0, error = ok, tcount = 0;
772
register char *keyword;
781
break; /* get out of loop */
784
/* get tokens until the end of the Track Kerning Data */
785
/* section without saving any of the data */
786
switch(recognize(keyword))
800
/* otherwise parse entire Track Kerning Data section, */
801
/* saving the data */
802
switch(recognize(keyword))
805
keyword = linetoken(fp);
808
if (tcount < fi->numOfTracks)
811
fi->tkd[pos].degree = atoi(keyword);
813
fi->tkd[pos].minPtSize = atof(keyword);
814
if (errno == ERANGE) error = parseError;
816
fi->tkd[pos].minKernAmt = atof(keyword);
817
if (errno == ERANGE) error = parseError;
819
fi->tkd[pos].maxPtSize = atof(keyword);
820
if (errno == ERANGE) error = parseError;
822
fi->tkd[pos++].maxKernAmt = atof(keyword);
823
if (errno == ERANGE) error = parseError;
847
if (error == ok && tcount != fi->numOfTracks)
852
} /* parseTrackKernData */
855
/************************* parsePairKernData ************************/
857
/* This function is called by "parseFile". It will parse the AFM File
858
* up to the "EndKernPairs" or "EndKernData" keywords. It will save
859
* the pair kerning data if requested by the caller of parseFile.
861
* parsePairKernData is passed in a pointer to the FontInfo record.
862
* If data is to be saved, the FontInfo record will already contain
863
* a valid pointer to storage for the pair kerning data.
865
* This function returns an error code specifying whether there was
866
* a premature EOF or a parsing error. This return value is used by
867
* parseFile to determine if there is more file to parse.
870
static int parsePairKernData(fp, fi)
872
register FontInfo *fi;
874
BOOL cont = T1LIB_TRUE, save = (fi->pkd != NULL);
875
int pos = 0, error = ok, pcount = 0;
876
register char *keyword;
885
break; /* get out of loop */
888
/* get tokens until the end of the Pair Kerning Data */
889
/* section without saving any of the data */
890
switch(recognize(keyword))
904
/* otherwise parse entire Pair Kerning Data section, */
905
/* saving the data */
906
switch(recognize(keyword))
909
keyword = linetoken(fp);
912
if (pcount < fi->numOfPairs)
915
fi->pkd[pos].name1 = (char *)
916
malloc(strlen(keyword) + 1);
917
strcpy(fi->pkd[pos].name1, keyword);
919
fi->pkd[pos].name2 = (char *)
920
malloc(strlen(keyword) + 1);
921
strcpy(fi->pkd[pos].name2, keyword);
923
fi->pkd[pos].xamt = atoi(keyword);
925
fi->pkd[pos++].yamt = atoi(keyword);
935
if (pcount < fi->numOfPairs)
938
fi->pkd[pos].name1 = (char *)
939
malloc(strlen(keyword) + 1);
940
strcpy(fi->pkd[pos].name1, keyword);
942
fi->pkd[pos].name2 = (char *)
943
malloc(strlen(keyword) + 1);
944
strcpy(fi->pkd[pos].name2, keyword);
946
fi->pkd[pos++].xamt = atoi(keyword);
970
if (error == ok && pcount != fi->numOfPairs)
975
} /* parsePairKernData */
978
/************************* parseCompCharData **************************/
980
/* This function is called by "parseFile". It will parse the AFM File
981
* up to the "EndComposites" keyword. It will save the composite
982
* character data if requested by the caller of parseFile.
984
* parseCompCharData is passed in a pointer to the FontInfo record, and
985
* a boolean representing if the data should be saved.
987
* This function will create the appropriate amount of storage for
988
* the composite character data and store a pointer to the storage
989
* in the FontInfo record.
991
* This function returns an error code specifying whether there was
992
* a premature EOF or a parsing error. This return value is used by
993
* parseFile to determine if there is more file to parse.
996
static int parseCompCharData(fp, fi)
998
register FontInfo *fi;
1000
BOOL cont = T1LIB_TRUE, firstTime = T1LIB_TRUE, save = (fi->ccd != NULL);
1001
int pos = 0, j = 0, error = ok, ccount = 0, pcount = 0;
1002
register char *keyword;
1006
keyword = token(fp);
1007
if (keyword == NULL)
1008
/* Have reached an early and unexpected EOF. */
1009
/* Set flag and stop parsing */
1012
break; /* get out of loop */
1014
if (ccount > fi->numOfComps)
1017
break; /* get out of loop */
1020
/* get tokens until the end of the Composite Character info */
1021
/* section without saving any of the data */
1022
switch(recognize(keyword))
1027
case ENDFONTMETRICS:
1035
/* otherwise parse entire Composite Character info section, */
1036
/* saving the data */
1037
switch(recognize(keyword))
1040
keyword = linetoken(fp);
1043
if (ccount < fi->numOfComps)
1045
keyword = token(fp);
1046
if (pcount != fi->ccd[pos].numOfPieces)
1049
if (firstTime) firstTime = T1LIB_FALSE;
1051
fi->ccd[pos].ccName = (char *)
1052
malloc(strlen(keyword) + 1);
1053
strcpy(fi->ccd[pos].ccName, keyword);
1054
keyword = token(fp);
1055
fi->ccd[pos].numOfPieces = atoi(keyword);
1056
fi->ccd[pos].pieces = (Pcc *)
1057
calloc(fi->ccd[pos].numOfPieces, sizeof(Pcc));
1068
if (pcount < fi->ccd[pos].numOfPieces)
1070
keyword = token(fp);
1071
fi->ccd[pos].pieces[j].pccName = (char *)
1072
malloc(strlen(keyword) + 1);
1073
strcpy(fi->ccd[pos].pieces[j].pccName, keyword);
1074
keyword = token(fp);
1075
fi->ccd[pos].pieces[j].deltax = atoi(keyword);
1076
keyword = token(fp);
1077
fi->ccd[pos].pieces[j++].deltay = atoi(keyword);
1086
case ENDFONTMETRICS:
1097
if (error == ok && ccount != fi->numOfComps)
1102
} /* parseCompCharData */
1107
/*************************** 'PUBLIC' FUNCTION ********************/
1110
/*************************** parseFile *****************************/
1112
/* parseFile is the only 'public' procedure available. It is called
1113
* from an application wishing to get information from an AFM file.
1114
* The caller of this function is responsible for locating and opening
1115
* an AFM file and handling all errors associated with that task.
1117
* parseFile expects 3 parameters: a vaild file pointer, a pointer
1118
* to a (FontInfo *) variable (for which storage will be allocated and
1119
* the data requested filled in), and a mask specifying which
1120
* data from the AFM File should be saved in the FontInfo structure.
1122
* The file will be parsed and the requested data will be stored in
1123
* a record of type FontInfo (refer to ParseAFM.h).
1125
* parseFile returns an error code as defined in parseAFM.h.
1127
* The position of the read/write pointer associated with the file
1128
* pointer upon return of this function is undefined.
1131
/* Note: function renamed to T1lib_parseFile in order to avoid name clushes
1132
with other libraries that also use the Adobe parseAFM-package (RMz) */
1133
int T1lib_parseFile (fp, fi, flags)
1139
int code = ok; /* return code from each of the parsing routines */
1140
int error = ok; /* used as the return code from this function */
1142
register char *keyword; /* used to store a token */
1145
/* storage data for the global variable ident */
1146
ident = (char *) calloc(MAX_NAME, sizeof(char));
1147
if (ident == NULL) {error = storageProblem; return(error);}
1149
(*fi) = (FontInfo *) calloc(1, sizeof(FontInfo));
1150
if ((*fi) == NULL) {error = storageProblem; return(error);}
1154
(*fi)->gfi = (GlobalFontInfo *) calloc(1, sizeof(GlobalFontInfo));
1155
if ((*fi)->gfi == NULL) {error = storageProblem; return(error);}
1158
/* The AFM File begins with Global Font Information. This section */
1159
/* will be parsed whether or not information should be saved. */
1160
code = parseGlobals(fp, (*fi)->gfi);
1162
if (code < 0) error = code;
1164
/* The Global Font Information is followed by the Character Metrics */
1165
/* section. Which procedure is used to parse this section depends on */
1166
/* how much information should be saved. If all of the metrics info */
1167
/* is wanted, parseCharMetrics is called. If only the character widths */
1168
/* is wanted, parseCharWidths is called. parseCharWidths will also */
1169
/* be called in the case that no character data is to be saved, just */
1170
/* to parse through the section. */
1172
if ((code != normalEOF) && (code != earlyEOF))
1174
(*fi)->numOfChars = atoi(token(fp));
1175
if (flags & (P_M ^ P_W))
1177
(*fi)->cmi = (CharMetricInfo *)
1178
calloc((*fi)->numOfChars, sizeof(CharMetricInfo));
1179
if ((*fi)->cmi == NULL) {error = storageProblem; return(error);}
1180
code = parseCharMetrics(fp, *fi);
1186
(*fi)->cwi = (int *) calloc(256, sizeof(int));
1187
if ((*fi)->cwi == NULL)
1189
error = storageProblem;
1193
/* parse section regardless */
1194
code = parseCharWidths(fp, (*fi)->cwi);
1198
if ((error != earlyEOF) && (code < 0)) error = code;
1200
/* The remaining sections of the AFM are optional. This code will */
1201
/* look at the next keyword in the file to determine what section */
1202
/* is next, and then allocate the appropriate amount of storage */
1203
/* for the data (if the data is to be saved) and call the */
1204
/* appropriate parsing routine to parse the section. */
1206
while ((code != normalEOF) && (code != earlyEOF)) {
1207
keyword = token(fp);
1208
if (keyword == NULL)
1209
/* Have reached an early and unexpected EOF. */
1210
/* Set flag and stop parsing */
1213
break; /* get out of loop */
1215
switch(recognize(keyword))
1217
/* this case has been added for t1lib because otherwise comment line
1218
between (i.e., outside) the main sections would lead to parse
1219
errors. The Adobe spec does not seem to forbid comments at
1220
such locations (2001-05-14, RMz) */
1222
keyword = linetoken(fp);
1228
case STARTTRACKKERN:
1229
keyword = token(fp);
1232
(*fi)->numOfTracks = atoi(keyword);
1233
(*fi)->tkd = (TrackKernData *)
1234
calloc((*fi)->numOfTracks, sizeof(TrackKernData));
1235
if ((*fi)->tkd == NULL)
1237
error = storageProblem;
1241
code = parseTrackKernData(fp, *fi);
1243
case STARTKERNPAIRS:
1244
keyword = token(fp);
1247
(*fi)->numOfPairs = atoi(keyword);
1248
(*fi)->pkd = (PairKernData *)
1249
calloc((*fi)->numOfPairs, sizeof(PairKernData));
1250
if ((*fi)->pkd == NULL)
1252
error = storageProblem;
1256
code = parsePairKernData(fp, *fi);
1258
case STARTCOMPOSITES:
1259
keyword = token(fp);
1262
(*fi)->numOfComps = atoi(keyword);
1263
(*fi)->ccd = (CompCharData *)
1264
calloc((*fi)->numOfComps, sizeof(CompCharData));
1265
if ((*fi)->ccd == NULL)
1267
error = storageProblem;
1271
code = parseCompCharData(fp, *fi);
1273
case ENDFONTMETRICS:
1282
if ((error != earlyEOF) && (code < 0)) error = code;
1286
if ((error != earlyEOF) && (code < 0)) error = code;
1288
if (ident != NULL) { free(ident); ident = NULL; }