~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to .pc/03_CVE-2010-264x.patch/backend/dvi/mdvi-lib/afmparse.c

  • Committer: Bazaar Package Importer
  • Author(s): Rodrigo Moya, Josselin Mouette, Rodrigo Moya
  • Date: 2011-05-19 12:12:42 UTC
  • mfrom: (1.1.65 upstream) (1.3.6 experimental)
  • Revision ID: james.westby@ubuntu.com-20110519121242-967hbn2nh2hunp4y
Tags: 3.0.0-4ubuntu1
[ Josselin Mouette ]
* bug-presubj: please document where to report rendering bugs.
* evince.mime: dropped. We have desktop files to handle MIME 
  associations, no need to maintain an alternate system by hand.
  Closes: #619564, #627027, #551734, #581441.

[ Rodrigo Moya ]
* Rebase from Debian and GNOME3 PPA (thanks to Rico Tzschichholz).
  Remaining Ubuntu changes:
* debian/apparmor-profile:
* debian/apparmor-profile.abstraction:
* debian/evince.apport:
* debian/evince-common.dirs:
* debian/evince-common.postinst:
* debian/evince-common.postrm:
  - Add apparmor profile
* debian/control:
  - Build-Depend on debhelper (>= 7.4.20ubuntu5), gnome-common,
    hardening-includes and liblaunchpad-integration-3.0-dev
  - Standards-Version is 3.9.1
  - Depend on apparmor
* debian/rules:
  - Include hardening.make
  - Add rule to install apparmor files
* debian/watch:
  - Watch unstable series
* debian/patches/01_lpi.patch:
  - Launchpad integration patch
* debian/patches/04_gold.patch:
  - Link against libz
* debian/patches/05_library-path.patch:
  - Fix library path for g-ir-scanner

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * (C) 1988, 1989, 1990 by Adobe Systems Incorporated. All rights reserved.
3
 
 *
4
 
 * This file may be freely copied and redistributed as long as:
5
 
 *   1) This entire notice continues to be included in the file, 
6
 
 *   2) If the file has been modified in any way, a notice of such
7
 
 *      modification is conspicuously indicated.
8
 
 *
9
 
 * PostScript, Display PostScript, and Adobe are registered trademarks of
10
 
 * Adobe Systems Incorporated.
11
 
 * 
12
 
 * ************************************************************************
13
 
 * THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
14
 
 * NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
15
 
 * INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR 
16
 
 * LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY 
17
 
 * KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION, 
18
 
 * AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
19
 
 * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
20
 
 * ************************************************************************
21
 
 */
22
 
 
23
 
/* 
24
 
 * modified for MDVI:
25
 
 *   - some names changed to avoid conflicts with T1lib
26
 
 *   - changed to ANSI C prototypes, as used by MDVI
27
 
 * mal - 3/01
28
 
 */
29
 
 
30
 
/* parseAFM.c
31
 
 * 
32
 
 * This file is used in conjuction with the parseAFM.h header file.
33
 
 * This file contains several procedures that are used to parse AFM
34
 
 * files. It is intended to work with an application program that needs
35
 
 * font metric information. The program can be used as is by making a
36
 
 * procedure call to "parseFile" (passing in the expected parameters)
37
 
 * and having it fill in a data structure with the data from the 
38
 
 * AFM file, or an application developer may wish to customize this
39
 
 * code.
40
 
 *
41
 
 * There is also a file, parseAFMclient.c, that is a sample application
42
 
 * showing how to call the "parseFile" procedure and how to use the data
43
 
 * after "parseFile" has returned.
44
 
 *
45
 
 * Please read the comments in parseAFM.h and parseAFMclient.c.
46
 
 *
47
 
 * History:
48
 
 *      original: DSM  Thu Oct 20 17:39:59 PDT 1988
49
 
 *  modified: DSM  Mon Jul  3 14:17:50 PDT 1989
50
 
 *    - added 'storageProblem' return code
51
 
 *        - fixed bug of not allocating extra byte for string duplication
52
 
 *    - fixed typos
53
 
 *  modified: DSM  Tue Apr  3 11:18:34 PDT 1990
54
 
 *    - added free(ident) at end of parseFile routine
55
 
 *  modified: DSM  Tue Jun 19 10:16:29 PDT 1990
56
 
 *    - changed (width == 250) to (width = 250) in initializeArray
57
 
 */
58
 
 
59
 
#include <config.h>
60
 
#include "sysdeps.h"
61
 
 
62
 
#ifdef WITH_AFM_FILES
63
 
 
64
 
#include <stdlib.h> /* added for MDVI */
65
 
#include <string.h> /* added for MDVI */
66
 
 
67
 
#include <stdio.h>
68
 
#include <errno.h>
69
 
#include <sys/file.h>
70
 
#include <math.h>
71
 
#include "afmparse.h"
72
 
#undef VERSION
73
 
 
74
 
#define lineterm EOL    /* line terminating character */
75
 
#define normalEOF 1     /* return code from parsing routines used only */
76
 
                        /* in this module */
77
 
#define Space "space"   /* used in string comparison to look for the width */
78
 
                        /* of the space character to init the widths array */
79
 
#define False "false"   /* used in string comparison to check the value of */
80
 
                        /* boolean keys (e.g. IsFixedPitch)  */
81
 
 
82
 
#define MATCH(A,B)              (strncmp((A),(B), MAX_NAME) == 0)
83
 
 
84
 
 
85
 
 
86
 
/*************************** GLOBALS ***********************/
87
 
 
88
 
static char *ident = NULL; /* storage buffer for keywords */
89
 
 
90
 
 
91
 
/* "shorts" for fast case statement 
92
 
 * The values of each of these enumerated items correspond to an entry in the
93
 
 * table of strings defined below. Therefore, if you add a new string as 
94
 
 * new keyword into the keyStrings table, you must also add a corresponding
95
 
 * parseKey AND it MUST be in the same position!
96
 
 *
97
 
 * IMPORTANT: since the sorting algorithm is a binary search, the strings of
98
 
 * keywords must be placed in lexicographical order, below. [Therefore, the 
99
 
 * enumerated items are not necessarily in lexicographical order, depending 
100
 
 * on the name chosen. BUT, they must be placed in the same position as the 
101
 
 * corresponding key string.] The NOPE shall remain in the last position, 
102
 
 * since it does not correspond to any key string, and it is used in the 
103
 
 * "recognize" procedure to calculate how many possible keys there are.
104
 
 */
105
 
 
106
 
enum parseKey {
107
 
  ASCENDER, CHARBBOX, CODE, COMPCHAR, CAPHEIGHT, COMMENT, 
108
 
  DESCENDER, ENCODINGSCHEME, ENDCHARMETRICS, ENDCOMPOSITES, 
109
 
  ENDFONTMETRICS, ENDKERNDATA, ENDKERNPAIRS, ENDTRACKKERN, 
110
 
  FAMILYNAME, FONTBBOX, FONTNAME, FULLNAME, ISFIXEDPITCH, 
111
 
