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