xref: /trunk/main/vcl/unx/generic/fontmanager/parseAFM.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1cdf0e10cSrcweir /*
2cdf0e10cSrcweir  * (C) 1988, 1989, 1990 by Adobe Systems Incorporated. All rights reserved.
3cdf0e10cSrcweir  *
4cdf0e10cSrcweir  * This file may be freely copied and redistributed as long as:
5cdf0e10cSrcweir  *   1) This entire notice continues to be included in the file,
6cdf0e10cSrcweir  *   2) If the file has been modified in any way, a notice of such
7cdf0e10cSrcweir  *      modification is conspicuously indicated.
8cdf0e10cSrcweir  *
9cdf0e10cSrcweir  * PostScript, Display PostScript, and Adobe are registered trademarks of
10cdf0e10cSrcweir  * Adobe Systems Incorporated.
11cdf0e10cSrcweir  *
12cdf0e10cSrcweir  * ************************************************************************
13cdf0e10cSrcweir  * THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
14cdf0e10cSrcweir  * NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
15cdf0e10cSrcweir  * INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
16cdf0e10cSrcweir  * LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
17cdf0e10cSrcweir  * KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
18cdf0e10cSrcweir  * AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
19cdf0e10cSrcweir  * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
20cdf0e10cSrcweir  * ************************************************************************
21cdf0e10cSrcweir  */
22cdf0e10cSrcweir 
23cdf0e10cSrcweir /*
24cdf0e10cSrcweir  * Changes made for OpenOffice.org
25cdf0e10cSrcweir  *
26cdf0e10cSrcweir  *  10/24/2000 pl       - changed code to compile with c++-compilers
27cdf0e10cSrcweir  *                      - added namespace to avoid symbol clashes
28cdf0e10cSrcweir  *                      - replaced BOOL by bool
29cdf0e10cSrcweir  *                      - added function to free space allocated by parseFile
30cdf0e10cSrcweir  *  10/26/2000 pl       - added additional keys
31cdf0e10cSrcweir  *                      - added ability to parse slightly broken files
32cdf0e10cSrcweir  *                      - added charwidth member to GlobalFontInfo
33cdf0e10cSrcweir  *  04/26/2001 pl       - added OpenOffice header
34cdf0e10cSrcweir  *  10/19/2005 pl       - performance increase:
35cdf0e10cSrcweir  *                         - fread file in one pass
36cdf0e10cSrcweir  *                         - replace file io by buffer access
37cdf0e10cSrcweir  *  10/20/2005 pl       - performance increase:
38cdf0e10cSrcweir  *                         - use one table lookup in token() routine
39cdf0e10cSrcweir  *                           instead of many conditions
40cdf0e10cSrcweir  *                         - return token length in toke() routine
41cdf0e10cSrcweir  *                         - use hash lookup instead of binary search
42cdf0e10cSrcweir  *                           in recognize() routine
43cdf0e10cSrcweir  */
44cdf0e10cSrcweir 
45cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
46cdf0e10cSrcweir #include "precompiled_vcl.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir /* parseAFM.c
49cdf0e10cSrcweir  *
5086e1cf34SPedro Giffuni  * This file is used in conjunction with the parseAFM.h header file.
51cdf0e10cSrcweir  * This file contains several procedures that are used to parse AFM
52cdf0e10cSrcweir  * files. It is intended to work with an application program that needs
53cdf0e10cSrcweir  * font metric information. The program can be used as is by making a
54cdf0e10cSrcweir  * procedure call to "parseFile" (passing in the expected parameters)
55cdf0e10cSrcweir  * and having it fill in a data structure with the data from the
56cdf0e10cSrcweir  * AFM file, or an application developer may wish to customize this
57cdf0e10cSrcweir  * code.
58cdf0e10cSrcweir  *
59cdf0e10cSrcweir  * There is also a file, parseAFMclient.c, that is a sample application
60cdf0e10cSrcweir  * showing how to call the "parseFile" procedure and how to use the data
61cdf0e10cSrcweir  * after "parseFile" has returned.
62cdf0e10cSrcweir  *
63cdf0e10cSrcweir  * Please read the comments in parseAFM.h and parseAFMclient.c.
64cdf0e10cSrcweir  *
65cdf0e10cSrcweir  * History:
66cdf0e10cSrcweir  *  original: DSM  Thu Oct 20 17:39:59 PDT 1988
67cdf0e10cSrcweir  *  modified: DSM  Mon Jul  3 14:17:50 PDT 1989
68cdf0e10cSrcweir  *    - added 'storageProblem' return code
69cdf0e10cSrcweir  *    - fixed bug of not allocating extra byte for string duplication
70cdf0e10cSrcweir  *    - fixed typos
71cdf0e10cSrcweir  *  modified: DSM  Tue Apr  3 11:18:34 PDT 1990
72cdf0e10cSrcweir  *    - added free(ident) at end of parseFile routine
73cdf0e10cSrcweir  *  modified: DSM  Tue Jun 19 10:16:29 PDT 1990
74cdf0e10cSrcweir  *    - changed (width == 250) to (width = 250) in initializeArray
75cdf0e10cSrcweir  */
76cdf0e10cSrcweir 
77cdf0e10cSrcweir #include <stdio.h>
78cdf0e10cSrcweir #include <string.h>
79cdf0e10cSrcweir #include <stdlib.h>
80cdf0e10cSrcweir #include <errno.h>
81cdf0e10cSrcweir #include <sys/file.h>
82cdf0e10cSrcweir #include <sys/stat.h>
83cdf0e10cSrcweir #include <math.h>
84cdf0e10cSrcweir 
85cdf0e10cSrcweir #include "parseAFM.hxx"
86cdf0e10cSrcweir #include "vcl/strhelper.hxx"
87cdf0e10cSrcweir 
88cdf0e10cSrcweir #include "rtl/alloc.h"
89cdf0e10cSrcweir 
90cdf0e10cSrcweir #define lineterm EOL    /* line terminating character */
91cdf0e10cSrcweir #define normalEOF 1 /* return code from parsing routines used only */
92cdf0e10cSrcweir /* in this module */
93cdf0e10cSrcweir #define Space "space"   /* used in string comparison to look for the width */
94cdf0e10cSrcweir /* of the space character to init the widths array */
95cdf0e10cSrcweir #define False "false"   /* used in string comparison to check the value of */
96cdf0e10cSrcweir /* boolean keys (e.g. IsFixedPitch)  */
97cdf0e10cSrcweir 
98cdf0e10cSrcweir #define MATCH(A,B)      (strncmp((A),(B), MAX_NAME) == 0)
99cdf0e10cSrcweir 
100cdf0e10cSrcweir namespace psp {
101cdf0e10cSrcweir 
102cdf0e10cSrcweir class FileInputStream
103cdf0e10cSrcweir {
104cdf0e10cSrcweir     char*         m_pMemory;
105cdf0e10cSrcweir     unsigned int        m_nPos;
106cdf0e10cSrcweir     unsigned int        m_nLen;
107cdf0e10cSrcweir     public:
108cdf0e10cSrcweir     FileInputStream( const char* pFilename );
109cdf0e10cSrcweir     ~FileInputStream();
110cdf0e10cSrcweir 
getChar()111cdf0e10cSrcweir     int getChar() { return (m_nPos < m_nLen) ? int(m_pMemory[m_nPos++]) : -1; }
ungetChar()112cdf0e10cSrcweir     void ungetChar()
113cdf0e10cSrcweir     {
114cdf0e10cSrcweir         if( m_nPos > 0 )
115cdf0e10cSrcweir             m_nPos--;
116cdf0e10cSrcweir     }
tell() const117cdf0e10cSrcweir     unsigned int tell() const { return m_nPos; }
seek(unsigned int nPos)118cdf0e10cSrcweir     void seek( unsigned int nPos )
119cdf0e10cSrcweir     // NOTE: do not check input data since only results of tell()
120cdf0e10cSrcweir     // get seek()ed in this file
121cdf0e10cSrcweir     { m_nPos = nPos; }
122cdf0e10cSrcweir };
123cdf0e10cSrcweir 
FileInputStream(const char * pFilename)124cdf0e10cSrcweir FileInputStream::FileInputStream( const char* pFilename ) :
125cdf0e10cSrcweir     m_pMemory( NULL ),
126cdf0e10cSrcweir     m_nPos( 0 ),
127cdf0e10cSrcweir     m_nLen( 0 )
128cdf0e10cSrcweir {
129cdf0e10cSrcweir     struct stat aStat;
130cdf0e10cSrcweir     if( ! stat( pFilename, &aStat ) &&
131cdf0e10cSrcweir         S_ISREG( aStat.st_mode )    &&
132cdf0e10cSrcweir         aStat.st_size > 0
133cdf0e10cSrcweir       )
134cdf0e10cSrcweir     {
135cdf0e10cSrcweir         FILE* fp = fopen( pFilename, "r" );
136cdf0e10cSrcweir         if( fp )
137cdf0e10cSrcweir         {
138cdf0e10cSrcweir             m_pMemory = (char*)rtl_allocateMemory( aStat.st_size );
139cdf0e10cSrcweir             m_nLen = (unsigned int)fread( m_pMemory, 1, aStat.st_size, fp );
140cdf0e10cSrcweir             fclose( fp );
141cdf0e10cSrcweir         }
142cdf0e10cSrcweir     }
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
~FileInputStream()145cdf0e10cSrcweir FileInputStream::~FileInputStream()
146cdf0e10cSrcweir {
147cdf0e10cSrcweir     rtl_freeMemory( m_pMemory );
148cdf0e10cSrcweir }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir /*************************** GLOBALS ***********************/
151cdf0e10cSrcweir /* "shorts" for fast case statement
152cdf0e10cSrcweir  * The values of each of these enumerated items correspond to an entry in the
153cdf0e10cSrcweir  * table of strings defined below. Therefore, if you add a new string as
154cdf0e10cSrcweir  * new keyword into the keyStrings table, you must also add a corresponding
155cdf0e10cSrcweir  * parseKey AND it MUST be in the same position!
156cdf0e10cSrcweir  *
157cdf0e10cSrcweir  * IMPORTANT: since the sorting algorithm is a binary search, the strings of
158cdf0e10cSrcweir  * keywords must be placed in lexicographical order, below. [Therefore, the
159cdf0e10cSrcweir  * enumerated items are not necessarily in lexicographical order, depending
160cdf0e10cSrcweir  * on the name chosen. BUT, they must be placed in the same position as the
161cdf0e10cSrcweir  * corresponding key string.] The NOPE shall remain in the last position,
162cdf0e10cSrcweir  * since it does not correspond to any key string, and it is used in the
163cdf0e10cSrcweir  * "recognize" procedure to calculate how many possible keys there are.
164cdf0e10cSrcweir  */
165cdf0e10cSrcweir 
166cdf0e10cSrcweir // some metrics have Ascent, Descent instead Ascender, Descender or Em
167e4384c19SJohn Bampton // which is not allowed per afm specification, but let us handle
168cdf0e10cSrcweir // this gently
169cdf0e10cSrcweir enum parseKey {
170cdf0e10cSrcweir     ASCENDER, ASCENT, CHARBBOX, CODE, COMPCHAR, CODEHEX, CAPHEIGHT, CHARWIDTH, CHARACTERSET, CHARACTERS, COMMENT,
171cdf0e10cSrcweir     DESCENDER, DESCENT, EM, ENCODINGSCHEME, ENDCHARMETRICS, ENDCOMPOSITES, ENDDIRECTION,
172cdf0e10cSrcweir     ENDFONTMETRICS, ENDKERNDATA, ENDKERNPAIRS, ENDTRACKKERN,
173cdf0e10cSrcweir     FAMILYNAME, FONTBBOX, FONTNAME, FULLNAME, ISBASEFONT, ISFIXEDPITCH,
174cdf0e10cSrcweir     ITALICANGLE, KERNPAIR, KERNPAIRXAMT, LIGATURE, MAPPINGSCHEME, METRICSSETS, CHARNAME,
175cdf0e10cSrcweir     NOTICE, COMPCHARPIECE, STARTCHARMETRICS, STARTCOMPOSITES, STARTDIRECTION,
176cdf0e10cSrcweir     STARTFONTMETRICS, STARTKERNDATA, STARTKERNPAIRS,
177cdf0e10cSrcweir     STARTTRACKKERN, STDHW, STDVW, TRACKKERN, UNDERLINEPOSITION,
178cdf0e10cSrcweir     UNDERLINETHICKNESS, VVECTOR, VERSION, XYWIDTH, X0WIDTH, XWIDTH, WEIGHT, XHEIGHT,
179cdf0e10cSrcweir     NOPE
180cdf0e10cSrcweir };
181cdf0e10cSrcweir 
182cdf0e10cSrcweir /*************************** PARSING ROUTINES **************/
183cdf0e10cSrcweir 
184cdf0e10cSrcweir /*************************** token *************************/
185cdf0e10cSrcweir 
186cdf0e10cSrcweir /*  A "AFM file Conventions" tokenizer. That means that it will
187cdf0e10cSrcweir  *  return the next token delimited by white space.  See also
188cdf0e10cSrcweir  *  the `linetoken' routine, which does a similar thing but
189cdf0e10cSrcweir  *  reads all tokens until the next end-of-line.
190cdf0e10cSrcweir  */
191cdf0e10cSrcweir 
192cdf0e10cSrcweir // token white space is ' ', '\n', '\r', ',', '\t', ';'
193cdf0e10cSrcweir static const bool is_white_Array[ 256 ] =
194cdf0e10cSrcweir {   false, false, false, false, false, false, false, false, // 0-7
195cdf0e10cSrcweir     false,  true,  true, false, false,  true, false, false, // 8-15
196cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 16-23
197cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 24-31
198cdf0e10cSrcweir      true, false, false, false, false, false, false, false, // 32-39
199cdf0e10cSrcweir     false, false, false, false,  true, false, false, false, // 40-47
200cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 48-55
201cdf0e10cSrcweir     false, false, false,  true, false, false, false, false, // 56-63
202cdf0e10cSrcweir 
203cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 64 -
204cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
205cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
206cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
207cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
208cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
209cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
210cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 127
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 128 -
213cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
214cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
215cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
216cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
217cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
218cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
219cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 191
220cdf0e10cSrcweir 
221cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 192 -
222cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
223cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
224cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
225cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
226cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
227cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
228cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 255
229cdf0e10cSrcweir };
230cdf0e10cSrcweir // token delimiters are ' ', '\n', '\r', '\t', ':', ';'
231cdf0e10cSrcweir static const bool is_delimiter_Array[ 256 ] =
232cdf0e10cSrcweir {   false, false, false, false, false, false, false, false, // 0-7
233cdf0e10cSrcweir     false,  true,  true, false, false,  true, false, false, // 8-15
234cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 16-23
235cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 24-31
236cdf0e10cSrcweir      true, false, false, false, false, false, false, false, // 32-39
237cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 40-47
238cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 48-55
239cdf0e10cSrcweir     false, false,  true,  true, false, false, false, false, // 56-63
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 64 -
242cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
243cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
244cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
245cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
246cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
247cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
248cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 127
249cdf0e10cSrcweir 
250cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 128 -
251cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
252cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
253cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
254cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
255cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
256cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
257cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 191
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 192 -
260cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
261cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
262cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
263cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
264cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
265cdf0e10cSrcweir     false, false, false, false, false, false, false, false,
266cdf0e10cSrcweir     false, false, false, false, false, false, false, false, // 255
267cdf0e10cSrcweir };
token(FileInputStream * stream,int & rLen)268cdf0e10cSrcweir static char *token( FileInputStream* stream, int& rLen )
269cdf0e10cSrcweir {
270cdf0e10cSrcweir     static char ident[MAX_NAME]; /* storage buffer for keywords */
271cdf0e10cSrcweir 
272cdf0e10cSrcweir     int ch, idx;
273cdf0e10cSrcweir 
274cdf0e10cSrcweir     /* skip over white space */
275cdf0e10cSrcweir     // relies on EOF = -1
276cdf0e10cSrcweir     while( is_white_Array[ (ch = stream->getChar()) & 255 ] )
277cdf0e10cSrcweir         ;
278cdf0e10cSrcweir 
279cdf0e10cSrcweir     idx = 0;
280cdf0e10cSrcweir     while( ch != -1 && ! is_delimiter_Array[ ch & 255 ] && idx < MAX_NAME-1 )
281cdf0e10cSrcweir     {
282cdf0e10cSrcweir         ident[idx++] = ch;
283cdf0e10cSrcweir         ch = stream->getChar();
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     if (ch == -1 && idx < 1) return ((char *)NULL);
287cdf0e10cSrcweir     if (idx >= 1 && ch != ':' && ch != -1) stream->ungetChar();
288cdf0e10cSrcweir     if (idx < 1 ) ident[idx++] = ch;    /* single-character token */
289cdf0e10cSrcweir     ident[idx] = 0;
290cdf0e10cSrcweir     rLen = idx;
291cdf0e10cSrcweir 
292cdf0e10cSrcweir     return(ident);  /* returns pointer to the token */
293cdf0e10cSrcweir 
294cdf0e10cSrcweir } /* token */
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 
297cdf0e10cSrcweir /*************************** linetoken *************************/
298cdf0e10cSrcweir 
299cdf0e10cSrcweir /*  "linetoken" will get read all tokens until the EOL character from
300cdf0e10cSrcweir  *  the given stream.  This is used to get any arguments that can be
301cdf0e10cSrcweir  *  more than one word (like Comment lines and FullName).
302cdf0e10cSrcweir  */
303cdf0e10cSrcweir 
linetoken(FileInputStream * stream)304cdf0e10cSrcweir static char *linetoken( FileInputStream* stream )
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     static char ident[MAX_NAME]; /* storage buffer for keywords */
307cdf0e10cSrcweir     int ch, idx;
308cdf0e10cSrcweir 
309cdf0e10cSrcweir     while ((ch = stream->getChar()) == ' ' || ch == '\t' ) ;
310cdf0e10cSrcweir 
311cdf0e10cSrcweir     idx = 0;
312cdf0e10cSrcweir     while (ch != -1 && ch != lineterm && ch != '\r' && idx < MAX_NAME-1 )
313cdf0e10cSrcweir     {
314cdf0e10cSrcweir         ident[idx++] = ch;
315cdf0e10cSrcweir         ch = stream->getChar();
316cdf0e10cSrcweir     } /* while */
317cdf0e10cSrcweir 
318cdf0e10cSrcweir     stream->ungetChar();
319cdf0e10cSrcweir     ident[idx] = 0;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     return(ident);  /* returns pointer to the token */
322cdf0e10cSrcweir 
323cdf0e10cSrcweir } /* linetoken */
324cdf0e10cSrcweir 
325cdf0e10cSrcweir 
326cdf0e10cSrcweir /*************************** recognize *************************/
327cdf0e10cSrcweir 
328cdf0e10cSrcweir /*  This function tries to match a string to a known list of
329cdf0e10cSrcweir  *  valid AFM entries (check the keyStrings array above).
330cdf0e10cSrcweir  *  "ident" contains everything from white space through the
331cdf0e10cSrcweir  *  next space, tab, or ":" character.
332cdf0e10cSrcweir  *
333cdf0e10cSrcweir  *  The algorithm is a standard Knuth binary search.
334cdf0e10cSrcweir  */
335cdf0e10cSrcweir #include "afm_hash.cpp"
336cdf0e10cSrcweir 
recognize(char * ident,int len)337c1e8cc3aSDon Lewis static inline enum parseKey recognize( char* ident, int len)
338cdf0e10cSrcweir {
339cdf0e10cSrcweir     const hash_entry* pEntry = AfmKeywordHash::in_word_set( ident, len );
340cdf0e10cSrcweir     return pEntry ? pEntry->eKey : NOPE;
341cdf0e10cSrcweir 
342cdf0e10cSrcweir } /* recognize */
343cdf0e10cSrcweir 
344cdf0e10cSrcweir 
345cdf0e10cSrcweir /************************* parseGlobals *****************************/
346cdf0e10cSrcweir 
347cdf0e10cSrcweir /*  This function is called by "parseFile". It will parse the AFM file
348cdf0e10cSrcweir  *  up to the "StartCharMetrics" keyword, which essentially marks the
349cdf0e10cSrcweir  *  end of the Global Font Information and the beginning of the character
350cdf0e10cSrcweir  *  metrics information.
351cdf0e10cSrcweir  *
352cdf0e10cSrcweir  *  If the caller of "parseFile" specified that it wanted the Global
353cdf0e10cSrcweir  *  Font Information (as defined by the "AFM file Specification"
354cdf0e10cSrcweir  *  document), then that information will be stored in the returned
355cdf0e10cSrcweir  *  data structure.
356cdf0e10cSrcweir  *
357cdf0e10cSrcweir  *  Any Global Font Information entries that are not found in a
358cdf0e10cSrcweir  *  given file, will have the usual default initialization value
359cdf0e10cSrcweir  *  for its type (i.e. entries of type int will be 0, etc).
360cdf0e10cSrcweir  *
361cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
362cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
363cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
364cdf0e10cSrcweir  */
365cdf0e10cSrcweir 
parseGlobals(FileInputStream * fp,GlobalFontInfo * gfi)366c1e8cc3aSDon Lewis static int parseGlobals( FileInputStream* fp, GlobalFontInfo* gfi )
367cdf0e10cSrcweir {
368cdf0e10cSrcweir     bool cont = true, save = (gfi != NULL);
369cdf0e10cSrcweir     int error = ok;
370c1e8cc3aSDon Lewis     char *keyword;
371cdf0e10cSrcweir     int direction = -1;
372cdf0e10cSrcweir     int tokenlen;
373cdf0e10cSrcweir 
374cdf0e10cSrcweir     while (cont)
375cdf0e10cSrcweir     {
376cdf0e10cSrcweir         keyword = token(fp, tokenlen);
377cdf0e10cSrcweir 
378cdf0e10cSrcweir         if (keyword == NULL)
379cdf0e10cSrcweir             /* Have reached an early and unexpected EOF. */
380cdf0e10cSrcweir             /* Set flag and stop parsing */
381cdf0e10cSrcweir         {
382cdf0e10cSrcweir             error = earlyEOF;
383cdf0e10cSrcweir             break;   /* get out of loop */
384cdf0e10cSrcweir         }
385cdf0e10cSrcweir         if (!save)
386cdf0e10cSrcweir             /* get tokens until the end of the Global Font info section */
387cdf0e10cSrcweir             /* without saving any of the data */
388cdf0e10cSrcweir             switch (recognize(keyword, tokenlen))
389cdf0e10cSrcweir             {
390cdf0e10cSrcweir                 case STARTCHARMETRICS:
391cdf0e10cSrcweir                     cont = false;
392cdf0e10cSrcweir                     break;
393cdf0e10cSrcweir                 case ENDFONTMETRICS:
394cdf0e10cSrcweir                     cont = false;
395cdf0e10cSrcweir                     error = normalEOF;
396cdf0e10cSrcweir                     break;
397cdf0e10cSrcweir                 default:
398cdf0e10cSrcweir                     break;
399cdf0e10cSrcweir             } /* switch */
400cdf0e10cSrcweir         else
401cdf0e10cSrcweir             /* otherwise parse entire global font info section, */
402cdf0e10cSrcweir             /* saving the data */
403cdf0e10cSrcweir             switch(recognize(keyword, tokenlen))
404cdf0e10cSrcweir             {
405cdf0e10cSrcweir                 case STARTFONTMETRICS:
406cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
407cdf0e10cSrcweir                         gfi->afmVersion = strdup( keyword );
408cdf0e10cSrcweir                     break;
409cdf0e10cSrcweir                 case COMMENT:
410cdf0e10cSrcweir                     keyword = linetoken(fp);
411cdf0e10cSrcweir                     break;
412cdf0e10cSrcweir                 case FONTNAME:
413cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
414cdf0e10cSrcweir                         gfi->fontName = strdup( keyword );
415cdf0e10cSrcweir                     break;
416cdf0e10cSrcweir                 case ENCODINGSCHEME:
417cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
418cdf0e10cSrcweir                         gfi->encodingScheme = strdup( keyword );
419cdf0e10cSrcweir                     break;
420cdf0e10cSrcweir                 case FULLNAME:
421cdf0e10cSrcweir                     if ((keyword = linetoken(fp)) != NULL)
422cdf0e10cSrcweir                         gfi->fullName = strdup( keyword );
423cdf0e10cSrcweir                     break;
424cdf0e10cSrcweir                 case FAMILYNAME:
425cdf0e10cSrcweir                     if ((keyword = linetoken(fp)) != NULL)
426cdf0e10cSrcweir                         gfi->familyName = strdup( keyword );
427cdf0e10cSrcweir                     break;
428cdf0e10cSrcweir                 case WEIGHT:
429cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
430cdf0e10cSrcweir                         gfi->weight = strdup( keyword );
431cdf0e10cSrcweir                     break;
432cdf0e10cSrcweir                 case ITALICANGLE:
433cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
434cdf0e10cSrcweir                         gfi->italicAngle = StringToDouble( keyword );
435cdf0e10cSrcweir                     break;
436cdf0e10cSrcweir                 case ISFIXEDPITCH:
437cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
438cdf0e10cSrcweir                     {
439cdf0e10cSrcweir                         if (MATCH(keyword, False))
440cdf0e10cSrcweir                             gfi->isFixedPitch = 0;
441cdf0e10cSrcweir                         else
442cdf0e10cSrcweir                             gfi->isFixedPitch = 1;
443cdf0e10cSrcweir                     }
444cdf0e10cSrcweir                     break;
445cdf0e10cSrcweir                 case UNDERLINEPOSITION:
446cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
447cdf0e10cSrcweir                         gfi->underlinePosition = atoi(keyword);
448cdf0e10cSrcweir                     break;
449cdf0e10cSrcweir                 case UNDERLINETHICKNESS:
450cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
451cdf0e10cSrcweir                         gfi->underlineThickness = atoi(keyword);
452cdf0e10cSrcweir                     break;
453cdf0e10cSrcweir                 case VERSION:
454cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
455cdf0e10cSrcweir                         gfi->version = strdup( keyword );
456cdf0e10cSrcweir                     break;
457cdf0e10cSrcweir                 case NOTICE:
458cdf0e10cSrcweir                     if ((keyword = linetoken(fp)) != NULL)
459cdf0e10cSrcweir                         gfi->notice = strdup( keyword );
460cdf0e10cSrcweir                     break;
461cdf0e10cSrcweir                 case FONTBBOX:
462cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
463cdf0e10cSrcweir                         gfi->fontBBox.llx = atoi(keyword);
464cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
465cdf0e10cSrcweir                         gfi->fontBBox.lly = atoi(keyword);
466cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
467cdf0e10cSrcweir                         gfi->fontBBox.urx = atoi(keyword);
468cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
469cdf0e10cSrcweir                         gfi->fontBBox.ury = atoi(keyword);
470cdf0e10cSrcweir                     break;
471cdf0e10cSrcweir                 case CAPHEIGHT:
472cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
473cdf0e10cSrcweir                         gfi->capHeight = atoi(keyword);
474cdf0e10cSrcweir                     break;
475cdf0e10cSrcweir                 case XHEIGHT:
476cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
477cdf0e10cSrcweir                         gfi->xHeight = atoi(keyword);
478cdf0e10cSrcweir                     break;
479cdf0e10cSrcweir                 case DESCENT:
480cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
481cdf0e10cSrcweir                         gfi->descender = -atoi(keyword);
482cdf0e10cSrcweir                     break;
483cdf0e10cSrcweir                 case DESCENDER:
484cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
485cdf0e10cSrcweir                         gfi->descender = atoi(keyword);
486cdf0e10cSrcweir                     break;
487cdf0e10cSrcweir                 case ASCENT:
488cdf0e10cSrcweir                 case ASCENDER:
489cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
490cdf0e10cSrcweir                         gfi->ascender = atoi(keyword);
491cdf0e10cSrcweir                     break;
492cdf0e10cSrcweir                 case STARTCHARMETRICS:
493cdf0e10cSrcweir                     cont = false;
494cdf0e10cSrcweir                     break;
495cdf0e10cSrcweir                 case ENDFONTMETRICS:
496cdf0e10cSrcweir                     cont = false;
497cdf0e10cSrcweir                     error = normalEOF;
498cdf0e10cSrcweir                     break;
499cdf0e10cSrcweir                 case EM:
500cdf0e10cSrcweir                     // skip one token
501cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
502cdf0e10cSrcweir                     break;
503cdf0e10cSrcweir                 case STARTDIRECTION:
504cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
505cdf0e10cSrcweir                         direction = atoi(keyword);
506cdf0e10cSrcweir                     break; /* ignore this for now */
507cdf0e10cSrcweir                 case ENDDIRECTION:
508cdf0e10cSrcweir                     break; /* ignore this for now */
509cdf0e10cSrcweir                 case MAPPINGSCHEME:
510cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
511cdf0e10cSrcweir                     break; /* ignore     this for now */
512cdf0e10cSrcweir                 case CHARACTERS:
513cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
514cdf0e10cSrcweir                     break; /* ignore this for now */
515cdf0e10cSrcweir                 case ISBASEFONT:
516cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
517cdf0e10cSrcweir                     break; /* ignore this for now */
518cdf0e10cSrcweir                 case CHARACTERSET:
519cdf0e10cSrcweir                     keyword=token(fp,tokenlen); //ignore
520cdf0e10cSrcweir                     break;
521cdf0e10cSrcweir                 case STDHW:
522cdf0e10cSrcweir                     keyword=token(fp,tokenlen); //ignore
523cdf0e10cSrcweir                     break;
524cdf0e10cSrcweir                 case STDVW:
525cdf0e10cSrcweir                     keyword=token(fp,tokenlen); //ignore
526cdf0e10cSrcweir                     break;
527cdf0e10cSrcweir                 case CHARWIDTH:
528cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
529cdf0e10cSrcweir                     {
530cdf0e10cSrcweir                         if (direction == 0)
531cdf0e10cSrcweir                             gfi->charwidth = atoi(keyword);
532cdf0e10cSrcweir                     }
533cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
534cdf0e10cSrcweir                     /* ignore y-width for now */
535cdf0e10cSrcweir                     break;
536cdf0e10cSrcweir                 case METRICSSETS:
537cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
538cdf0e10cSrcweir                     break; /* ignore this for now */
539cdf0e10cSrcweir                 case NOPE:
540cdf0e10cSrcweir                 default:
541cdf0e10cSrcweir                     error = parseError;
542cdf0e10cSrcweir                     break;
543cdf0e10cSrcweir             } /* switch */
544cdf0e10cSrcweir     } /* while */
545cdf0e10cSrcweir 
546cdf0e10cSrcweir     return(error);
547cdf0e10cSrcweir 
548cdf0e10cSrcweir } /* parseGlobals */
549cdf0e10cSrcweir 
550cdf0e10cSrcweir 
551cdf0e10cSrcweir #if 0
552cdf0e10cSrcweir /************************* initializeArray ************************/
553cdf0e10cSrcweir 
554cdf0e10cSrcweir /*  Unmapped character codes are (at Adobe Systems) assigned the
555cdf0e10cSrcweir  *  width of the space character (if one exists) else they get the
556cdf0e10cSrcweir  *  value of 250 ems. This function initializes all entries in the
557cdf0e10cSrcweir  *  char widths array to have this value. Then any mapped character
558cdf0e10cSrcweir  *  codes will be replaced with the width of the appropriate character
559cdf0e10cSrcweir  *  when parsing the character metric section.
560cdf0e10cSrcweir 
561cdf0e10cSrcweir  *  This function parses the Character Metrics Section looking
562cdf0e10cSrcweir  *  for a space character (by comparing character names). If found,
563cdf0e10cSrcweir  *  the width of the space character will be used to initialize the
564cdf0e10cSrcweir  *  values in the array of character widths.
565cdf0e10cSrcweir  *
566cdf0e10cSrcweir  *  Before returning, the position of the read/write pointer of the
567cdf0e10cSrcweir  *  FileInputStream is reset to be where it was upon entering this function.
568cdf0e10cSrcweir  */
569cdf0e10cSrcweir 
570c1e8cc3aSDon Lewis static int initializeArray( FileInputStream* fp, int* cwi)
571cdf0e10cSrcweir {
572cdf0e10cSrcweir     bool cont = true, found = false;
573cdf0e10cSrcweir     unsigned int opos = fp->tell();
574cdf0e10cSrcweir     int code = 0, width = 0, i = 0, error = 0, tokenlen;
575c1e8cc3aSDon Lewis     char *keyword;
576cdf0e10cSrcweir 
577cdf0e10cSrcweir     while (cont)
578cdf0e10cSrcweir     {
579cdf0e10cSrcweir         keyword = token(fp,tokenlen);
580cdf0e10cSrcweir         if (keyword == NULL)
581cdf0e10cSrcweir         {
582cdf0e10cSrcweir             error = earlyEOF;
583cdf0e10cSrcweir             break; /* get out of loop */
584cdf0e10cSrcweir         }
585cdf0e10cSrcweir         switch(recognize(keyword,tokenlen))
586cdf0e10cSrcweir         {
587cdf0e10cSrcweir             case COMMENT:
588cdf0e10cSrcweir                 keyword = linetoken(fp);
589cdf0e10cSrcweir                 break;
590cdf0e10cSrcweir             case CODE:
591cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
592cdf0e10cSrcweir                     code = atoi(keyword);
593cdf0e10cSrcweir                 break;
594cdf0e10cSrcweir             case CODEHEX:
595cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
596cdf0e10cSrcweir                     sscanf(keyword,"<%x>", &code);
597cdf0e10cSrcweir                 break;
598cdf0e10cSrcweir             case XWIDTH:
599cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
600cdf0e10cSrcweir                     width = atoi(keyword);
601cdf0e10cSrcweir                 break;
602cdf0e10cSrcweir             case X0WIDTH:
603cdf0e10cSrcweir                 (void) token(fp,tokenlen);
604cdf0e10cSrcweir                 break;
605cdf0e10cSrcweir             case CHARNAME:
606cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
607cdf0e10cSrcweir                     if (MATCH(keyword, Space))
608cdf0e10cSrcweir                     {
609cdf0e10cSrcweir                         cont = false;
610cdf0e10cSrcweir                         found = true;
611cdf0e10cSrcweir                     }
612cdf0e10cSrcweir                 break;
613cdf0e10cSrcweir             case ENDCHARMETRICS:
614cdf0e10cSrcweir                 cont = false;
615cdf0e10cSrcweir                 break;
616cdf0e10cSrcweir             case ENDFONTMETRICS:
617cdf0e10cSrcweir                 cont = false;
618cdf0e10cSrcweir                 error = normalEOF;
619cdf0e10cSrcweir                 break;
620cdf0e10cSrcweir             case NOPE:
621cdf0e10cSrcweir             default:
622cdf0e10cSrcweir                 error = parseError;
623cdf0e10cSrcweir                 break;
624cdf0e10cSrcweir         } /* switch */
625cdf0e10cSrcweir     } /* while */
626cdf0e10cSrcweir 
627cdf0e10cSrcweir     if (!found)
628cdf0e10cSrcweir         width = 250;
629cdf0e10cSrcweir 
630cdf0e10cSrcweir     for (i = 0; i < 256; ++i)
631cdf0e10cSrcweir         cwi[i] = width;
632cdf0e10cSrcweir 
633cdf0e10cSrcweir     fp->seek(opos);
634cdf0e10cSrcweir 
635cdf0e10cSrcweir     return(error);
636cdf0e10cSrcweir 
637cdf0e10cSrcweir } /* initializeArray */
638cdf0e10cSrcweir #endif
639cdf0e10cSrcweir 
640cdf0e10cSrcweir /************************* parseCharWidths **************************/
641cdf0e10cSrcweir 
642cdf0e10cSrcweir /*  This function is called by "parseFile". It will parse the AFM file
643cdf0e10cSrcweir  *  up to the "EndCharMetrics" keyword. It will save the character
644cdf0e10cSrcweir  *  width info (as opposed to all of the character metric information)
645cdf0e10cSrcweir  *  if requested by the caller of parseFile. Otherwise, it will just
646cdf0e10cSrcweir  *  parse through the section without saving any information.
647cdf0e10cSrcweir  *
648cdf0e10cSrcweir  *  If data is to be saved, parseCharWidths is passed in a pointer
649cdf0e10cSrcweir  *  to an array of widths that has already been initialized by the
650cdf0e10cSrcweir  *  standard value for unmapped character codes. This function parses
651cdf0e10cSrcweir  *  the Character Metrics section only storing the width information
652cdf0e10cSrcweir  *  for the encoded characters into the array using the character code
653cdf0e10cSrcweir  *  as the index into that array.
654cdf0e10cSrcweir  *
655cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
656cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
657cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
658cdf0e10cSrcweir  */
659cdf0e10cSrcweir 
parseCharWidths(FileInputStream * fp,int * cwi)660c1e8cc3aSDon Lewis static int parseCharWidths( FileInputStream* fp, int* cwi)
661cdf0e10cSrcweir {
662cdf0e10cSrcweir     bool cont = true, save = (cwi != NULL);
663cdf0e10cSrcweir     int pos = 0, error = ok, tokenlen;
664c1e8cc3aSDon Lewis     char *keyword;
665cdf0e10cSrcweir 
666cdf0e10cSrcweir     while (cont)
667cdf0e10cSrcweir     {
668cdf0e10cSrcweir         keyword = token(fp,tokenlen);
669cdf0e10cSrcweir         /* Have reached an early and unexpected EOF. */
670cdf0e10cSrcweir         /* Set flag and stop parsing */
671cdf0e10cSrcweir         if (keyword == NULL)
672cdf0e10cSrcweir         {
673cdf0e10cSrcweir             error = earlyEOF;
674cdf0e10cSrcweir             break; /* get out of loop */
675cdf0e10cSrcweir         }
676cdf0e10cSrcweir         if (!save)
677cdf0e10cSrcweir             /* get tokens until the end of the Char Metrics section without */
678cdf0e10cSrcweir             /* saving any of the data*/
679cdf0e10cSrcweir             switch (recognize(keyword,tokenlen))
680cdf0e10cSrcweir             {
681cdf0e10cSrcweir                 case ENDCHARMETRICS:
682cdf0e10cSrcweir                     cont = false;
683cdf0e10cSrcweir                     break;
684cdf0e10cSrcweir                 case ENDFONTMETRICS:
685cdf0e10cSrcweir                     cont = false;
686cdf0e10cSrcweir                     error = normalEOF;
687cdf0e10cSrcweir                     break;
688cdf0e10cSrcweir                 default:
689cdf0e10cSrcweir                     break;
690cdf0e10cSrcweir             } /* switch */
691cdf0e10cSrcweir         else
692cdf0e10cSrcweir             /* otherwise parse entire char metrics section, saving */
693cdf0e10cSrcweir             /* only the char x-width info */
694cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
695cdf0e10cSrcweir             {
696cdf0e10cSrcweir                 case COMMENT:
697cdf0e10cSrcweir                     keyword = linetoken(fp);
698cdf0e10cSrcweir                     break;
699cdf0e10cSrcweir                 case CODE:
700cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
701cdf0e10cSrcweir                         pos = atoi(keyword);
702cdf0e10cSrcweir                     break;
703cdf0e10cSrcweir                 case XYWIDTH:
704cdf0e10cSrcweir                     /* PROBLEM: Should be no Y-WIDTH when doing "quick & dirty" */
705cdf0e10cSrcweir                     keyword = token(fp,tokenlen); keyword = token(fp,tokenlen); /* eat values */
706cdf0e10cSrcweir                     error = parseError;
707cdf0e10cSrcweir                     break;
708cdf0e10cSrcweir                 case CODEHEX:
709cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
710cdf0e10cSrcweir                         sscanf(keyword, "<%x>", &pos);
711cdf0e10cSrcweir                     break;
712cdf0e10cSrcweir                 case X0WIDTH:
713cdf0e10cSrcweir                     (void) token(fp,tokenlen);
714cdf0e10cSrcweir                     break;
715cdf0e10cSrcweir                 case XWIDTH:
716cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
717cdf0e10cSrcweir                         if (pos >= 0) /* ignore unmapped chars */
718cdf0e10cSrcweir                             cwi[pos] = atoi(keyword);
719cdf0e10cSrcweir                     break;
720cdf0e10cSrcweir                 case ENDCHARMETRICS:
721cdf0e10cSrcweir                     cont = false;
722cdf0e10cSrcweir                     break;
723cdf0e10cSrcweir                 case ENDFONTMETRICS:
724cdf0e10cSrcweir                     cont = false;
725cdf0e10cSrcweir                     error = normalEOF;
726cdf0e10cSrcweir                     break;
727cdf0e10cSrcweir                 case CHARNAME:  /* eat values (so doesn't cause parseError) */
728cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
729cdf0e10cSrcweir                     break;
730cdf0e10cSrcweir                 case CHARBBOX:
731cdf0e10cSrcweir                     keyword = token(fp,tokenlen); keyword = token(fp,tokenlen);
732cdf0e10cSrcweir                     keyword = token(fp,tokenlen); keyword = token(fp,tokenlen);
733cdf0e10cSrcweir                     break;
734cdf0e10cSrcweir                 case LIGATURE:
735cdf0e10cSrcweir                     keyword = token(fp,tokenlen); keyword = token(fp,tokenlen);
736cdf0e10cSrcweir                     break;
737cdf0e10cSrcweir                 case VVECTOR:
738cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
739cdf0e10cSrcweir                     keyword = token(fp,tokenlen);
740cdf0e10cSrcweir                     break;
741cdf0e10cSrcweir                 case NOPE:
742cdf0e10cSrcweir                 default:
743cdf0e10cSrcweir                     error = parseError;
744cdf0e10cSrcweir                     break;
745cdf0e10cSrcweir             } /* switch */
746cdf0e10cSrcweir     } /* while */
747cdf0e10cSrcweir 
748cdf0e10cSrcweir     return(error);
749cdf0e10cSrcweir 
750cdf0e10cSrcweir } /* parseCharWidths */
751cdf0e10cSrcweir 
752cdf0e10cSrcweir 
753cdf0e10cSrcweir /*
7548fbda7e2SJohn Bampton  * number of char metrics is almost always inaccurate, so be gentle and try to
755cdf0e10cSrcweir  * adapt our internal storage by adjusting the allocated list
756cdf0e10cSrcweir  */
757cdf0e10cSrcweir 
758cdf0e10cSrcweir static int
reallocFontMetrics(void ** pp_fontmetrics,int * p_oldcount,int n_newcount,unsigned int n_size)759cdf0e10cSrcweir reallocFontMetrics( void **pp_fontmetrics, int *p_oldcount, int n_newcount, unsigned int n_size )
760cdf0e10cSrcweir {
761cdf0e10cSrcweir     char *p_tmpmetrics = NULL;
762cdf0e10cSrcweir 
763cdf0e10cSrcweir     if ((pp_fontmetrics == NULL) || (*pp_fontmetrics == NULL))
764cdf0e10cSrcweir         return storageProblem;
765cdf0e10cSrcweir 
766cdf0e10cSrcweir     if (*p_oldcount == n_newcount)
767cdf0e10cSrcweir         return ok;
768cdf0e10cSrcweir 
769cdf0e10cSrcweir     p_tmpmetrics = (char*)realloc(*pp_fontmetrics, n_newcount * n_size);
770cdf0e10cSrcweir     if (p_tmpmetrics == NULL)
771cdf0e10cSrcweir         return storageProblem;
772cdf0e10cSrcweir 
773cdf0e10cSrcweir     if ( n_newcount > *p_oldcount )
774cdf0e10cSrcweir     {
775cdf0e10cSrcweir         char *p_inimetrics = p_tmpmetrics + n_size * *p_oldcount;
776cdf0e10cSrcweir         int   n_inimetrics = n_size * (n_newcount - *p_oldcount);
777cdf0e10cSrcweir         memset( p_inimetrics, 0, n_inimetrics );
778cdf0e10cSrcweir     }
779cdf0e10cSrcweir 
780cdf0e10cSrcweir     *pp_fontmetrics = p_tmpmetrics;
781cdf0e10cSrcweir     *p_oldcount    = n_newcount;
782cdf0e10cSrcweir 
783cdf0e10cSrcweir     return ok;
784cdf0e10cSrcweir }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir static unsigned int
enlargeCount(unsigned int n_oldcount)787cdf0e10cSrcweir enlargeCount( unsigned int n_oldcount )
788cdf0e10cSrcweir {
789cdf0e10cSrcweir     unsigned int n_newcount = n_oldcount + n_oldcount / 5;
790cdf0e10cSrcweir     if (n_oldcount == n_newcount )
791cdf0e10cSrcweir         n_newcount = n_oldcount + 5;
792cdf0e10cSrcweir 
793cdf0e10cSrcweir     return n_newcount;
794cdf0e10cSrcweir }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir /************************* parseCharMetrics ************************/
797cdf0e10cSrcweir 
798cdf0e10cSrcweir /*  This function is called by parseFile if the caller of parseFile
799cdf0e10cSrcweir  *  requested that all character metric information be saved
800cdf0e10cSrcweir  *  (as opposed to only the character width information).
801cdf0e10cSrcweir  *
802cdf0e10cSrcweir  *  parseCharMetrics is passed in a pointer to an array of records
803cdf0e10cSrcweir  *  to hold information on a per character basis. This function
804cdf0e10cSrcweir  *  parses the Character Metrics section storing all character
805cdf0e10cSrcweir  *  metric information for the ALL characters (mapped and unmapped)
806cdf0e10cSrcweir  *  into the array.
807cdf0e10cSrcweir  *
808cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
809cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
810cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
811cdf0e10cSrcweir  */
812cdf0e10cSrcweir 
parseCharMetrics(FileInputStream * fp,FontInfo * fi)813c1e8cc3aSDon Lewis static int parseCharMetrics( FileInputStream* fp, FontInfo* fi)
814cdf0e10cSrcweir {
815cdf0e10cSrcweir     bool cont = true, firstTime = true;
816cdf0e10cSrcweir     int error = ok, count = 0, tokenlen;
817c1e8cc3aSDon Lewis     CharMetricInfo *temp = fi->cmi;
818c1e8cc3aSDon Lewis     char *keyword;
819cdf0e10cSrcweir 
820cdf0e10cSrcweir     while (cont)
821cdf0e10cSrcweir     {
822cdf0e10cSrcweir         keyword = token(fp,tokenlen);
823cdf0e10cSrcweir         if (keyword == NULL)
824cdf0e10cSrcweir         {
825cdf0e10cSrcweir             error = earlyEOF;
826cdf0e10cSrcweir             break; /* get out of loop */
827cdf0e10cSrcweir         }
828cdf0e10cSrcweir         switch(recognize(keyword,tokenlen))
829cdf0e10cSrcweir         {
830cdf0e10cSrcweir             case COMMENT:
831cdf0e10cSrcweir                 keyword = linetoken(fp);
832cdf0e10cSrcweir                 break;
833cdf0e10cSrcweir             case CODE:
834cdf0e10cSrcweir                 if (!(count < fi->numOfChars))
835cdf0e10cSrcweir                 {
836cdf0e10cSrcweir                     reallocFontMetrics( (void**)&(fi->cmi),
837cdf0e10cSrcweir                                         &(fi->numOfChars), enlargeCount(fi->numOfChars),
838cdf0e10cSrcweir                                         sizeof(CharMetricInfo) );
839cdf0e10cSrcweir                     temp = &(fi->cmi[ count - 1 ]);
840cdf0e10cSrcweir                 }
841cdf0e10cSrcweir                 if (count < fi->numOfChars)
842cdf0e10cSrcweir                 {
843cdf0e10cSrcweir                     if (firstTime) firstTime = false;
844cdf0e10cSrcweir                     else temp++;
845cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
846cdf0e10cSrcweir                         temp->code = atoi(keyword);
847cdf0e10cSrcweir                     if (fi->gfi && fi->gfi->charwidth)
848cdf0e10cSrcweir                         temp->wx = fi->gfi->charwidth;
849cdf0e10cSrcweir                     count++;
850cdf0e10cSrcweir                 }
851cdf0e10cSrcweir                 else
852cdf0e10cSrcweir                 {
853cdf0e10cSrcweir                     error = parseError;
854cdf0e10cSrcweir                     cont = false;
855cdf0e10cSrcweir                 }
856cdf0e10cSrcweir                 break;
857cdf0e10cSrcweir             case CODEHEX:
858cdf0e10cSrcweir                 if (!(count < fi->numOfChars ))
859cdf0e10cSrcweir                 {
860cdf0e10cSrcweir                     reallocFontMetrics( (void**)&(fi->cmi),
861cdf0e10cSrcweir                                         &(fi->numOfChars), enlargeCount(fi->numOfChars),
862cdf0e10cSrcweir                                         sizeof(CharMetricInfo) );
863cdf0e10cSrcweir                     temp = &(fi->cmi[ count - 1 ]);
864cdf0e10cSrcweir                 }
865cdf0e10cSrcweir                 if (count < fi->numOfChars) {
866cdf0e10cSrcweir                     if (firstTime)
867cdf0e10cSrcweir                         firstTime = false;
868cdf0e10cSrcweir                     else
869cdf0e10cSrcweir                         temp++;
870cdf0e10cSrcweir                     if ((keyword = token(fp,tokenlen)) != NULL)
871cdf0e10cSrcweir                         sscanf(keyword,"<%x>", &temp->code);
872cdf0e10cSrcweir                     if (fi->gfi && fi->gfi->charwidth)
873cdf0e10cSrcweir                         temp->wx = fi->gfi->charwidth;
874cdf0e10cSrcweir                     count++;
875cdf0e10cSrcweir                 }
876cdf0e10cSrcweir                 else {
877cdf0e10cSrcweir                     error = parseError;
878cdf0e10cSrcweir                     cont = false;
879cdf0e10cSrcweir                 }
880cdf0e10cSrcweir                 break;
881cdf0e10cSrcweir             case XYWIDTH:
882cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
883cdf0e10cSrcweir                     temp->wx = atoi(keyword);
884cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
885cdf0e10cSrcweir                     temp->wy = atoi(keyword);
886cdf0e10cSrcweir                 break;
887cdf0e10cSrcweir             case X0WIDTH:
888cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
889cdf0e10cSrcweir                     temp->wx = atoi(keyword);
890cdf0e10cSrcweir                 break;
891cdf0e10cSrcweir             case XWIDTH:
892cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
893cdf0e10cSrcweir                     temp->wx = atoi(keyword);
894cdf0e10cSrcweir                 break;
895cdf0e10cSrcweir             case CHARNAME:
896cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
897cdf0e10cSrcweir                     temp->name = (char *)strdup(keyword);
898cdf0e10cSrcweir                 break;
899cdf0e10cSrcweir             case CHARBBOX:
900cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
901cdf0e10cSrcweir                     temp->charBBox.llx = atoi(keyword);
902cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
903cdf0e10cSrcweir                     temp->charBBox.lly = atoi(keyword);
904cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
905cdf0e10cSrcweir                     temp->charBBox.urx = atoi(keyword);
906cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
907cdf0e10cSrcweir                     temp->charBBox.ury = atoi(keyword);
908cdf0e10cSrcweir                 break;
909cdf0e10cSrcweir             case LIGATURE: {
910cdf0e10cSrcweir                 Ligature **tail = &(temp->ligs);
911cdf0e10cSrcweir                 Ligature *node = *tail;
912cdf0e10cSrcweir 
913cdf0e10cSrcweir                 if (*tail != NULL)
914cdf0e10cSrcweir                 {
915cdf0e10cSrcweir                     while (node->next != NULL)
916cdf0e10cSrcweir                         node = node->next;
917cdf0e10cSrcweir                     tail = &(node->next);
918cdf0e10cSrcweir                 }
919cdf0e10cSrcweir 
920cdf0e10cSrcweir                 *tail = (Ligature *) calloc(1, sizeof(Ligature));
921cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
922cdf0e10cSrcweir                     (*tail)->succ = (char *)strdup(keyword);
923cdf0e10cSrcweir                 if ((keyword = token(fp,tokenlen)) != NULL)
924cdf0e10cSrcweir                     (*tail)->lig = (char *)strdup(keyword);
925cdf0e10cSrcweir                 break; }
926cdf0e10cSrcweir             case ENDCHARMETRICS:
927*6bcc9fe0Smseidel                 cont = false;
928cdf0e10cSrcweir                 break;
929cdf0e10cSrcweir             case ENDFONTMETRICS:
930cdf0e10cSrcweir                 cont = false;
931cdf0e10cSrcweir                 error = normalEOF;
932cdf0e10cSrcweir                 break;
933cdf0e10cSrcweir             case VVECTOR:
934cdf0e10cSrcweir                 keyword = token(fp,tokenlen);
935cdf0e10cSrcweir                 keyword = token(fp,tokenlen);
936cdf0e10cSrcweir                 break;
937cdf0e10cSrcweir             case NOPE:
938cdf0e10cSrcweir             default:
939cdf0e10cSrcweir                 error = parseError;
940cdf0e10cSrcweir                 break;
941cdf0e10cSrcweir         } /* switch */
942cdf0e10cSrcweir     } /* while */
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     if ((error == ok) && (count != fi->numOfChars))
945cdf0e10cSrcweir         error = reallocFontMetrics( (void**)&(fi->cmi), &(fi->numOfChars),
946cdf0e10cSrcweir                                     count, sizeof(CharMetricInfo) );
947cdf0e10cSrcweir 
948cdf0e10cSrcweir     if ((error == ok) && (count != fi->numOfChars))
949cdf0e10cSrcweir         error = parseError;
950cdf0e10cSrcweir 
951cdf0e10cSrcweir     return(error);
952cdf0e10cSrcweir 
953cdf0e10cSrcweir } /* parseCharMetrics */
954cdf0e10cSrcweir 
955cdf0e10cSrcweir 
956cdf0e10cSrcweir 
957cdf0e10cSrcweir /************************* parseTrackKernData ***********************/
958cdf0e10cSrcweir 
959cdf0e10cSrcweir /*  This function is called by "parseFile". It will parse the AFM file
960cdf0e10cSrcweir  *  up to the "EndTrackKern" or "EndKernData" keywords. It will save the
961cdf0e10cSrcweir  *  track kerning data if requested by the caller of parseFile.
962cdf0e10cSrcweir  *
963cdf0e10cSrcweir  *  parseTrackKernData is passed in a pointer to the FontInfo record.
964cdf0e10cSrcweir  *  If data is to be saved, the FontInfo record will already contain
965cdf0e10cSrcweir  *  a valid pointer to storage for the track kerning data.
966cdf0e10cSrcweir  *
967cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
968cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
969cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
970cdf0e10cSrcweir  */
971cdf0e10cSrcweir 
parseTrackKernData(FileInputStream * fp,FontInfo * fi)972c1e8cc3aSDon Lewis static int parseTrackKernData( FileInputStream* fp, FontInfo* fi)
973cdf0e10cSrcweir {
974cdf0e10cSrcweir     bool cont = true, save = (fi->tkd != NULL);
975cdf0e10cSrcweir     int pos = 0, error = ok, tcount = 0, tokenlen;
976c1e8cc3aSDon Lewis     char *keyword;
977cdf0e10cSrcweir 
978cdf0e10cSrcweir     while (cont)
979cdf0e10cSrcweir     {
980cdf0e10cSrcweir         keyword = token(fp,tokenlen);
981cdf0e10cSrcweir 
982cdf0e10cSrcweir         if (keyword == NULL)
983cdf0e10cSrcweir         {
984cdf0e10cSrcweir             error = earlyEOF;
985cdf0e10cSrcweir             break; /* get out of loop */
986cdf0e10cSrcweir         }
987cdf0e10cSrcweir         if (!save)
988cdf0e10cSrcweir             /* get tokens until the end of the Track Kerning Data */
989cdf0e10cSrcweir             /* section without saving any of the data */
990cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
991cdf0e10cSrcweir             {
992cdf0e10cSrcweir                 case ENDTRACKKERN:
993cdf0e10cSrcweir                 case ENDKERNDATA:
994cdf0e10cSrcweir                     cont = false;
995cdf0e10cSrcweir                     break;
996cdf0e10cSrcweir                 case ENDFONTMETRICS:
997cdf0e10cSrcweir                     cont = false;
998cdf0e10cSrcweir                     error = normalEOF;
999cdf0e10cSrcweir                     break;
1000cdf0e10cSrcweir                 default:
1001cdf0e10cSrcweir                     break;
1002cdf0e10cSrcweir             } /* switch */
1003cdf0e10cSrcweir         else
1004cdf0e10cSrcweir             /* otherwise parse entire Track Kerning Data section, */
1005cdf0e10cSrcweir             /* saving the data */
1006cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
1007cdf0e10cSrcweir             {
1008cdf0e10cSrcweir                 case COMMENT:
1009cdf0e10cSrcweir                     keyword = linetoken(fp);
1010cdf0e10cSrcweir                     break;
1011cdf0e10cSrcweir                 case TRACKKERN:
1012cdf0e10cSrcweir                     if (!(tcount < fi->numOfTracks))
1013cdf0e10cSrcweir                     {
1014cdf0e10cSrcweir                         reallocFontMetrics( (void**)&(fi->tkd), &(fi->numOfTracks),
1015cdf0e10cSrcweir                                             enlargeCount(fi->numOfTracks), sizeof(TrackKernData) );
1016cdf0e10cSrcweir                     }
1017cdf0e10cSrcweir 
1018cdf0e10cSrcweir                     if (tcount < fi->numOfTracks)
1019cdf0e10cSrcweir                     {
1020cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1021cdf0e10cSrcweir                             fi->tkd[pos].degree = atoi(keyword);
1022cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1023cdf0e10cSrcweir                             fi->tkd[pos].minPtSize = StringToDouble(keyword);
1024cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1025cdf0e10cSrcweir                             fi->tkd[pos].minKernAmt = StringToDouble(keyword);
1026cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1027cdf0e10cSrcweir                             fi->tkd[pos].maxPtSize = StringToDouble(keyword);
1028cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1029cdf0e10cSrcweir                             fi->tkd[pos++].maxKernAmt = StringToDouble(keyword);
1030cdf0e10cSrcweir                         tcount++;
1031cdf0e10cSrcweir                     }
1032cdf0e10cSrcweir                     else
1033cdf0e10cSrcweir                     {
1034cdf0e10cSrcweir                         error = parseError;
1035cdf0e10cSrcweir                         cont = false;
1036cdf0e10cSrcweir                     }
1037cdf0e10cSrcweir                     break;
1038cdf0e10cSrcweir                 case ENDTRACKKERN:
1039cdf0e10cSrcweir                 case ENDKERNDATA:
1040cdf0e10cSrcweir                     cont = false;
1041cdf0e10cSrcweir                     break;
1042cdf0e10cSrcweir                 case ENDFONTMETRICS:
1043cdf0e10cSrcweir                     cont = false;
1044cdf0e10cSrcweir                     error = normalEOF;
1045cdf0e10cSrcweir                     break;
1046cdf0e10cSrcweir                 case NOPE:
1047cdf0e10cSrcweir                 default:
1048cdf0e10cSrcweir                     error = parseError;
1049cdf0e10cSrcweir                     break;
1050cdf0e10cSrcweir             } /* switch */
1051cdf0e10cSrcweir     } /* while */
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir     if (error == ok && tcount != fi->numOfTracks)
1054cdf0e10cSrcweir         error = reallocFontMetrics( (void**)&(fi->tkd), &(fi->numOfTracks),
1055cdf0e10cSrcweir                                     tcount, sizeof(TrackKernData) );
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir     if (error == ok && tcount != fi->numOfTracks)
1058cdf0e10cSrcweir         error = parseError;
1059cdf0e10cSrcweir 
1060cdf0e10cSrcweir     return(error);
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir } /* parseTrackKernData */
1063cdf0e10cSrcweir 
1064cdf0e10cSrcweir 
1065cdf0e10cSrcweir /************************* parsePairKernData ************************/
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir /*  This function is called by "parseFile". It will parse the AFM file
1068cdf0e10cSrcweir  *  up to the "EndKernPairs" or "EndKernData" keywords. It will save
1069cdf0e10cSrcweir  *  the pair kerning data if requested by the caller of parseFile.
1070cdf0e10cSrcweir  *
1071cdf0e10cSrcweir  *  parsePairKernData is passed in a pointer to the FontInfo record.
1072cdf0e10cSrcweir  *  If data is to be saved, the FontInfo record will already contain
1073cdf0e10cSrcweir  *  a valid pointer to storage for the pair kerning data.
1074cdf0e10cSrcweir  *
1075cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
1076cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
1077cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
1078cdf0e10cSrcweir  */
1079cdf0e10cSrcweir 
parsePairKernData(FileInputStream * fp,FontInfo * fi)1080c1e8cc3aSDon Lewis static int parsePairKernData( FileInputStream* fp, FontInfo* fi)
1081cdf0e10cSrcweir {
1082cdf0e10cSrcweir     bool cont = true, save = (fi->pkd != NULL);
1083cdf0e10cSrcweir     int pos = 0, error = ok, pcount = 0, tokenlen;
1084c1e8cc3aSDon Lewis     char *keyword;
1085cdf0e10cSrcweir 
1086cdf0e10cSrcweir     while (cont)
1087cdf0e10cSrcweir     {
1088cdf0e10cSrcweir         keyword = token(fp,tokenlen);
1089cdf0e10cSrcweir 
1090cdf0e10cSrcweir         if (keyword == NULL)
1091cdf0e10cSrcweir         {
1092cdf0e10cSrcweir             error = earlyEOF;
1093cdf0e10cSrcweir             break; /* get out of loop */
1094cdf0e10cSrcweir         }
1095cdf0e10cSrcweir         if (!save)
1096cdf0e10cSrcweir             /* get tokens until the end of the Pair Kerning Data */
1097cdf0e10cSrcweir             /* section without saving any of the data */
1098cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
1099cdf0e10cSrcweir             {
1100cdf0e10cSrcweir                 case ENDKERNPAIRS:
1101cdf0e10cSrcweir                 case ENDKERNDATA:
1102cdf0e10cSrcweir                     cont = false;
1103cdf0e10cSrcweir                     break;
1104cdf0e10cSrcweir                 case ENDFONTMETRICS:
1105cdf0e10cSrcweir                     cont = false;
1106cdf0e10cSrcweir                     error = normalEOF;
1107cdf0e10cSrcweir                     break;
1108cdf0e10cSrcweir                 default:
1109cdf0e10cSrcweir                     break;
1110cdf0e10cSrcweir             } /* switch */
1111cdf0e10cSrcweir         else
1112cdf0e10cSrcweir             /* otherwise parse entire Pair Kerning Data section, */
1113cdf0e10cSrcweir             /* saving the data */
1114cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
1115cdf0e10cSrcweir             {
1116cdf0e10cSrcweir                 case COMMENT:
1117cdf0e10cSrcweir                     keyword = linetoken(fp);
1118cdf0e10cSrcweir                     break;
1119cdf0e10cSrcweir                 case KERNPAIR:
1120cdf0e10cSrcweir                     if (!(pcount < fi->numOfPairs))
1121cdf0e10cSrcweir                     {
1122cdf0e10cSrcweir                         reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
1123cdf0e10cSrcweir                                             enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
1124cdf0e10cSrcweir                     }
1125cdf0e10cSrcweir                     if (pcount < fi->numOfPairs)
1126cdf0e10cSrcweir                     {
1127cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1128cdf0e10cSrcweir                             fi->pkd[pos].name1 = strdup( keyword );
1129cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1130cdf0e10cSrcweir                             fi->pkd[pos].name2 = strdup( keyword );
1131cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1132cdf0e10cSrcweir                             fi->pkd[pos].xamt = atoi(keyword);
1133cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1134cdf0e10cSrcweir                             fi->pkd[pos++].yamt = atoi(keyword);
1135cdf0e10cSrcweir                         pcount++;
1136cdf0e10cSrcweir                     }
1137cdf0e10cSrcweir                     else
1138cdf0e10cSrcweir                     {
1139cdf0e10cSrcweir                         error = parseError;
1140cdf0e10cSrcweir                         cont = false;
1141cdf0e10cSrcweir                     }
1142cdf0e10cSrcweir                     break;
1143cdf0e10cSrcweir                 case KERNPAIRXAMT:
1144cdf0e10cSrcweir                     if (!(pcount < fi->numOfPairs))
1145cdf0e10cSrcweir                     {
1146cdf0e10cSrcweir                         reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
1147cdf0e10cSrcweir                                             enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
1148cdf0e10cSrcweir                     }
1149cdf0e10cSrcweir                     if (pcount < fi->numOfPairs)
1150cdf0e10cSrcweir                     {
1151cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1152cdf0e10cSrcweir                             fi->pkd[pos].name1 = strdup( keyword );
1153cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1154cdf0e10cSrcweir                             fi->pkd[pos].name2 = strdup( keyword );
1155cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1156cdf0e10cSrcweir                             fi->pkd[pos++].xamt = atoi(keyword);
1157cdf0e10cSrcweir                         pcount++;
1158cdf0e10cSrcweir                     }
1159cdf0e10cSrcweir                     else
1160cdf0e10cSrcweir                     {
1161cdf0e10cSrcweir                         error = parseError;
1162cdf0e10cSrcweir                         cont = false;
1163cdf0e10cSrcweir                     }
1164cdf0e10cSrcweir                     break;
1165cdf0e10cSrcweir                 case ENDKERNPAIRS:
1166cdf0e10cSrcweir                 case ENDKERNDATA:
1167cdf0e10cSrcweir                     cont = false;
1168cdf0e10cSrcweir                     break;
1169cdf0e10cSrcweir                 case ENDFONTMETRICS:
1170cdf0e10cSrcweir                     cont = false;
1171cdf0e10cSrcweir                     error = normalEOF;
1172cdf0e10cSrcweir                     break;
1173cdf0e10cSrcweir                 case NOPE:
1174cdf0e10cSrcweir                 default:
1175cdf0e10cSrcweir                     error = parseError;
1176cdf0e10cSrcweir                     break;
1177cdf0e10cSrcweir             } /* switch */
1178cdf0e10cSrcweir     } /* while */
1179cdf0e10cSrcweir 
1180cdf0e10cSrcweir     if ((error == ok) && (pcount != fi->numOfPairs))
1181cdf0e10cSrcweir         error = reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
1182cdf0e10cSrcweir                                     pcount, sizeof(PairKernData) );
1183cdf0e10cSrcweir 
1184cdf0e10cSrcweir     if (error == ok && pcount != fi->numOfPairs)
1185cdf0e10cSrcweir         error = parseError;
1186cdf0e10cSrcweir 
1187cdf0e10cSrcweir     return(error);
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir } /* parsePairKernData */
1190cdf0e10cSrcweir 
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir /************************* parseCompCharData **************************/
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir /*  This function is called by "parseFile". It will parse the AFM file
1195cdf0e10cSrcweir  *  up to the "EndComposites" keyword. It will save the composite
1196cdf0e10cSrcweir  *  character data if requested by the caller of parseFile.
1197cdf0e10cSrcweir  *
1198cdf0e10cSrcweir  *  parseCompCharData is passed in a pointer to the FontInfo record, and
1199cdf0e10cSrcweir  *  a boolean representing if the data should be saved.
1200cdf0e10cSrcweir  *
1201cdf0e10cSrcweir  *  This function will create the appropriate amount of storage for
1202cdf0e10cSrcweir  *  the composite character data and store a pointer to the storage
1203cdf0e10cSrcweir  *  in the FontInfo record.
1204cdf0e10cSrcweir  *
1205cdf0e10cSrcweir  *  This function returns an error code specifying whether there was
1206cdf0e10cSrcweir  *  a premature EOF or a parsing error. This return value is used by
1207cdf0e10cSrcweir  *  parseFile to determine if there is more file to parse.
1208cdf0e10cSrcweir  */
1209cdf0e10cSrcweir 
parseCompCharData(FileInputStream * fp,FontInfo * fi)1210c1e8cc3aSDon Lewis static int parseCompCharData( FileInputStream* fp, FontInfo* fi)
1211cdf0e10cSrcweir {
1212cdf0e10cSrcweir     bool cont = true, firstTime = true, save = (fi->ccd != NULL);
1213cdf0e10cSrcweir     int pos = 0, j = 0, error = ok, ccount = 0, pcount = 0, tokenlen;
1214c1e8cc3aSDon Lewis     char *keyword;
1215cdf0e10cSrcweir 
1216cdf0e10cSrcweir     while (cont)
1217cdf0e10cSrcweir     {
1218cdf0e10cSrcweir         keyword = token(fp,tokenlen);
1219cdf0e10cSrcweir         if (keyword == NULL)
1220cdf0e10cSrcweir             /* Have reached an early and unexpected EOF. */
1221cdf0e10cSrcweir             /* Set flag and stop parsing */
1222cdf0e10cSrcweir         {
1223cdf0e10cSrcweir             error = earlyEOF;
1224cdf0e10cSrcweir             break; /* get out of loop */
1225cdf0e10cSrcweir         }
1226cdf0e10cSrcweir         if (ccount > fi->numOfComps)
1227cdf0e10cSrcweir         {
1228cdf0e10cSrcweir             reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
1229cdf0e10cSrcweir                                 enlargeCount(fi->numOfComps), sizeof(CompCharData) );
1230cdf0e10cSrcweir         }
1231cdf0e10cSrcweir         if (ccount > fi->numOfComps)
1232cdf0e10cSrcweir         {
1233cdf0e10cSrcweir             error = parseError;
1234cdf0e10cSrcweir             break; /* get out of loop */
1235cdf0e10cSrcweir         }
1236cdf0e10cSrcweir         if (!save)
1237cdf0e10cSrcweir             /* get tokens until the end of the Composite Character info */
1238cdf0e10cSrcweir             /* section without saving any of the data */
1239cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
1240cdf0e10cSrcweir             {
1241cdf0e10cSrcweir                 case ENDCOMPOSITES:
1242cdf0e10cSrcweir                     cont = false;
1243cdf0e10cSrcweir                     break;
1244cdf0e10cSrcweir                 case ENDFONTMETRICS:
1245cdf0e10cSrcweir                     cont = false;
1246cdf0e10cSrcweir                     error = normalEOF;
1247cdf0e10cSrcweir                     break;
1248cdf0e10cSrcweir                 case COMMENT:
1249cdf0e10cSrcweir                 case COMPCHAR:
1250cdf0e10cSrcweir                     keyword = linetoken(fp);
1251cdf0e10cSrcweir                     break;
1252cdf0e10cSrcweir                 default:
1253cdf0e10cSrcweir                     break;
1254cdf0e10cSrcweir             } /* switch */
1255cdf0e10cSrcweir         else
1256cdf0e10cSrcweir             /* otherwise parse entire Composite Character info section, */
1257cdf0e10cSrcweir             /* saving the data */
1258cdf0e10cSrcweir             switch(recognize(keyword,tokenlen))
1259cdf0e10cSrcweir             {
1260cdf0e10cSrcweir                 case COMMENT:
1261cdf0e10cSrcweir                     keyword = linetoken(fp);
1262cdf0e10cSrcweir                     break;
1263cdf0e10cSrcweir                 case COMPCHAR:
1264cdf0e10cSrcweir                     if (!(ccount < fi->numOfComps))
1265cdf0e10cSrcweir                     {
1266cdf0e10cSrcweir                         reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
1267cdf0e10cSrcweir                                             enlargeCount(fi->numOfComps), sizeof(CompCharData) );
1268cdf0e10cSrcweir                     }
1269cdf0e10cSrcweir                     if (ccount < fi->numOfComps)
1270cdf0e10cSrcweir                     {
1271cdf0e10cSrcweir                         keyword = token(fp,tokenlen);
1272cdf0e10cSrcweir                         if (pcount != fi->ccd[pos].numOfPieces)
1273cdf0e10cSrcweir                             error = parseError;
1274cdf0e10cSrcweir                         pcount = 0;
1275cdf0e10cSrcweir                         if (firstTime) firstTime = false;
1276cdf0e10cSrcweir                         else pos++;
1277cdf0e10cSrcweir                         fi->ccd[pos].ccName = strdup( keyword );
1278cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1279cdf0e10cSrcweir                             fi->ccd[pos].numOfPieces = atoi(keyword);
1280cdf0e10cSrcweir                         fi->ccd[pos].pieces = (Pcc *)
1281cdf0e10cSrcweir                             calloc(fi->ccd[pos].numOfPieces, sizeof(Pcc));
1282cdf0e10cSrcweir                         j = 0;
1283cdf0e10cSrcweir                         ccount++;
1284cdf0e10cSrcweir                     }
1285cdf0e10cSrcweir                     else
1286cdf0e10cSrcweir                     {
1287cdf0e10cSrcweir                         error = parseError;
1288cdf0e10cSrcweir                         cont = false;
1289cdf0e10cSrcweir                     }
1290cdf0e10cSrcweir                     break;
1291cdf0e10cSrcweir                 case COMPCHARPIECE:
1292cdf0e10cSrcweir                     if (pcount < fi->ccd[pos].numOfPieces)
1293cdf0e10cSrcweir                     {
1294cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1295cdf0e10cSrcweir                             fi->ccd[pos].pieces[j].pccName = strdup( keyword );
1296cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1297cdf0e10cSrcweir                             fi->ccd[pos].pieces[j].deltax = atoi(keyword);
1298cdf0e10cSrcweir                         if ((keyword = token(fp,tokenlen)) != NULL)
1299cdf0e10cSrcweir                             fi->ccd[pos].pieces[j++].deltay = atoi(keyword);
1300cdf0e10cSrcweir                         pcount++;
1301cdf0e10cSrcweir                     }
1302cdf0e10cSrcweir                     else
1303cdf0e10cSrcweir                         error = parseError;
1304cdf0e10cSrcweir                     break;
1305cdf0e10cSrcweir                 case ENDCOMPOSITES:
1306cdf0e10cSrcweir                     cont = false;
1307cdf0e10cSrcweir                     break;
1308cdf0e10cSrcweir                 case ENDFONTMETRICS:
1309cdf0e10cSrcweir                     cont = false;
1310cdf0e10cSrcweir                     error = normalEOF;
1311cdf0e10cSrcweir                     break;
1312cdf0e10cSrcweir                 case NOPE:
1313cdf0e10cSrcweir                 default:
1314cdf0e10cSrcweir                     error = parseError;
1315cdf0e10cSrcweir                     break;
1316cdf0e10cSrcweir             } /* switch */
1317cdf0e10cSrcweir     } /* while */
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir     if (error == ok && ccount != fi->numOfComps)
1320cdf0e10cSrcweir         reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
1321cdf0e10cSrcweir                             ccount, sizeof(CompCharData) );
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir     if (error == ok && ccount != fi->numOfComps)
1324cdf0e10cSrcweir         error = parseError;
1325cdf0e10cSrcweir 
1326cdf0e10cSrcweir     return(error);
1327cdf0e10cSrcweir 
1328cdf0e10cSrcweir } /* parseCompCharData */
1329cdf0e10cSrcweir 
1330cdf0e10cSrcweir 
1331cdf0e10cSrcweir 
1332cdf0e10cSrcweir 
1333cdf0e10cSrcweir /*************************** 'PUBLIC' FUNCTION ********************/
1334cdf0e10cSrcweir 
1335cdf0e10cSrcweir 
1336cdf0e10cSrcweir /*************************** parseFile *****************************/
1337cdf0e10cSrcweir 
1338cdf0e10cSrcweir /*  parseFile is the only 'public' procedure available. It is called
1339cdf0e10cSrcweir  *  from an application wishing to get information from an AFM file.
1340cdf0e10cSrcweir  *  The caller of this function is responsible for locating and opening
1341cdf0e10cSrcweir  *  an AFM file and handling all errors associated with that task.
1342cdf0e10cSrcweir  *
1343cdf0e10cSrcweir  *  parseFile expects 3 parameters: a filename pointer, a pointer
1344cdf0e10cSrcweir  *  to a (FontInfo *) variable (for which storage will be allocated and
1345cdf0e10cSrcweir  *  the data requested filled in), and a mask specifying which
1346cdf0e10cSrcweir  *  data from the AFM file should be saved in the FontInfo structure.
1347cdf0e10cSrcweir  *
1348cdf0e10cSrcweir  *  The file will be parsed and the requested data will be stored in
1349cdf0e10cSrcweir  *  a record of type FontInfo (refer to ParseAFM.h).
1350cdf0e10cSrcweir  *
1351cdf0e10cSrcweir  *  parseFile returns an error code as defined in parseAFM.h.
1352cdf0e10cSrcweir  *
1353cdf0e10cSrcweir  *  The position of the read/write pointer associated with the file
1354cdf0e10cSrcweir  *  pointer upon return of this function is undefined.
1355cdf0e10cSrcweir  */
1356cdf0e10cSrcweir 
parseFile(const char * pFilename,FontInfo ** fi,FLAGS flags)1357cdf0e10cSrcweir int parseFile( const char* pFilename, FontInfo** fi, FLAGS flags)
1358cdf0e10cSrcweir {
1359cdf0e10cSrcweir     FileInputStream aFile( pFilename );
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir     int code = ok;  /* return code from each of the parsing routines */
1362cdf0e10cSrcweir     int error = ok; /* used as the return code from this function */
1363cdf0e10cSrcweir     int tokenlen;
1364cdf0e10cSrcweir 
1365c1e8cc3aSDon Lewis     char *keyword; /* used to store a token */
1366cdf0e10cSrcweir 
1367cdf0e10cSrcweir 
1368cdf0e10cSrcweir     (*fi) = (FontInfo *) calloc(1, sizeof(FontInfo));
1369cdf0e10cSrcweir     if ((*fi) == NULL) {error = storageProblem; return(error);}
1370cdf0e10cSrcweir 
1371cdf0e10cSrcweir     if (flags & P_G)
1372cdf0e10cSrcweir     {
1373cdf0e10cSrcweir         (*fi)->gfi = (GlobalFontInfo *) calloc(1, sizeof(GlobalFontInfo));
1374cdf0e10cSrcweir         if ((*fi)->gfi == NULL) {error = storageProblem; return(error);}
1375cdf0e10cSrcweir     }
1376cdf0e10cSrcweir 
1377cdf0e10cSrcweir     /* The AFM file begins with Global Font Information. This section */
1378cdf0e10cSrcweir     /* will be parsed whether or not information should be saved. */
1379cdf0e10cSrcweir     code = parseGlobals(&aFile, (*fi)->gfi);
1380cdf0e10cSrcweir 
1381cdf0e10cSrcweir     if (code < 0) error = code;
1382cdf0e10cSrcweir 
1383cdf0e10cSrcweir     /* The Global Font Information is followed by the Character Metrics */
1384cdf0e10cSrcweir     /* section. Which procedure is used to parse this section depends on */
1385cdf0e10cSrcweir     /* how much information should be saved. If all of the metrics info */
1386cdf0e10cSrcweir     /* is wanted, parseCharMetrics is called. If only the character widths */
1387cdf0e10cSrcweir     /* is wanted, parseCharWidths is called. parseCharWidths will also */
1388cdf0e10cSrcweir     /* be called in the case that no character data is to be saved, just */
1389cdf0e10cSrcweir     /* to parse through the section. */
1390cdf0e10cSrcweir 
1391cdf0e10cSrcweir     if ((code != normalEOF) && (code != earlyEOF))
1392cdf0e10cSrcweir     {
1393cdf0e10cSrcweir         if ((keyword = token(&aFile,tokenlen)) != NULL)
1394cdf0e10cSrcweir             (*fi)->numOfChars = atoi(keyword);
1395cdf0e10cSrcweir         if (flags & (P_M ^ P_W))
1396cdf0e10cSrcweir         {
1397cdf0e10cSrcweir             (*fi)->cmi = (CharMetricInfo *)
1398cdf0e10cSrcweir                 calloc((*fi)->numOfChars, sizeof(CharMetricInfo));
1399cdf0e10cSrcweir             if ((*fi)->cmi == NULL) {error = storageProblem; return(error);}
1400cdf0e10cSrcweir             code = parseCharMetrics(&aFile, *fi);
1401cdf0e10cSrcweir         }
1402cdf0e10cSrcweir         else
1403cdf0e10cSrcweir         {
1404cdf0e10cSrcweir             if (flags & P_W)
1405cdf0e10cSrcweir             {
1406cdf0e10cSrcweir                 (*fi)->cwi = (int *) calloc(256, sizeof(int));
1407cdf0e10cSrcweir                 if ((*fi)->cwi == NULL)
1408cdf0e10cSrcweir                 {
1409cdf0e10cSrcweir                     error = storageProblem;
1410cdf0e10cSrcweir                     return(error);
1411cdf0e10cSrcweir                 }
1412cdf0e10cSrcweir             }
1413cdf0e10cSrcweir             /* parse section regardless */
1414cdf0e10cSrcweir             code = parseCharWidths(&aFile, (*fi)->cwi);
1415cdf0e10cSrcweir         } /* else */
1416cdf0e10cSrcweir     } /* if */
1417cdf0e10cSrcweir 
1418cdf0e10cSrcweir     if ((error != earlyEOF) && (code < 0)) error = code;
1419cdf0e10cSrcweir 
1420cdf0e10cSrcweir     /* The remaining sections of the AFM are optional. This code will */
1421cdf0e10cSrcweir     /* look at the next keyword in the file to determine what section */
1422cdf0e10cSrcweir     /* is next, and then allocate the appropriate amount of storage */
1423cdf0e10cSrcweir     /* for the data (if the data is to be saved) and call the */
1424cdf0e10cSrcweir     /* appropriate parsing routine to parse the section. */
1425cdf0e10cSrcweir 
1426cdf0e10cSrcweir     while ((code != normalEOF) && (code != earlyEOF))
1427cdf0e10cSrcweir     {
1428cdf0e10cSrcweir         keyword = token(&aFile,tokenlen);
1429cdf0e10cSrcweir         if (keyword == NULL)
1430cdf0e10cSrcweir             /* Have reached an early and unexpected EOF. */
1431cdf0e10cSrcweir             /* Set flag and stop parsing */
1432cdf0e10cSrcweir         {
1433cdf0e10cSrcweir             code = earlyEOF;
1434cdf0e10cSrcweir             break; /* get out of loop */
1435cdf0e10cSrcweir         }
1436cdf0e10cSrcweir         switch(recognize(keyword,tokenlen))
1437cdf0e10cSrcweir         {
1438cdf0e10cSrcweir             case STARTKERNDATA:
1439cdf0e10cSrcweir                 break;
1440cdf0e10cSrcweir             case ENDKERNDATA:
1441cdf0e10cSrcweir                 break;
1442cdf0e10cSrcweir             case STARTTRACKKERN:
1443cdf0e10cSrcweir                 keyword = token(&aFile,tokenlen);
1444cdf0e10cSrcweir                 if ((flags & P_T) && keyword)
1445cdf0e10cSrcweir                 {
1446cdf0e10cSrcweir                     (*fi)->numOfTracks = atoi(keyword);
1447cdf0e10cSrcweir                     (*fi)->tkd = (TrackKernData *)
1448cdf0e10cSrcweir                         calloc((*fi)->numOfTracks, sizeof(TrackKernData));
1449cdf0e10cSrcweir                     if ((*fi)->tkd == NULL)
1450cdf0e10cSrcweir                     {
1451cdf0e10cSrcweir                         error = storageProblem;
1452cdf0e10cSrcweir                         return(error);
1453cdf0e10cSrcweir                     }
1454cdf0e10cSrcweir                 } /* if */
1455cdf0e10cSrcweir                 code = parseTrackKernData(&aFile, *fi);
1456cdf0e10cSrcweir                 break;
1457cdf0e10cSrcweir             case STARTKERNPAIRS:
1458cdf0e10cSrcweir                 keyword = token(&aFile,tokenlen);
1459cdf0e10cSrcweir                 if ((flags & P_P) && keyword)
1460cdf0e10cSrcweir                 {
1461cdf0e10cSrcweir                     (*fi)->numOfPairs = atoi(keyword);
1462cdf0e10cSrcweir                     (*fi)->pkd = (PairKernData *)
1463cdf0e10cSrcweir                         calloc((*fi)->numOfPairs, sizeof(PairKernData));
1464cdf0e10cSrcweir                     if ((*fi)->pkd == NULL)
1465cdf0e10cSrcweir                     {
1466cdf0e10cSrcweir                         error = storageProblem;
1467cdf0e10cSrcweir                         return(error);
1468cdf0e10cSrcweir                     }
1469cdf0e10cSrcweir                 } /* if */
1470cdf0e10cSrcweir                 code = parsePairKernData(&aFile, *fi);
1471cdf0e10cSrcweir                 break;
1472cdf0e10cSrcweir             case STARTCOMPOSITES:
1473cdf0e10cSrcweir                 keyword = token(&aFile,tokenlen);
1474cdf0e10cSrcweir                 if ((flags & P_C) && keyword)
1475cdf0e10cSrcweir                 {
1476cdf0e10cSrcweir                     (*fi)->numOfComps = atoi(keyword);
1477cdf0e10cSrcweir                     (*fi)->ccd = (CompCharData *)
1478cdf0e10cSrcweir                         calloc((*fi)->numOfComps, sizeof(CompCharData));
1479cdf0e10cSrcweir                     if ((*fi)->ccd == NULL)
1480cdf0e10cSrcweir                     {
1481cdf0e10cSrcweir                         error = storageProblem;
1482cdf0e10cSrcweir                         return(error);
1483cdf0e10cSrcweir                     }
1484cdf0e10cSrcweir                 } /* if */
1485cdf0e10cSrcweir                 code = parseCompCharData(&aFile, *fi);
1486cdf0e10cSrcweir                 break;
1487cdf0e10cSrcweir             case ENDFONTMETRICS:
1488cdf0e10cSrcweir                 code = normalEOF;
1489cdf0e10cSrcweir                 break;
1490cdf0e10cSrcweir             case COMMENT:
1491cdf0e10cSrcweir                 linetoken(&aFile);
1492cdf0e10cSrcweir                 break;
1493cdf0e10cSrcweir             case NOPE:
1494cdf0e10cSrcweir             default:
1495cdf0e10cSrcweir                 code = parseError;
1496cdf0e10cSrcweir                 break;
1497cdf0e10cSrcweir         } /* switch */
1498cdf0e10cSrcweir 
1499cdf0e10cSrcweir         if ((error != earlyEOF) && (code < 0)) error = code;
1500cdf0e10cSrcweir 
1501cdf0e10cSrcweir     } /* while */
1502cdf0e10cSrcweir 
1503cdf0e10cSrcweir     if ((error != earlyEOF) && (code < 0)) error = code;
1504cdf0e10cSrcweir 
1505cdf0e10cSrcweir     return(error);
1506cdf0e10cSrcweir 
1507cdf0e10cSrcweir } /* parseFile */
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir void
freeFontInfo(FontInfo * fi)1510cdf0e10cSrcweir freeFontInfo (FontInfo *fi)
1511cdf0e10cSrcweir {
1512cdf0e10cSrcweir     int i, j;
1513cdf0e10cSrcweir 
1514cdf0e10cSrcweir     if (fi->gfi)
1515cdf0e10cSrcweir     {
1516cdf0e10cSrcweir         free (fi->gfi->afmVersion);
1517cdf0e10cSrcweir         free (fi->gfi->fontName);
1518cdf0e10cSrcweir         free (fi->gfi->fullName);
1519cdf0e10cSrcweir         free (fi->gfi->familyName);
1520cdf0e10cSrcweir         free (fi->gfi->weight);
1521cdf0e10cSrcweir         free (fi->gfi->version);
1522cdf0e10cSrcweir         free (fi->gfi->notice);
1523cdf0e10cSrcweir         free (fi->gfi->encodingScheme);
1524cdf0e10cSrcweir         free (fi->gfi);
1525cdf0e10cSrcweir     }
1526cdf0e10cSrcweir 
1527cdf0e10cSrcweir     free (fi->cwi);
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir     if (fi->cmi)
1530cdf0e10cSrcweir     {
1531cdf0e10cSrcweir         for (i = 0; i < fi->numOfChars; i++)
1532cdf0e10cSrcweir         {
1533cdf0e10cSrcweir             Ligature *ligs;
1534cdf0e10cSrcweir             free (fi->cmi[i].name);
1535cdf0e10cSrcweir             ligs = fi->cmi[i].ligs;
1536cdf0e10cSrcweir             while (ligs)
1537cdf0e10cSrcweir             {
1538cdf0e10cSrcweir                 Ligature *tmp;
1539cdf0e10cSrcweir                 tmp = ligs;
1540cdf0e10cSrcweir                 ligs = ligs->next;
1541cdf0e10cSrcweir                 free (tmp->succ);
1542cdf0e10cSrcweir                 free (tmp->lig);
1543cdf0e10cSrcweir                 free (tmp);
1544cdf0e10cSrcweir             }
1545cdf0e10cSrcweir         }
1546cdf0e10cSrcweir         free (fi->cmi);
1547cdf0e10cSrcweir     }
1548cdf0e10cSrcweir 
1549cdf0e10cSrcweir     free (fi->tkd);
1550cdf0e10cSrcweir 
1551cdf0e10cSrcweir     if (fi->pkd)
1552cdf0e10cSrcweir     {
1553cdf0e10cSrcweir         for ( i = 0; i < fi->numOfPairs; i++)
1554cdf0e10cSrcweir         {
1555cdf0e10cSrcweir             free (fi->pkd[i].name1);
1556cdf0e10cSrcweir             free (fi->pkd[i].name2);
1557cdf0e10cSrcweir         }
1558cdf0e10cSrcweir         free (fi->pkd);
1559cdf0e10cSrcweir     }
1560cdf0e10cSrcweir 
1561cdf0e10cSrcweir     if (fi->ccd)
1562cdf0e10cSrcweir     {
1563cdf0e10cSrcweir         for (i = 0; i < fi->numOfComps; i++)
1564cdf0e10cSrcweir         {
1565cdf0e10cSrcweir             free (fi->ccd[i].ccName);
1566cdf0e10cSrcweir             for (j = 0; j < fi->ccd[i].numOfPieces; j++)
1567cdf0e10cSrcweir                 free (fi->ccd[i].pieces[j].pccName);
1568cdf0e10cSrcweir 
1569cdf0e10cSrcweir             free (fi->ccd[i].pieces);
1570cdf0e10cSrcweir         }
1571cdf0e10cSrcweir         free (fi->ccd);
1572cdf0e10cSrcweir     }
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir     free (fi);
1575cdf0e10cSrcweir }
1576cdf0e10cSrcweir 
1577e4384c19SJohn Bampton } // namespace
1578