  ITALICANGLE, KERNPAIR, KERNPAIRXAMT, LIGATURE, CHARNAME, 
112
 
  NOTICE, COMPCHARPIECE, STARTCHARMETRICS, STARTCOMPOSITES, 
113
 
  STARTFONTMETRICS, STARTKERNDATA, STARTKERNPAIRS, 
114
 
  STARTTRACKKERN, TRACKKERN, UNDERLINEPOSITION, 
115
 
  UNDERLINETHICKNESS, VERSION, XYWIDTH, XWIDTH, WEIGHT, XHEIGHT,
116
 
  NOPE } ;
117
 
 
118
 
/* keywords for the system:  
119
 
 * This a table of all of the current strings that are vaild AFM keys.
120
 
 * Each entry can be referenced by the appropriate parseKey value (an
121
 
 * enumerated data type defined above). If you add a new keyword here, 
122
 
 * a corresponding parseKey MUST be added to the enumerated data type
123
 
 * defined above, AND it MUST be added in the same position as the 
124
 
 * string is in this table.
125
 
 *
126
 
 * IMPORTANT: since the sorting algorithm is a binary search, the keywords
127
 
 * must be placed in lexicographical order. And, NULL should remain at the
128
 
 * end.
129
 
 */
130
 
 
131
 
static char *keyStrings[] = {
132
 
  "Ascender", "B", "C", "CC", "CapHeight", "Comment",
133
 
  "Descender", "EncodingScheme", "EndCharMetrics", "EndComposites", 
134
 
  "EndFontMetrics", "EndKernData", "EndKernPairs", "EndTrackKern", 
135
 
  "FamilyName", "FontBBox", "FontName", "FullName", "IsFixedPitch", 
136
 
  "ItalicAngle", "KP", "KPX", "L", "N", 
137
 
  "Notice", "PCC", "StartCharMetrics", "StartComposites", 
138
 
  "StartFontMetrics", "StartKernData", "StartKernPairs", 
139
 
  "StartTrackKern", "TrackKern", "UnderlinePosition", 
140
 
  "UnderlineThickness", "Version", "W", "WX", "Weight", "XHeight",
141
 
  NULL };
142
 
  
143
 
/*************************** PARSING ROUTINES **************/ 
144
 
  
145
 
/*************************** token *************************/
146
 
 
147
 
/*  A "AFM File Conventions" tokenizer. That means that it will
148
 
 *  return the next token delimited by white space.  See also
149
 
 *  the `linetoken' routine, which does a similar thing but 
150
 
 *  reads all tokens until the next end-of-line.
151
 
 */
152
 
 
153
 
static char *token(FILE *stream)
154
 
{
155
 
    int ch, idx;
156
 
 
157
 
    /* skip over white space */
158
 
    while ((ch = fgetc(stream)) == ' ' || ch == lineterm || 
159
 
            ch == ',' || ch == '\t' || ch == ';');
160
 
    
161
 
    idx = 0;
162
 
    while (ch != EOF && ch != ' ' && ch != lineterm 
163
 
           && ch != '\t' && ch != ':' && ch != ';') 
164
 
    {
165
 
        ident[idx++] = ch;
166
 
        ch = fgetc(stream);
167
 
    } /* while */
168
 
 
169
 
    if (ch == EOF && idx < 1) return ((char *)NULL);
170
 
    if (idx >= 1 && ch != ':' ) ungetc(ch, stream);
171
 
    if (idx < 1 ) ident[idx++] = ch;    /* single-character token */
172
 
    ident[idx] = 0;
173
 
    
174
 
    return(ident);      /* returns pointer to the token */
175
 
 
176
 
} /* token */
177
 
 
178
 
 
179
 
/*************************** linetoken *************************/
180
 
 
181
 
/*  "linetoken" will get read all tokens until the EOL character from
182
 
 *  the given stream.  This is used to get any arguments that can be
183
 
 *  more than one word (like Comment lines and FullName).
184
 
 */
185
 
 
186
 
static char *linetoken(FILE *stream)
187
 
{
188
 
    int ch, idx;
189
 
 
190
 
    while ((ch = fgetc(stream)) == ' ' || ch == '\t' ); 
191
 
    
192
 
    idx = 0;
193
 
    while (ch != EOF && ch != lineterm) 
194
 
    {
195
 
        ident[idx++] = ch;
196
 
        ch = fgetc(stream);
197
 
    } /* while */
198
 
    
199
 
    ungetc(ch, stream);
200
 
    ident[idx] = 0;
201
 
 
202
 
    return(ident);      /* returns pointer to the token */
203
 
 
204
 
} /* linetoken */
205
 
 
206
 
 
207
 
/*************************** recognize *************************/
208
 
 
209
 
/*  This function tries to match a string to a known list of
210
 
 *  valid AFM entries (check the keyStrings array above). 
211
 
 *  "ident" contains everything from white space through the
212
 
 *  next space, tab, or ":" character.
213
 
 *
214
 
 *  The algorithm is a standard Knuth binary search.
215
 
 */
216
 
 
217
 
static enum parseKey recognize(char *ident)
218
 
{
219
 
    int lower = 0, upper = (int) NOPE, midpoint, cmpvalue;
220
 
    BOOL found = FALSE;
221
 
 
222
 
    while ((upper >= lower) && !found)
223
 
    {
224
 
        midpoint = (lower + upper)/2;
225
 
        if (keyStrings[midpoint] == NULL) break;
226
 
        cmpvalue = strncmp(ident, keyStrings[midpoint], MAX_NAME);
227
 
        if (cmpvalue == 0) found = TRUE;
228
 
        else if (cmpvalue < 0) upper = midpoint - 1;
229
 
        else lower = midpoint + 1;
230
 
    } /* while */
231
 
 
232
 
    if (found) return (enum parseKey) midpoint;
233
 
    else return NOPE;
234
 
    
235
 
} /* recognize */
236
 
 
237
 
 
238
 
/************************* parseGlobals *****************************/
239
 
 
240
 
/*  This function is called by "parseFile". It will parse the AFM File
241
 
 *  up to the "StartCharMetrics" keyword, which essentially marks the
242
 
 *  end of the Global Font Information and the beginning of the character
243
 
 *  metrics information. 
244
 
 *
245
 
 *  If the caller of "parseFile" specified that it wanted the Global
246
 
 *  Font Information (as defined by the "AFM File Specification"
247
 
 *  document), then that information will be stored in the returned 
248
 
 *  data structure.
249
 
 *
250
 
 *  Any Global Font Information entries that are not found in a 
251
 
 *  given file, will have the usual default initialization value
252
 
 *  for its type (i.e. entries of type int will be 0, etc).
253
 
 *
254
 
 *  This function returns an error code specifying whether there was 
255
 
 *  a premature EOF or a parsing error. This return value is used by 
256
 
 *  parseFile to determine if there is more file to parse.
257
 
 */
258
 
 
259
 
static BOOL parseGlobals(FILE *fp, GlobalFontInfo *gfi)
260
 
{  
261
 
    BOOL cont = TRUE, save = (gfi != NULL);
262
 
    int error = ok;
263
 
    register char *keyword;
264
 
    
265
 
    while (cont)
266
 
    {
267
 
        keyword = token(fp);
268
 
        
269
 
        if (keyword == NULL)
270
 
          /* Have reached an early and unexpected EOF. */
271
 
          /* Set flag and stop parsing */
272
 
        {
273
 
            error = earlyEOF;
274
 
            break;   /* get out of loop */
275
 
        }
276
 
        if (!save)      
277
 
          /* get tokens until the end of the Global Font info section */
278
 
          /* without saving any of the data */
279
 
            switch (recognize(keyword))  
280
 
            {                           
281
 
                case STARTCHARMETRICS:
282
 
                    cont = FALSE;
283
 
                    break;
284
 
                case ENDFONTMETRICS:    
285
 
                    cont = FALSE;
286
 
                    error = normalEOF;
287
 
                    break;
288
 
                default:
289
 
                    break;
290
 
            } /* switch */
291
 
        else
292
 
          /* otherwise parse entire global font info section, */
293
 
          /* saving the data */
294
 
            switch(recognize(keyword))
295
 
            {
296
 
                case STARTFONTMETRICS:
297
 
                    keyword = token(fp);
298
 
                    gfi->afmVersion = (char *) malloc(strlen(keyword) + 1);
299
 
                    strcpy(gfi->afmVersion, keyword);
300
 
                    break;
301
 
                case COMMENT:
302
 
                    keyword = linetoken(fp);
303
 
                    break;
304
 
                case FONTNAME:
305
 
                    keyword = token(fp);
306
 
                    gfi->fontName = (char *) malloc(strlen(keyword) + 1);
307
 
                    strcpy(gfi->fontName, keyword);
308
 
                    break;
309
 
                case ENCODINGSCHEME:
310
 
                    keyword = token(fp);
311
 
                    gfi->encodingScheme = (char *) 
312
 
                        malloc(strlen(keyword) + 1);
313
 
                    strcpy(gfi->encodingScheme, keyword);
314
 
                    break; 
315
 
                case FULLNAME:
316
 
                    keyword = linetoken(fp);
317
 
                    gfi->fullName = (char *) malloc(strlen(keyword) + 1);
318
 
                    strcpy(gfi->fullName, keyword);
319
 
                    break; 
320
 
                case FAMILYNAME:           
321
 
                   keyword = linetoken(fp);
322
 
                    gfi->familyName = (char *) malloc(strlen(keyword) + 1);
323
 
                    strcpy(gfi->familyName, keyword);
324
 
                    break; 
325
 
                case WEIGHT:
326
 
                    keyword = token(fp);
327
 
                    gfi->weight = (char *) malloc(strlen(keyword) + 1);
328
 
                    strcpy(gfi->weight, keyword);
329
 
                    break;
330
 
                case ITALICANGLE:
331
 
                    keyword = token(fp);
332
 
                    gfi->italicAngle = atof(keyword);
333
 
                    if (errno == ERANGE) error = parseError;
334
 
                    break;
335
 
                case ISFIXEDPITCH:
336
 
                    keyword = token(fp);
337
 
                    if (MATCH(keyword, False))
338
 
                        gfi->isFixedPitch = 0;
339
 
                    else 
340
 
                        gfi->isFixedPitch = 1;
341
 
                    break; 
342
 
                    case UNDERLINEPOSITION:
343
 
                    keyword = token(fp);
344
 
                        gfi->underlinePosition = atoi(keyword);
345
 
                    break; 
346
 
                case UNDERLINETHICKNESS:
347
 
                    keyword = token(fp);
348
 
                    gfi->underlineThickness = atoi(keyword);
349
 
                    break;
350
 
                case VERSION:
351
 
                    keyword = token(fp);
352
 
                    gfi->version = (char *) malloc(strlen(keyword) + 1);
353
 
                    strcpy(gfi->version, keyword);
354
 
                    break; 
355
 
                case NOTICE:
356
 
                    keyword = linetoken(fp);
357
 
                    gfi->notice = (char *) malloc(strlen(keyword) + 1);
358
 
                    strcpy(gfi->notice, keyword);
359
 
                    break; 
360
 
                case FONTBBOX:
361
 
                    keyword = token(fp);
362
 
                    gfi->fontBBox.llx = atoi(keyword);
363
 
                    keyword = token(fp);
364
 
                    gfi->fontBBox.lly = atoi(keyword);
365
 
                    keyword = token(fp);
366
 
                    gfi->fontBBox.urx = atoi(keyword);
367
 
                    keyword = token(fp);
368
 
                    gfi->fontBBox.ury = atoi(keyword);
369
 
                    break;
370
 
                case CAPHEIGHT:
371
 
                    keyword = token(fp);
372
 
                    gfi->capHeight = atoi(keyword);
373
 
                    break;
374
 
                case XHEIGHT:
375
 
                    keyword = token(fp);
376
 
                    gfi->xHeight = atoi(keyword);
377
 
                    break;
378
 
                case DESCENDER:
379
 
                    keyword = token(fp);
380
 
                    gfi->descender = atoi(keyword);
381
 
                    break;
382
 
                case ASCENDER:
383
 
                    keyword = token(fp);
384
 
                    gfi->ascender = atoi(keyword);
385
 
                    break;
386
 
                case STARTCHARMETRICS:
387
 
                    cont = FALSE;
388
 
                    break;
389
 
                case ENDFONTMETRICS:
390
 
                    cont = FALSE;
391
 
                    error = normalEOF;
392
 
                    break;
393
 
                case NOPE:
394
 
                default:
395
 
                    error = parseError;
396
 
                    break;
397
 
            } /* switch */
398
 
    } /* while */
399
 
    
400
 
    return(error);
401
 
    
402
 
} /* parseGlobals */    
403
 
 
404
 
 
405
 
 
406
 
#if 0 /* this function does not seem to be used anywhere */
407
 
/************************* initializeArray ************************/
408
 
 
409
 
/*  Unmapped character codes are (at Adobe Systems) assigned the
410
 
 *  width of the space character (if one exists) else they get the
411
 
 *  value of 250 ems. This function initializes all entries in the
412
 
 *  char widths array to have this value. Then any mapped character 
413
 
 *  codes will be replaced with the width of the appropriate character 
414
 
 *  when parsing the character metric section.
415
 
 
416
 
 *  This function parses the Character Metrics Section looking
417
 
 *  for a space character (by comparing character names). If found,
418
 
 *  the width of the space character will be used to initialize the
419
 
 *  values in the array of character widths. 
420
 
 *
421
 
 *  Before returning, the position of the read/write pointer of the
422
 
 *  file is reset to be where it was upon entering this function.
423
 
 */
424
 
 
425
 
static int initializeArray(FILE *fp, int *cwi)
426
 
{  
427
 
    BOOL cont = TRUE, found = FALSE;
428
 
    long opos = ftell(fp);
429
 
    int code = 0, width = 0, i = 0, error = 0;
430
 
    register char *keyword;
431
 
  
432
 
    while (cont)
433
 
    {
434
 
        keyword = token(fp);
435
 
        if (keyword == NULL)
436
 
        {
437
 
            error = earlyEOF;
438
 
            break; /* get out of loop */
439
 
        }
440
 
        switch(recognize(keyword))
441
 
        {
442
 
            case COMMENT:
443
 
                keyword = linetoken(fp);
444
 
                break;
445
 
            case CODE:
446
 
                code = atoi(token(fp));
447
 
                break;
448
 
            case XWIDTH:
449
 
                width = atoi(token(fp));
450
 
                break;
451
 
            case CHARNAME: 
452
 
                keyword = token(fp);
453
 
                if (MATCH(keyword, Space))
454
 
                {    
455
 
                    cont = FALSE;
456
 
                    found = TRUE;
457
 
                } 
458
 
                break;            
459
 
            case ENDCHARMETRICS:
460
 
                cont = FALSE;
461
 
                break; 
462
 
            case ENDFONTMETRICS:
463
 
                cont = FALSE;
464
 
                error = normalEOF;
465
 
                break;
466
 
            case NOPE:
467
 
            default: 
468
 
                error = parseError;
469
 
                break;
470
 
        } /* switch */
471
 
    } /* while */
472
 
    
473
 
    if (!found)
474
 
        width = 250;
475
 
    
476
 
    for (i = 0; i < 256; ++i)
477
 
        cwi[i] = width;
478
 
    
479
 
    fseek(fp, opos, 0);
480
 
    
481
 
    return(error);
482
 
        
483
 
} /* initializeArray */    
484
 
#endif /* unused */
485
 
 
486
 
/************************* parseCharWidths **************************/
487
 
 
488
 
/*  This function is called by "parseFile". It will parse the AFM File
489
 
 *  up to the "EndCharMetrics" keyword. It will save the character 
490
 
 *  width info (as opposed to all of the character metric information)
491
 
 *  if requested by the caller of parseFile. Otherwise, it will just
492
 
 *  parse through the section without saving any information.
493
 
 *
494
 
 *  If data is to be saved, parseCharWidths is passed in a pointer 
495
 
 *  to an array of widths that has already been initialized by the
496
 
 *  standard value for unmapped character codes. This function parses
497
 
 *  the Character Metrics section only storing the width information
498
 
 *  for the encoded characters into the array using the character code
499
 
 *  as the index into that array.
500
 
 *
501
 
 *  This function returns an error code specifying whether there was 
502
 
 *  a premature EOF or a parsing error. This return value is used by 
503
 
 *  parseFile to determine if there is more file to parse.
504
 
 */
505
 
 
506
 
static int parseCharWidths(FILE *fp, int *cwi)
507
 
{  
508
 
    BOOL cont = TRUE, save = (cwi != NULL);
509
 
    int pos = 0, error = ok;
510
 
    register char *keyword;
511
 
    
512
 
    while (cont)
513
 
    {
514
 
        keyword = token(fp);
515
 
          /* Have reached an early and unexpected EOF. */
516
 
          /* Set flag and stop parsing */
517
 
        if (keyword == NULL)
518
 
        {
519
 
            error = earlyEOF;
520
 
            break; /* get out of loop */
521
 
        }
522
 
        if (!save)      
523
 
          /* get tokens until the end of the Char Metrics section without */
524
 
          /* saving any of the data*/
525
 
            switch (recognize(keyword))  
526
 
            {                           
527
 
                case ENDCHARMETRICS:
528
 
                    cont = FALSE;
529
 
                    break; 
530
 
                case ENDFONTMETRICS:
531
 
                    cont = FALSE;
532
 
                    error = normalEOF;
533
 
                    break;
534
 
                default: 
535
 
                    break;
536
 
            } /* switch */
537
 
        else
538
 
          /* otherwise parse entire char metrics section, saving */
539
 
          /* only the char x-width info */
540
 
            switch(recognize(keyword))
541
 
            {
542
 
                case COMMENT:
543
 
                    keyword = linetoken(fp);
544
 
                    break;
545
 
                case CODE:
546
 
                    keyword = token(fp);
547
 
                    pos = atoi(keyword);
548
 
                    break;
549
 
                case XYWIDTH:
550
 
                /* PROBLEM: Should be no Y-WIDTH when doing "quick & dirty" */
551
 
                    keyword = token(fp); keyword = token(fp); /* eat values */
552
 
                    error = parseError;
553
 
                    break;
554
 
                case XWIDTH:
555
 
                    keyword = token(fp);
556
 
                    if (pos >= 0) /* ignore unmapped chars */
557
 
                        cwi[pos] = atoi(keyword);
558
 
                    break;
559
 
                case ENDCHARMETRICS:
560
 
                    cont = FALSE;
561
 
                    break; 
562
 
                case ENDFONTMETRICS:
563
 
                    cont = FALSE;
564
 
                    error = normalEOF;
565
 
                    break;
566
 
                case CHARNAME:  /* eat values (so doesn't cause parseError) */
567
 
                    keyword = token(fp); 
568
 
                    break;
569
 
                case CHARBBOX: 
570
 
                    keyword = token(fp); keyword = token(fp);
571
 
                    keyword = token(fp); keyword = token(fp);
572
 
                    break;
573
 
                case LIGATURE:
574
 
                    keyword = token(fp); keyword = token(fp);
575
 
                    break;
576
 
                case NOPE:
577
 
                default: 
578
 
                    error = parseError;
579
 
                    break;
580
 
            } /* switch */
581
 
    } /* while */
582
 
    
583
 
    return(error);
584
 
    
585
 
} /* parseCharWidths */    
586
 
 
587
 
 
588
 
/************************* parseCharMetrics ************************/
589
 
 
590
 
/*  This function is called by parseFile if the caller of parseFile
591
 
 *  requested that all character metric information be saved
592
 
 *  (as opposed to only the character width information).
593
 
 *
594
 
 *  parseCharMetrics is passed in a pointer to an array of records
595
 
 *  to hold information on a per character basis. This function
596
 
 *  parses the Character Metrics section storing all character
597
 
 *  metric information for the ALL characters (mapped and unmapped) 
598
 
 *  into the array.
599
 
 *
600
 
 *  This function returns an error code specifying whether there was 
601
 
 *  a premature EOF or a parsing error. This return value is used by 
602
 
 *  parseFile to determine if there is more file to parse.
603
 
 */
604
 
 
605
 
static int parseCharMetrics(FILE *fp, FontInfo *fi)
606
 
{  
607
 
    BOOL cont = TRUE, firstTime = TRUE;
608
 
    int error = ok, count = 0;
609
 
    register CharMetricInfo *temp = fi->cmi;
610
 
    register char *keyword;
611
 
  
612
 
    while (cont)
613
 
    {
614
 
        keyword = token(fp);
615
 
        if (keyword == NULL)
616
 
        {
617
 
            error = earlyEOF;
618
 
            break; /* get out of loop */
619
 
        }
620
 
        switch(recognize(keyword))
621
 
        {
622
 
            case COMMENT:
623
 
                keyword = linetoken(fp);
624
 
                break; 
625
 
            case CODE:
626
 
                if (count < fi->numOfChars)
627
 
                { 
628
 
                    if (firstTime) firstTime = FALSE;
629
 
                    else temp++;
630
 
                    temp->code = atoi(token(fp));
631
 
                    count++;
632
 
                }
633
 
                else
634
 
                {
635
 
                    error = parseError;
636
 
                    cont = FALSE;
637
 
                }
638
 
                break;
639
 
            case XYWIDTH:
640
 
                temp->wx = atoi(token(fp));
641
 
                temp->wy = atoi(token(fp));
642
 
                break;                 
643
 
            case XWIDTH: 
644
 
                temp->wx = atoi(token(fp));
645
 
                break;
646
 
            case CHARNAME: 
647
 
                keyword = token(fp);
648
 
                temp->name = (char *) malloc(strlen(keyword) + 1);
649
 
                strcpy(temp->name, keyword);
650
 
                break;            
651
 
            case CHARBBOX: 
652
 
                temp->charBBox.llx = atoi(token(fp));
653
 
                temp->charBBox.lly = atoi(token(fp));
654
 
                temp->charBBox.urx = atoi(token(fp));
655
 
                temp->charBBox.ury = atoi(token(fp));
656
 
                break;
657
 
            case LIGATURE: {
658
 
                Ligature **tail = &(temp->ligs);
659
 
                Ligature *node = *tail;
660
 
                
661
 
                if (*tail != NULL)
662
 
                {
663
 
                    while (node->next != NULL)
664
 
                        node = node->next;
665
 
                    tail = &(node->next); 
666
 
                }
667
 
                
668
 
                *tail = (Ligature *) calloc(1, sizeof(Ligature));
669
 
                keyword = token(fp);
670
 
                (*tail)->succ = (char *) malloc(strlen(keyword) + 1);
671
 
                strcpy((*tail)->succ, keyword);
672
 
                keyword = token(fp);
673
 
                (*tail)->lig = (char *) malloc(strlen(keyword) + 1);
674
 
                strcpy((*tail)->lig, keyword);
675
 
                break; }
676
 
            case ENDCHARMETRICS:
677
 
                cont = FALSE;;
678
 
                break; 
679
 
            case ENDFONTMETRICS: 
680
 
                cont = FALSE;
681
 
                error = normalEOF;
682
 
                break; 
683
 
            case NOPE:
684
 
            default:
685
 
                error = parseError; 
686
 
                break; 
687
 
        } /* switch */
688
 
    } /* while */
689
 
    
690
 
    if ((error == ok) && (count != fi->numOfChars))
691
 
        error = parseError;
692
 
    
693
 
    return(error);
694
 
    
695
 
} /* parseCharMetrics */    
696
 
 
697
 
 
698
 
 
699
 
/************************* parseTrackKernData ***********************/
700
 
 
701
 
/*  This function is called by "parseFile". It will parse the AFM File 
702
 
 *  up to the "EndTrackKern" or "EndKernData" keywords. It will save the
703
 
 *  track kerning data if requested by the caller of parseFile.
704
 
 *
705
 
 *  parseTrackKernData is passed in a pointer to the FontInfo record.
706
 
 *  If data is to be saved, the FontInfo record will already contain 
707
 
 *  a valid pointer to storage for the track kerning data.
708
 
 *
709
 
 *  This function returns an error code specifying whether there was 
710
 
 *  a premature EOF or a parsing error. This return value is used by 
711
 
 *  parseFile to determine if there is more file to parse.
712
 
 */
713
 
 
714
 
static int parseTrackKernData(FILE *fp, FontInfo *fi)
715
 
{  
716
 
    BOOL cont = TRUE, save = (fi->tkd != NULL);
717
 
    int pos = 0, error = ok, tcount = 0;
718
 
    register char *keyword;
719
 
  
720
 
    while (cont)
721
 
    {
722
 
        keyword = token(fp);
723
 
        
724
 
        if (keyword == NULL)
725
 
        {
726
 
            error = earlyEOF;
727
 
            break; /* get out of loop */
728
 
        }
729
 
        if (!save)
730
 
          /* get tokens until the end of the Track Kerning Data */
731
 
          /* section without saving any of the data */
732
 
            switch(recognize(keyword))
733
 
            {
734
 
                case ENDTRACKKERN:
735
 
                case ENDKERNDATA:
736
 
                    cont = FALSE;
737
 
                    break;
738
 
                case ENDFONTMETRICS:
739
 
                    cont = FALSE;
740
 
                    error = normalEOF;
741
 
                    break;
742
 
                default:
743
 
                    break;
744
 
            } /* switch */
745
 
        else
746
 
          /* otherwise parse entire Track Kerning Data section, */
747
 
          /* saving the data */
748
 
            switch(recognize(keyword))
749
 
            {
750
 
                case COMMENT:
751
 
                    keyword = linetoken(fp);
752
 
                    break;
753
 
                case TRACKKERN:
754
 
                    if (tcount < fi->numOfTracks)
755
 
                    {
756
 
                        keyword = token(fp);
757
 
                        fi->tkd[pos].degree = atoi(keyword);
758
 
                        keyword = token(fp);
759
 
                        fi->tkd[pos].minPtSize = atof(keyword);
760
 
                        if (errno == ERANGE) error = parseError;
761
 
                        keyword = token(fp);
762
 
                        fi->tkd[pos].minKernAmt = atof(keyword);
763
 
                        if (errno == ERANGE) error = parseError;
764
 
                        keyword = token(fp);
765
 
                        fi->tkd[pos].maxPtSize = atof(keyword);
766
 
                        if (errno == ERANGE) error = parseError;
767
 
                        keyword = token(fp);
768
 
                        fi->tkd[pos++].maxKernAmt = atof(keyword);
769
 
                        if (errno == ERANGE) error = parseError;
770
 
                        tcount++;
771
 
                    }
772
 
                    else
773
 
                    {
774
 
                        error = parseError;
775
 
                        cont = FALSE;
776
 
                    }
777
 
                    break;
778
 
                case ENDTRACKKERN:
779
 
                case ENDKERNDATA:
780
 
                    cont = FALSE;
781
 
                    break;
782
 
                case ENDFONTMETRICS:
783
 
                    cont = FALSE;
784
 
                    error = normalEOF;
785
 
                    break;
786
 
                case NOPE:
787
 
                default:
788
 
                    error = parseError;
789
 
                    break;
790
 
            } /* switch */
791
 
    } /* while */
792
 
    
793
 
    if (error == ok && tcount != fi->numOfTracks)
794
 
        error = parseError;
795
 
        
796
 
    return(error);
797
 
    
798
 
} /* parseTrackKernData */    
799
 
 
800
 
 
801
 
/************************* parsePairKernData ************************/
802
 
 
803
 
/*  This function is called by "parseFile". It will parse the AFM File 
804
 
 *  up to the "EndKernPairs" or "EndKernData" keywords. It will save
805
 
 *  the pair kerning data if requested by the caller of parseFile.
806
 
 *
807
 
 *  parsePairKernData is passed in a pointer to the FontInfo record.
808
 
 *  If data is to be saved, the FontInfo record will already contain 
809
 
 *  a valid pointer to storage for the pair kerning data.
810
 
 *
811
 
 *  This function returns an error code specifying whether there was 
812
 
 *  a premature EOF or a parsing error. This return value is used by 
813
 
 *  parseFile to determine if there is more file to parse.
814
 
 */
815
 
 
816
 
static int parsePairKernData(FILE *fp, FontInfo *fi)
817
 
{  
818
 
    BOOL cont = TRUE, save = (fi->pkd != NULL);
819
 
    int pos = 0, error = ok, pcount = 0;
820
 
    register char *keyword;
821
 
  
822
 
    while (cont)
823
 
    {
824
 
        keyword = token(fp);
825
 
        
826
 
        if (keyword == NULL)
827
 
        {
828
 
            error = earlyEOF;
829
 
            break; /* get out of loop */
830
 
        }
831
 
        if (!save)
832
 
          /* get tokens until the end of the Pair Kerning Data */
833
 
          /* section without saving any of the data */
834
 
            switch(recognize(keyword))
835
 
            {
836
 
                case ENDKERNPAIRS:
837
 
                case ENDKERNDATA:
838
 
                    cont = FALSE;
839
 
                    break;
840
 
                case ENDFONTMETRICS:
841
 
                    cont = FALSE;
842
 
                    error = normalEOF;
843
 
                    break;
844
 
                default:
845
 
                    break;
846
 
            } /* switch */
847
 
        else
848
 
          /* otherwise parse entire Pair Kerning Data section, */
849
 
          /* saving the data */
850
 
            switch(recognize(keyword))
851
 
            {
852
 
                case COMMENT:
853
 
                    keyword = linetoken(fp);
854
 
                    break;
855
 
                case KERNPAIR:
856
 
                    if (pcount < fi->numOfPairs)
857
 
                    {
858
 
                        keyword = token(fp);
859
 
                        fi->pkd[pos].name1 = (char *) 
860
 
                            malloc(strlen(keyword) + 1);
861
 
                        strcpy(fi->pkd[pos].name1, keyword);
862
 
                        keyword = token(fp);
863
 
                        fi->pkd[pos].name2 = (char *) 
864
 
                            malloc(strlen(keyword) + 1);
865
 
                        strcpy(fi->pkd[pos].name2, keyword);
866
 
                        keyword = token(fp);
867
 
                        fi->pkd[pos].xamt = atoi(keyword);
868
 
                        keyword = token(fp);
869
 
                        fi->pkd[pos++].yamt = atoi(keyword);
870
 
                        pcount++;
871
 
                    }
872
 
                    else
873
 
                    {
874
 
                        error = parseError;
875
 
                        cont = FALSE;
876
 
                    }
877
 
                    break;
878
 
                case KERNPAIRXAMT:
879
 
                    if (pcount < fi->numOfPairs)
880
 
                    {
881
 
                        keyword = token(fp);
882
 
                        fi->pkd[pos].name1 = (char *) 
883
 
                            malloc(strlen(keyword) + 1);
884
 
                        strcpy(fi->pkd[pos].name1, keyword);
885
 
                        keyword = token(fp);
886
 
                        fi->pkd[pos].name2 = (char *) 
887
 
                            malloc(strlen(keyword) + 1);
888
 
                        strcpy(fi->pkd[pos].name2, keyword);
889
 
                        keyword = token(fp);
890
 
                        fi->pkd[pos++].xamt = atoi(keyword);
891
 
                        pcount++;
892
 
                    }
893
 
                    else
894
 
                    {
895
 
                        error = parseError;
896
 
                        cont = FALSE;
897
 
                    }
898
 
                    break;
899
 
                case ENDKERNPAIRS:
900
 
                case ENDKERNDATA:
901
 
                    cont = FALSE;
902
 
                    break;
903
 
                case ENDFONTMETRICS:
904
 
                    cont = FALSE;
905
 
                    error = normalEOF;
906
 
                    break;
907
 
                case NOPE:
908
 
                default:
909
 
                    error = parseError;
910
 
                    break;
911
 
            } /* switch */
912
 
    } /* while */
913
 
    
914
 
    if (error == ok && pcount != fi->numOfPairs)
915
 
        error = parseError;
916
 
        
917
 
    return(error);
918
 
    
919
 
} /* parsePairKernData */    
920
 
 
921
 
 
922
 
/************************* parseCompCharData **************************/
923
 
 
924
 
/*  This function is called by "parseFile". It will parse the AFM File 
925
 
 *  up to the "EndComposites" keyword. It will save the composite 
926
 
 *  character data if requested by the caller of parseFile.
927
 
 *
928
 
 *  parseCompCharData is passed in a pointer to the FontInfo record, and 
929
 
 *  a boolean representing if the data should be saved.
930
 
 *
931
 
 *  This function will create the appropriate amount of storage for
932
 
 *  the composite character data and store a pointer to the storage
933
 
 *  in the FontInfo record.
934
 
 *
935
 
 *  This function returns an error code specifying whether there was 
936
 
 *  a premature EOF or a parsing error. This return value is used by 
937
 
 *  parseFile to determine if there is more file to parse.
938
 
 */
939
 
 
940
 
static int parseCompCharData(FILE *fp, FontInfo *fi)
941
 
{  
942
 
    BOOL cont = TRUE, firstTime = TRUE, save = (fi->ccd != NULL);
943
 
    int pos = 0, j = 0, error = ok, ccount = 0, pcount = 0;
944
 
    register char *keyword;
945
 
  
946
 
    while (cont)
947
 
    {
948
 
        keyword = token(fp);
949
 
        if (keyword == NULL)
950
 
          /* Have reached an early and unexpected EOF. */
951
 
          /* Set flag and stop parsing */
952
 
        {
953
 
            error = earlyEOF;
954
 
            break; /* get out of loop */
955
 
        }
956
 
        if (ccount > fi->numOfComps)
957
 
        {
958
 
            error = parseError;
959
 
            break; /* get out of loop */
960
 
        }
961
 
        if (!save)
962
 
          /* get tokens until the end of the Composite Character info */
963
 
          /* section without saving any of the data */
964
 
            switch(recognize(keyword))
965
 
            {
966
 
                case ENDCOMPOSITES:
967
 
                    cont = FALSE;
968
 
                    break;
969
 
                case ENDFONTMETRICS:
970
 
                    cont = FALSE;
971
 
                    error = normalEOF;
972
 
                    break;
973
 
                default:
974
 
                    break;
975
 
            } /* switch */
976
 
        else
977
 
          /* otherwise parse entire Composite Character info section, */
978
 
          /* saving the data */
979
 
            switch(recognize(keyword))
980
 
            {
981
 
                case COMMENT:
982
 
                    keyword = linetoken(fp);
983
 
                    break;
984
 
                case COMPCHAR:
985
 
                    if (ccount < fi->numOfComps)
986
 
                    {
987
 
                        keyword = token(fp);
988
 
                        if (pcount != fi->ccd[pos].numOfPieces)
989
 
                            error = parseError;
990
 
                        pcount = 0;
991
 
                        if (firstTime) firstTime = FALSE;
992
 
                        else pos++;
993
 
                        fi->ccd[pos].ccName = (char *) 
994
 
                            malloc(strlen(keyword) + 1);
995
 
                        strcpy(fi->ccd[pos].ccName, keyword);
996
 
                        keyword = token(fp);
997
 
                        fi->ccd[pos].numOfPieces = atoi(keyword);
998
 
                        fi->ccd[pos].pieces = (Pcc *)
999
 
                            calloc(fi->ccd[pos].numOfPieces, sizeof(Pcc));
1000
 
                        j = 0;
1001
 
                        ccount++;
1002
 
                    }
1003
 
                    else
1004
 
                    {
1005
 
                        error = parseError;
1006
 
                        cont = FALSE;
1007
 
                    }
1008
 
                    break;
1009
 
                case COMPCHARPIECE:
1010
 
                    if (pcount < fi->ccd[pos].numOfPieces)
1011
 
                    {
1012
 
                        keyword = token(fp);
1013
 
                        fi->ccd[pos].pieces[j].pccName = (char *) 
1014
 
                                malloc(strlen(keyword) + 1);
1015
 
                        strcpy(fi->ccd[pos].pieces[j].pccName, keyword);
1016
 
                        keyword = token(fp);
1017
 
                        fi->ccd[pos].pieces[j].deltax = atoi(keyword);
1018
 
                        keyword = token(fp);
1019
 
                        fi->ccd[pos].pieces[j++].deltay = atoi(keyword);
1020
 
                        pcount++;
1021
 
                    }
1022
 
                    else
1023
 
                        error = parseError;
1024
 
                    break;
1025
 
                case ENDCOMPOSITES:
1026
 
                    cont = FALSE;
1027
 
                    break;
1028
 
                case ENDFONTMETRICS:
1029
 
                    cont = FALSE;
1030
 
                    error = normalEOF;
1031
 
                    break;
1032
 
                case NOPE:
1033
 
                default:
1034
 
                    error = parseError;
1035
 
                    break;
1036
 
            } /* switch */
1037
 
    } /* while */
1038
 
    
1039
 
    if (error == ok && ccount != fi->numOfComps)
1040
 
        error = parseError;
1041
 
    
1042
 
    return(error);
1043
 
    
1044
 
} /* parseCompCharData */    
1045
 
 
1046
 
 
1047
 
 
1048
 
 
1049
 
/*************************** 'PUBLIC' FUNCTION ********************/ 
1050
 
 
1051
 
 
1052
 
/*************************** parseFile *****************************/
1053
 
 
1054
 
/*  parseFile is the only 'public' procedure available. It is called 
1055
 
 *  from an application wishing to get information from an AFM file.
1056
 
 *  The caller of this function is responsible for locating and opening
1057
 
 *  an AFM file and handling all errors associated with that task.
1058
 
 *
1059
 
 *  parseFile expects 3 parameters: a vaild file pointer, a pointer
1060
 
 *  to a (FontInfo *) variable (for which storage will be allocated and
1061
 
 *  the data requested filled in), and a mask specifying which
1062
 
 *  data from the AFM File should be saved in the FontInfo structure.
1063
 
 *
1064
 
 *  The file will be parsed and the requested data will be stored in 
1065
 
 *  a record of type FontInfo (refer to ParseAFM.h).
1066
 
 *
1067
 
 *  parseFile returns an error code as defined in parseAFM.h. 
1068
 
 *
1069
 
 *  The position of the read/write pointer associated with the file 
1070
 
 *  pointer upon return of this function is undefined.
1071
 
 */
1072
 
 
1073
 
extern int afm_parse_file(FILE *fp, FontInfo **fi, FLAGS flags)
1074
 
{
1075
 
    
1076
 
    int code = ok;      /* return code from each of the parsing routines */
1077
 
    int error = ok;     /* used as the return code from this function */
1078
 
    
1079
 
    register char *keyword; /* used to store a token */  
1080
 
    
1081
 
                              
1082
 
    /* storage data for the global variable ident */                          
1083
 
    ident = (char *) calloc(MAX_NAME, sizeof(char)); 
1084
 
    if (ident == NULL) {error = storageProblem; return(error);}      
1085
 
  
1086
 
    (*fi) = (FontInfo *) calloc(1, sizeof(FontInfo));
1087
 
    if ((*fi) == NULL) {error = storageProblem; return(error);}      
1088
 
  
1089
 
    if (flags & P_G) 
1090
 
    {
1091
 
        (*fi)->gfi = (GlobalFontInfo *) calloc(1, sizeof(GlobalFontInfo));
1092
 
        if ((*fi)->gfi == NULL) {error = storageProblem; return(error);}      
1093
 
    }
1094
 
    
1095
 
    /* The AFM File begins with Global Font Information. This section */
1096
 
    /* will be parsed whether or not information should be saved. */     
1097
 
    code = parseGlobals(fp, (*fi)->gfi); 
1098
 
    
1099
 
    if (code < 0) error = code;
1100
 
    
1101
 
    /* The Global Font Information is followed by the Character Metrics */
1102
 
    /* section. Which procedure is used to parse this section depends on */
1103
 
    /* how much information should be saved. If all of the metrics info */
1104
 
    /* is wanted, parseCharMetrics is called. If only the character widths */
1105
 
    /* is wanted, parseCharWidths is called. parseCharWidths will also */
1106
 
    /* be called in the case that no character data is to be saved, just */
1107
 
    /* to parse through the section. */
1108
 
  
1109
 
    if ((code != normalEOF) && (code != earlyEOF))
1110
 
    {
1111
 
        (*fi)->numOfChars = atoi(token(fp));
1112
 
            if (flags & (P_M ^ P_W))
1113
 
        {
1114
 
            (*fi)->cmi = (CharMetricInfo *) 
1115
 
                      calloc((*fi)->numOfChars, sizeof(CharMetricInfo));
1116
 
           if ((*fi)->cmi == NULL) {error = storageProblem; return(error);}
1117
 
            code = parseCharMetrics(fp, *fi);             
1118
 
        }
1119
 
        else
1120
 
        {
1121
 
            if (flags & P_W)
1122
 
            { 
1123
 
                (*fi)->cwi = (int *) calloc(256, sizeof(int)); 
1124
 
                if ((*fi)->cwi == NULL) 
1125
 
                {
1126
 
                        error = storageProblem; 
1127
 
                        return(error);
1128
 
                }
1129
 
            }
1130
 
            /* parse section regardless */
1131
 
            code = parseCharWidths(fp, (*fi)->cwi);
1132
 
        } /* else */
1133
 
    } /* if */
1134
 
    
1135
 
    if ((error != earlyEOF) && (code < 0)) error = code;
1136
 
    
1137
 
    /* The remaining sections of the AFM are optional. This code will */
1138
 
    /* look at the next keyword in the file to determine what section */
1139
 
    /* is next, and then allocate the appropriate amount of storage */
1140
 
    /* for the data (if the data is to be saved) and call the */
1141
 
    /* appropriate parsing routine to parse the section. */
1142
 
    
1143
 
    while ((code != normalEOF) && (code != earlyEOF))
1144
 
    {
1145
 
        keyword = token(fp);
1146
 
        if (keyword == NULL)
1147
 
          /* Have reached an early and unexpected EOF. */
1148
 
          /* Set flag and stop parsing */
1149
 
        {
1150
 
            code = earlyEOF;
1151
 
            break; /* get out of loop */
1152
 
        }
1153
 
        switch(recognize(keyword))
1154
 
        {
1155
 
            case STARTKERNDATA:
1156
 
                break;
1157
 
            case ENDKERNDATA:
1158
 
                break;
1159
 
            case STARTTRACKKERN:
1160
 
                keyword = token(fp);
1161
 
                if (flags & P_T)
1162
 
                {
1163
 
                    (*fi)->numOfTracks = atoi(keyword);
1164
 
                    (*fi)->tkd = (TrackKernData *) 
1165
 
                        calloc((*fi)->numOfTracks, sizeof(TrackKernData));
1166
 
                    if ((*fi)->tkd == NULL) 
1167
 
                    {
1168
 
                        error = storageProblem; 
1169
 
                        return(error);
1170
 
                    }
1171
 
                } /* if */
1172
 
                code = parseTrackKernData(fp, *fi);
1173
 
                break;
1174
 
            case STARTKERNPAIRS:
1175
 
                keyword = token(fp);
1176
 
                if (flags & P_P)
1177
 
                {
1178
 
                    (*fi)->numOfPairs = atoi(keyword);
1179
 
                    (*fi)->pkd = (PairKernData *) 
1180
 
                        calloc((*fi)->numOfPairs, sizeof(PairKernData));
1181
 
                    if ((*fi)->pkd == NULL) 
1182
 
                    {
1183
 
                        error = storageProblem; 
1184
 
                        return(error);
1185
 
                    }
1186
 
                } /* if */
1187
 
                code = parsePairKernData(fp, *fi);
1188
 
                break;
1189
 
            case STARTCOMPOSITES:
1190
 
                keyword = token(fp);
1191
 
                if (flags & P_C)
1192
 
                { 
1193
 
                    (*fi)->numOfComps = atoi(keyword);
1194
 
                    (*fi)->ccd = (CompCharData *) 
1195
 
                        calloc((*fi)->numOfComps, sizeof(CompCharData));
1196
 
                    if ((*fi)->ccd == NULL) 
1197
 
                    {
1198
 
                        error = storageProblem; 
1199
 
                        return(error);
1200
 
                    }
1201
 
                } /* if */
1202
 
                code = parseCompCharData(fp, *fi); 
1203
 
                break;    
1204
 
            case ENDFONTMETRICS:
1205
 
                code = normalEOF;
1206
 
                break;
1207
 
            case NOPE:
1208
 
            default:
1209
 
                code = parseError;
1210
 
                break;
1211
 
        } /* switch */
1212
 
        
1213
 
        if ((error != earlyEOF) && (code < 0)) error = code;
1214
 
        
1215
 
    } /* while */
1216
 
  
1217
 
    if ((error != earlyEOF) && (code < 0)) error = code;
1218
 
    
1219
 
    if (ident != NULL) { free(ident); ident = NULL; }
1220
 
        
1221
 
    return(error);
1222
 
  
1223
 
} /* parseFile */
1224
 
 
1225
 
/* added for MDVI: this function was copied from `parseAFMclient.c' */
1226
 
 
1227
 
void afm_free_fontinfo(FontInfo *fi)
1228
 
{
1229
 
    if (fi != NULL)
1230
 
    {
1231
 
        if (fi->gfi != NULL)
1232
 
        { 
1233
 
            free(fi->gfi->afmVersion); fi->gfi->afmVersion = NULL;
1234
 
            free(fi->gfi->fontName); fi->gfi->fontName = NULL;
1235
 
            free(fi->gfi->fullName); fi->gfi->fullName = NULL;
1236
 
            free(fi->gfi->familyName); fi->gfi->familyName = NULL;
1237
 
            free(fi->gfi->weight); fi->gfi->weight = NULL;
1238
 
            free(fi->gfi->version); fi->gfi->version = NULL;
1239
 
            free(fi->gfi->notice); fi->gfi->notice = NULL;
1240
 
            free(fi->gfi->encodingScheme); fi->gfi->encodingScheme = NULL;
1241
 
            free(fi->gfi); fi->gfi = NULL;
1242
 
        }
1243
 
  
1244
 
        if (fi->cwi != NULL)
1245
 
        { free(fi->cwi); fi->cwi = NULL; }
1246
 
 
1247
 
        if (fi->cmi != NULL)
1248
 
        { 
1249
 
            int i = 0;
1250
 
            CharMetricInfo *temp = fi->cmi;
1251
 
            Ligature *node = temp->ligs;
1252
 
            
1253
 
            for (i = 0; i < fi->numOfChars; ++i)
1254
 
            {
1255
 
                for (node = temp->ligs; node != NULL; node = node->next)
1256
 
                {
1257
 
                    free(node->succ); node->succ = NULL;
1258
 
                    free(node->lig); node->lig = NULL;
1259
 
                }
1260
 
                
1261
 
                free(temp->name); temp->name = NULL;
1262
 
                temp++;
1263
 
            }
1264
 
            
1265
 
            free(fi->cmi); fi->cmi = NULL;
1266
 
        }
1267
 
 
1268
 
        if (fi->tkd != NULL)
1269
 
        { free(fi->tkd); fi->tkd = NULL; }
1270
 
  
1271
 
        if (fi->pkd != NULL)
1272
 
        { 
1273
 
            free(fi->pkd->name1); fi->pkd->name1 = NULL;
1274
 
            free(fi->pkd->name2); fi->pkd->name2 = NULL;
1275
 
            free(fi->pkd); fi->pkd = NULL;
1276
 
        }
1277
 
 
1278
 
        if (fi->ccd != NULL)
1279
 
        { 
1280
 
            int i = 0, j = 0;
1281
 
            CompCharData *ccd = fi->ccd;
1282
 
            
1283
 
            for (i = 0; i < fi->numOfComps; ++i)
1284
 
            {
1285
 
                for (j = 0; j < ccd[i].numOfPieces; ++j)
1286
 
                {
1287
 
                    free(ccd[i].pieces[j].pccName); 
1288
 
                    ccd[i].pieces[j].pccName = NULL;
1289
 
                }
1290
 
                
1291
 
                free(ccd[i].ccName); ccd[i].ccName = NULL;
1292
 
            }
1293
 
    
1294
 
            free(fi->ccd); fi->ccd = NULL;
1295
 
        }
1296
 
        
1297
 
        free(fi);
1298
 
 
1299
 
    } /* if */ 
1300
 
  
1301
 
} /* afm_free_fontinfo */
1302
 
 
1303
 
#endif /* WITH_AFM_FILES */