(file) Return to afmparse.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / afmlib

   1 rizwank 1.1 /*
   2              * Parse AFM files.
   3              * Copyright (c) 1995-1998 Markku Rossi.
   4              *
   5              * Author: Markku Rossi <mtr@iki.fi>
   6              */
   7             
   8             /*
   9              * This program is free software; you can redistribute it and/or modify
  10              * it under the terms of the GNU General Public License as published by
  11              * the Free Software Foundation; either version 2, or (at your option)
  12              * any later version.
  13              *
  14              * This program is distributed in the hope that it will be useful,
  15              * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16              * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17              * GNU General Public License for more details.
  18              *
  19              * You should have received a copy of the GNU General Public License
  20              * along with this program; see the file COPYING.  If not, write to
  21              * the Free Software Foundation, 59 Temple Place - Suite 330,
  22 rizwank 1.1  * Boston, MA 02111-1307, USA.
  23              */
  24             
  25             #include "afmint.h"
  26             #include "afm.h"
  27             
  28             /*
  29              * Definitions.
  30              */
  31             
  32             #define ISSPACE(ch) \
  33               ((ch) == ' ' || (ch) == '\n' || (ch) == '\r' || (ch) == '\t' || (ch) == ';')
  34             
  35             #define GET_VALUE(typenum) get_type (handle, ctx, (typenum), &node)
  36             
  37             struct parse_ctx_st
  38             {
  39               FILE *fp;
  40               char token[1024];		/* maximum line length is 255, this should be
  41             				   enought */
  42               unsigned int tokenlen;	/* length of the token */
  43 rizwank 1.1 };
  44             
  45             typedef struct parse_ctx_st ParseCtx;
  46             
  47             /*
  48              * Static variables.
  49              */
  50             
  51             /*
  52              * The AFM keys.  This array must be kept sorted because keys are
  53              * searched by using binary search.
  54              */
  55             static struct keyname_st
  56             {
  57               char *name;
  58               AFMKey key;
  59             } keynames[] =
  60             {
  61               {"Ascender", 			kAscender},
  62               {"Axes", 			kAxes},
  63               {"AxisLabel", 		kAxisLabel},
  64 rizwank 1.1   {"AxisType", 			kAxisType},
  65               {"B",				kB},
  66               {"BlendAxisTypes", 		kBlendAxisTypes},
  67               {"BlendDesignMap", 		kBlendDesignMap},
  68               {"BlendDesignPositions", 	kBlendDesignPositions},
  69               {"C",				kC},
  70               {"CC", 			kCC},
  71               {"CH",			kCH},
  72               {"CapHeight", 		kCapHeight},
  73               {"CharWidth", 		kCharWidth},
  74               {"CharacterSet", 		kCharacterSet},
  75               {"Characters", 		kCharacters},
  76               {"Comment", 			kComment},
  77               {"Descendents", 		kDescendents},
  78               {"Descender", 		kDescender},
  79               {"EncodingScheme", 		kEncodingScheme},
  80               {"EndAxis", 			kEndAxis},
  81               {"EndCharMetrics", 		kEndCharMetrics},
  82               {"EndCompFontMetrics", 	kEndCompFontMetrics},
  83               {"EndComposites", 		kEndComposites},
  84               {"EndDescendent", 		kEndDescendent},
  85 rizwank 1.1   {"EndDirection", 		kEndDirection},
  86               {"EndFontMetrics", 		kEndFontMetrics},
  87               {"EndKernData", 		kEndKernData},
  88               {"EndKernPairs",		kEndKernPairs},
  89               {"EndMaster", 		kEndMaster},
  90               {"EndMasterFontMetrics", 	kEndMasterFontMetrics},
  91               {"EndTrackKern", 		kEndTrackKern},
  92               {"EscChar", 			kEscChar},
  93               {"FamilyName", 		kFamilyName},
  94               {"FontBBox", 			kFontBBox},
  95               {"FontName", 			kFontName},
  96               {"FullName", 			kFullName},
  97               {"IsBaseFont", 		kIsBaseFont},
  98               {"IsFixedPitch", 		kIsFixedPitch},
  99               {"IsFixedV", 			kIsFixedV},
 100               {"ItalicAngle", 		kItalicAngle},
 101               {"KP", 			kKP},
 102               {"KPH", 			kKPH},
 103               {"KPX", 			kKPX},
 104               {"KPY", 			kKPY},
 105               {"L",				kL},
 106 rizwank 1.1   {"MappingScheme", 		kMappingScheme},
 107               {"Masters", 			kMasters},
 108               {"MetricsSets", 		kMetricsSets},
 109               {"N",				kN},
 110               {"Notice", 			kNotice},
 111               {"PCC", 			kPCC},
 112               {"StartAxis", 		kStartAxis},
 113               {"StartCharMetrics", 		kStartCharMetrics},
 114               {"StartCompFontMetrics", 	kStartCompFontMetrics},
 115               {"StartComposites", 		kStartComposites},
 116               {"StartDescendent", 		kStartDescendent},
 117               {"StartDirection", 		kStartDirection},
 118               {"StartFontMetrics", 		kStartFontMetrics},
 119               {"StartKernData", 		kStartKernData},
 120               {"StartKernPairs",		kStartKernPairs},
 121               {"StartMaster", 		kStartMaster},
 122               {"StartMasterFontMetrics", 	kStartMasterFontMetrics},
 123               {"StartTrackKern", 		kStartTrackKern},
 124               {"TrackKern", 		kTrackKern},
 125               {"UnderlinePosition", 	kUnderlinePosition},
 126               {"UnderlineThickness", 	kUnderlineThickness},
 127 rizwank 1.1   {"VV",			kVV},
 128               {"VVector", 			kVVector},
 129               {"Version", 			kVersion},
 130               {"W",				kW},
 131               {"W0",			kW0},
 132               {"W0X",			kW0X},
 133               {"W0Y",			kW0Y},
 134               {"W1",			kW1},
 135               {"W1X",			kW1X},
 136               {"W1Y",			kW1Y},
 137               {"WX",			kWX},
 138               {"WY",			kWY},
 139               {"Weight", 			kWeight},
 140               {"WeightVector", 		kWeightVector},
 141               {"XHeight", 			kXHeight},
 142             
 143               {NULL, 0},
 144             };
 145             
 146             #define NUM_KEYS (sizeof (keynames) / sizeof (struct keyname_st) - 1)
 147             
 148 rizwank 1.1 /*
 149              * Prototypes for static functions.
 150              */
 151             
 152             /* Throw parse error <error>.  Never returns. */
 153             static void parse_error ___P ((AFMHandle handle, AFMError error));
 154             
 155             static int get_token ___P ((AFMHandle handle, ParseCtx *ctx));
 156             static int get_line_token ___P ((AFMHandle handle, ParseCtx *ctx));
 157             static void get_key ___P ((AFMHandle handle, ParseCtx *ctx,
 158             			   AFMKey *key_return));
 159             static void get_type ___P ((AFMHandle handle, ParseCtx *ctx, int type,
 160             			    AFMNode *type_return));
 161             static void read_character_metrics ___P ((AFMHandle handle, ParseCtx *ctx,
 162             					  AFMFont font));
 163             static void read_kern_pairs ___P ((AFMHandle handle, ParseCtx *ctx,
 164             				   AFMFont font));
 165             static void read_track_kerns ___P ((AFMHandle handle, ParseCtx *ctx,
 166             				    AFMFont font));
 167             static void read_composites ___P ((AFMHandle handle, ParseCtx *ctx,
 168             				   AFMFont font));
 169 rizwank 1.1 
 170             /*
 171              * Global functions.
 172              */
 173             
 174             void
 175             afm_parse_file (AFMHandle handle, const char *filename, AFMFont font)
 176             {
 177               AFMKey key;
 178               AFMNode node;
 179               ParseCtx context;
 180               ParseCtx *ctx = &context;
 181               int wd = 0;			/* Writing direction. */
 182               int done = 0;
 183             
 184               ctx->fp = fopen (filename, "r");
 185               if (ctx->fp == NULL)
 186                 parse_error (handle, SYSERROR (AFM_ERROR_FILE_IO));
 187             
 188               /* Check that file is really an AFM file. */
 189             
 190 rizwank 1.1   get_key (handle, ctx, &key);
 191               if (key != kStartFontMetrics)
 192                 parse_error (handle, AFM_ERROR_NOT_AFM_FILE);
 193               GET_VALUE (AFM_TYPE_NUMBER);
 194               font->version = node.u.number;
 195             
 196               /* Parse it. */
 197               while (!done)
 198                 {
 199                   get_key (handle, ctx, &key);
 200                   switch (key)
 201             	{
 202             	case kComment:
 203             	  (void) get_line_token (handle, ctx);
 204             	  continue;
 205             	  break;
 206             
 207             	  /* File structure. */
 208             
 209             	case kStartFontMetrics:
 210             	  GET_VALUE (AFM_TYPE_NUMBER);
 211 rizwank 1.1 	  font->version = node.u.number;
 212             	  break;
 213             
 214             	case kEndFontMetrics:
 215             	  done = 1;
 216             	  break;
 217             
 218             	case kStartCompFontMetrics:
 219             	case kEndCompFontMetrics:
 220             	case kStartMasterFontMetrics:
 221             	case kEndMasterFontMetrics:
 222             	  parse_error (handle, AFM_ERROR_UNSUPPORTED_FORMAT);
 223             	  break;
 224             
 225             	  /* Global font information. */
 226             	case kFontName:
 227             	  GET_VALUE (AFM_TYPE_STRING);
 228             	  font->global_info.FontName = node.u.string;
 229             	  break;
 230             
 231             	case kFullName:
 232 rizwank 1.1 	  GET_VALUE (AFM_TYPE_STRING);
 233             	  font->global_info.FullName = node.u.string;
 234             	  break;
 235             
 236             	case kFamilyName:
 237             	  GET_VALUE (AFM_TYPE_STRING);
 238             	  font->global_info.FamilyName = node.u.string;
 239             	  break;
 240             
 241             	case kWeight:
 242             	  GET_VALUE (AFM_TYPE_STRING);
 243             	  font->global_info.Weight = node.u.string;
 244             	  break;
 245             
 246             	case kFontBBox:
 247             	  GET_VALUE (AFM_TYPE_NUMBER);
 248             	  font->global_info.FontBBox_llx = node.u.number;
 249             	  GET_VALUE (AFM_TYPE_NUMBER);
 250             	  font->global_info.FontBBox_lly = node.u.number;
 251             	  GET_VALUE (AFM_TYPE_NUMBER);
 252             	  font->global_info.FontBBox_urx = node.u.number;
 253 rizwank 1.1 	  GET_VALUE (AFM_TYPE_NUMBER);
 254             	  font->global_info.FontBBox_ury = node.u.number;
 255             	  break;
 256             
 257             	case kVersion:
 258             	  GET_VALUE (AFM_TYPE_STRING);
 259             	  font->global_info.Version = node.u.string;
 260             	  break;
 261             
 262             	case kNotice:
 263             	  GET_VALUE (AFM_TYPE_STRING);
 264             	  font->global_info.Notice = node.u.string;
 265             	  break;
 266             
 267             	case kEncodingScheme:
 268             	  GET_VALUE (AFM_TYPE_STRING);
 269             	  font->global_info.EncodingScheme = node.u.string;
 270             	  break;
 271             
 272             	case kMappingScheme:
 273             	  GET_VALUE (AFM_TYPE_INTEGER);
 274 rizwank 1.1 	  font->global_info.MappingScheme = node.u.integer;
 275             	  break;
 276             
 277             	case kEscChar:
 278             	  GET_VALUE (AFM_TYPE_INTEGER);
 279             	  font->global_info.EscChar = node.u.integer;
 280             	  break;
 281             
 282             	case kCharacterSet:
 283             	  GET_VALUE (AFM_TYPE_STRING);
 284             	  font->global_info.CharacterSet = node.u.string;
 285             	  break;
 286             
 287             	case kCharacters:
 288             	  GET_VALUE (AFM_TYPE_INTEGER);
 289             	  font->global_info.Characters = node.u.integer;
 290             	  break;
 291             
 292             	case kIsBaseFont:
 293             	  GET_VALUE (AFM_TYPE_BOOLEAN);
 294             	  font->global_info.IsBaseFont = node.u.boolean;
 295 rizwank 1.1 	  break;
 296             
 297             	case kVVector:
 298             	  GET_VALUE (AFM_TYPE_NUMBER);
 299             	  font->global_info.VVector_0 = node.u.number;
 300             	  GET_VALUE (AFM_TYPE_NUMBER);
 301             	  font->global_info.VVector_1 = node.u.number;
 302             	  break;
 303             
 304             	case kIsFixedV:
 305             	  GET_VALUE (AFM_TYPE_BOOLEAN);
 306             	  font->global_info.IsFixedV = node.u.boolean;
 307             	  break;
 308             
 309             	case kCapHeight:
 310             	  GET_VALUE (AFM_TYPE_NUMBER);
 311             	  font->global_info.CapHeight = node.u.number;
 312             	  break;
 313             
 314             	case kXHeight:
 315             	  GET_VALUE (AFM_TYPE_NUMBER);
 316 rizwank 1.1 	  font->global_info.XHeight = node.u.number;
 317             	  break;
 318             
 319             	case kAscender:
 320             	  GET_VALUE (AFM_TYPE_NUMBER);
 321             	  font->global_info.Ascender = node.u.number;
 322             	  break;
 323             
 324             	case kDescender:
 325             	  GET_VALUE (AFM_TYPE_NUMBER);
 326             	  font->global_info.Descender = node.u.number;
 327             	  break;
 328             
 329             	  /* Writing directions. */
 330             	case kStartDirection:
 331             	  GET_VALUE (AFM_TYPE_INTEGER);
 332             	  wd = node.u.integer;
 333             	  font->writing_direction_metrics[wd].is_valid = AFMTrue;
 334             	  break;
 335             
 336             	case kUnderlinePosition:
 337 rizwank 1.1 	  GET_VALUE (AFM_TYPE_NUMBER);
 338             	  font->writing_direction_metrics[wd].UnderlinePosition
 339             	    = node.u.number;
 340             	  break;
 341             
 342             	case kUnderlineThickness:
 343             	  GET_VALUE (AFM_TYPE_NUMBER);
 344             	  font->writing_direction_metrics[wd].UnderlineThickness
 345             	    = node.u.number;
 346             	  break;
 347             
 348             	case kItalicAngle:
 349             	  GET_VALUE (AFM_TYPE_NUMBER);
 350             	  font->writing_direction_metrics[wd].ItalicAngle = node.u.number;
 351             	  break;
 352             
 353             	case kCharWidth:
 354             	  GET_VALUE (AFM_TYPE_NUMBER);
 355             	  font->writing_direction_metrics[wd].CharWidth_x = node.u.number;
 356             	  GET_VALUE (AFM_TYPE_NUMBER);
 357             	  font->writing_direction_metrics[wd].CharWidth_y = node.u.number;
 358 rizwank 1.1 	  break;
 359             
 360             	case kIsFixedPitch:
 361             	  GET_VALUE (AFM_TYPE_BOOLEAN);
 362             	  font->writing_direction_metrics[wd].IsFixedPitch = node.u.boolean;
 363             	  break;
 364             
 365             	case kEndDirection:
 366             	  break;
 367             
 368             	  /* Individual Character Metrics. */
 369             	case kStartCharMetrics:
 370             	  GET_VALUE (AFM_TYPE_INTEGER);
 371             	  font->num_character_metrics = node.u.integer;
 372             	  font->character_metrics
 373             	    = ((AFMIndividualCharacterMetrics *)
 374             	       calloc (font->num_character_metrics + 1,
 375             		       sizeof (AFMIndividualCharacterMetrics)));
 376             	  if (font->character_metrics == NULL)
 377             	    parse_error (handle, AFM_ERROR_MEMORY);
 378             
 379 rizwank 1.1 	  read_character_metrics (handle, ctx, font);
 380             	  break;
 381             
 382             	  /* Kerning Data. */
 383             	case kStartKernData:
 384             	  break;
 385             
 386             	case kStartKernPairs:
 387             	  if (font->info_level & AFM_I_KERN_PAIRS)
 388             	    {
 389             	      GET_VALUE (AFM_TYPE_INTEGER);
 390             	      font->num_kern_pairs = node.u.integer;
 391             	      font->kern_pairs =
 392             		(AFMPairWiseKerning *) calloc (font->num_kern_pairs + 1,
 393             					       sizeof (AFMPairWiseKerning));
 394             	      if (font->kern_pairs == NULL)
 395             		parse_error (handle, AFM_ERROR_MEMORY);
 396             
 397             	      read_kern_pairs (handle, ctx, font);
 398             	    }
 399             	  else
 400 rizwank 1.1 	    {
 401             	      do
 402             		{
 403             		  (void) get_line_token (handle, ctx);
 404             		  get_key (handle, ctx, &key);
 405             		}
 406             	      while (key != kEndKernPairs);
 407             	    }
 408             	  break;
 409             
 410             	case kStartTrackKern:
 411             	  if (font->info_level & AFM_I_TRACK_KERNS)
 412             	    {
 413             	      GET_VALUE (AFM_TYPE_INTEGER);
 414             	      font->num_track_kerns = node.u.integer;
 415             	      font->track_kerns
 416             		= (AFMTrackKern *) calloc (font->num_track_kerns + 1,
 417             					   sizeof (AFMTrackKern));
 418             	      if (font->track_kerns == NULL)
 419             		parse_error (handle, AFM_ERROR_MEMORY);
 420             
 421 rizwank 1.1 	      read_track_kerns (handle, ctx, font);
 422             	    }
 423             	  else
 424             	    {
 425             	      do
 426             		{
 427             		  (void) get_line_token (handle, ctx);
 428             		  get_key (handle, ctx, &key);
 429             		}
 430             	      while (key != kEndTrackKern);
 431             	    }
 432             	  break;
 433             
 434             	case kEndKernData:
 435             	  break;
 436             
 437             	  /* Composite Character Data. */
 438             	case kStartComposites:
 439             	  if (font->info_level & AFM_I_COMPOSITES)
 440             	    {
 441             	      GET_VALUE (AFM_TYPE_INTEGER);
 442 rizwank 1.1 	      font->num_composites = node.u.integer;
 443             	      font->composites
 444             		= (AFMComposite *) calloc (font->num_composites + 1,
 445             					   sizeof (AFMComposite));
 446             	      if (font->composites == NULL)
 447             		parse_error (handle, AFM_ERROR_MEMORY);
 448             
 449             	      read_composites (handle, ctx, font);
 450             	    }
 451             	  else
 452             	    {
 453             	      do
 454             		{
 455             		  (void) get_line_token (handle, ctx);
 456             		  get_key (handle, ctx, &key);
 457             		}
 458             	      while (key != kEndComposites);
 459             	    }
 460             	  break;
 461             
 462             	default:
 463 rizwank 1.1 	  /* Ignore. */
 464             	  break;
 465             	}
 466                 }
 467               fclose (ctx->fp);
 468             
 469               /* Check post conditions. */
 470             
 471               if (!font->writing_direction_metrics[0].is_valid
 472                   && !font->writing_direction_metrics[1].is_valid)
 473                 /* No direction specified, 0 implied. */
 474                 font->writing_direction_metrics[0].is_valid = AFMTrue;
 475             
 476               /* Undef character. */
 477               if (!strhash_get (font->private->fontnames, "space", 5,
 478             		    (void *) font->private->undef))
 479                 {
 480                   /* Character "space" is not defined.  Select the first one. */
 481                   assert (font->num_character_metrics > 0);
 482                   font->private->undef = &font->character_metrics[0];
 483                 }
 484 rizwank 1.1 
 485               /* Fixed pitch. */
 486               if (font->writing_direction_metrics[0].is_valid
 487                   && font->writing_direction_metrics[0].IsFixedPitch)
 488                 {
 489                   /* Take one, it doesn't matter which one. */
 490                   font->writing_direction_metrics[0].CharWidth_x
 491             	= font->character_metrics[0].w0x;
 492                   font->writing_direction_metrics[0].CharWidth_y
 493             	= font->character_metrics[0].w0y;
 494                 }
 495               if (font->writing_direction_metrics[1].is_valid
 496                   && font->writing_direction_metrics[1].IsFixedPitch)
 497                 {
 498                   font->writing_direction_metrics[1].CharWidth_x
 499             	= font->character_metrics[1].w1x;
 500                   font->writing_direction_metrics[1].CharWidth_y
 501             	= font->character_metrics[1].w1y;
 502                 }
 503             }
 504             
 505 rizwank 1.1 
 506             /*
 507              * Static functions.
 508              */
 509             
 510             static void
 511             parse_error (AFMHandle handle, AFMError error)
 512             {
 513               handle->parse_error = error;
 514               longjmp (handle->jmpbuf, 1);
 515             
 516               /* If this is reached, then all is broken. */
 517               fprintf (stderr, "AFM: fatal internal longjmp() error.\n");
 518               abort ();
 519             }
 520             
 521             
 522             static int
 523             get_token (AFMHandle handle, ParseCtx *ctx)
 524             {
 525               int ch;
 526 rizwank 1.1   int i;
 527             
 528               /* Skip the leading whitespace. */
 529               while ((ch = getc (ctx->fp)) != EOF)
 530                 if (!ISSPACE (ch))
 531                   break;
 532             
 533               if (ch == EOF)
 534                 return 0;
 535             
 536               ungetc (ch, ctx->fp);
 537             
 538               /* Get name. */
 539               for (i = 0, ch = getc (ctx->fp);
 540                    i < sizeof (ctx->token) && ch != EOF && !ISSPACE (ch);
 541                    i++, ch = getc (ctx->fp))
 542                 ctx->token[i] = ch;
 543             
 544               if (i >= sizeof (ctx->token))
 545                 /* Line is too long, this is against AFM specification. */
 546                 parse_error (handle, AFM_ERROR_SYNTAX);
 547 rizwank 1.1 
 548               ctx->token[i] = '\0';
 549               ctx->tokenlen = i;
 550             
 551               return 1;
 552             }
 553             
 554             
 555             static int
 556             get_line_token (AFMHandle handle, ParseCtx *ctx)
 557             {
 558               int i, ch;
 559             
 560               /* Skip the leading whitespace. */
 561               while ((ch = getc (ctx->fp)) != EOF)
 562                 if (!ISSPACE (ch))
 563                   break;
 564             
 565               if (ch == EOF)
 566                 return 0;
 567             
 568 rizwank 1.1   ungetc (ch, ctx->fp);
 569             
 570               /* Read to the end of the line. */
 571               for (i = 0, ch = getc (ctx->fp);
 572                    i < sizeof (ctx->token) && ch != EOF && ch != '\n';
 573                    i++, ch = getc (ctx->fp))
 574                 ctx->token[i] = ch;
 575             
 576               if (i >= sizeof (ctx->token))
 577                 parse_error (handle, AFM_ERROR_SYNTAX);
 578             
 579               /* Skip all trailing whitespace. */
 580               for (i--; i >= 0 && ISSPACE (ctx->token[i]); i--)
 581                 ;
 582               i++;
 583             
 584               ctx->token[i] = '\0';
 585               ctx->tokenlen = i;
 586             
 587               return 1;
 588             }
 589 rizwank 1.1 
 590             
 591             static int
 592             match_key (char *key)
 593             {
 594               int lower = 0;
 595               int upper = NUM_KEYS;
 596               int midpoint, cmpvalue;
 597               AFMBoolean found = AFMFalse;
 598             
 599               while ((upper >= lower) && !found)
 600                 {
 601                   midpoint = (lower + upper) / 2;
 602                   if (keynames[midpoint].name == NULL)
 603             	break;
 604             
 605                   cmpvalue = strcmp (key, keynames[midpoint].name);
 606                   if (cmpvalue == 0)
 607             	found = AFMTrue;
 608                   else if (cmpvalue < 0)
 609             	upper = midpoint - 1;
 610 rizwank 1.1       else
 611             	lower = midpoint + 1;
 612                 }
 613             
 614               if (found)
 615                 return keynames[midpoint].key;
 616             
 617               return -1;
 618             }
 619             
 620             
 621             static void
 622             get_key (AFMHandle handle, ParseCtx *ctx, AFMKey *key_return)
 623             {
 624               int key;
 625               char msg[256];
 626             
 627               while (1)
 628                 {
 629                   if (!get_token (handle, ctx))
 630             	/* Unexpected EOF. */
 631 rizwank 1.1 	parse_error (handle, AFM_ERROR_SYNTAX);
 632             
 633                   key = match_key (ctx->token);
 634                   if (key >= 0)
 635             	{
 636             	  *key_return = key;
 637             	  return;
 638             	}
 639             
 640                   /* No match found.  According to standard, we must skip this key. */
 641                   sprintf (msg, "skipping key \"%s\"", ctx->token);
 642                   afm_error (handle, msg);
 643                   get_line_token (handle, ctx);
 644                 }
 645             
 646               /* NOTREACHED */
 647             }
 648             
 649             
 650             /* Reader for AFM types. */
 651             static void
 652 rizwank 1.1 get_type (AFMHandle handle, ParseCtx *ctx, int type, AFMNode *type_return)
 653             {
 654               char buf[256];
 655             
 656               switch (type)
 657                 {
 658                 case AFM_TYPE_STRING:
 659                   if (!get_line_token (handle, ctx))
 660             	parse_error (handle, AFM_ERROR_SYNTAX);
 661             
 662                   type_return->u.string = (AFMString) calloc (1, ctx->tokenlen + 1);
 663                   if (type_return->u.string == NULL)
 664             	parse_error (handle, AFM_ERROR_MEMORY);
 665             
 666                   memcpy (type_return->u.string, ctx->token, ctx->tokenlen);
 667                   break;
 668             
 669                 case AFM_TYPE_NAME:
 670                   if (!get_token (handle, ctx))
 671             	parse_error (handle, AFM_ERROR_SYNTAX);
 672             
 673 rizwank 1.1       type_return->u.name = (AFMName) calloc (1, ctx->tokenlen + 1);
 674                   if (type_return->u.string == NULL)
 675             	parse_error (handle, AFM_ERROR_MEMORY);
 676             
 677                   memcpy (type_return->u.name, ctx->token, ctx->tokenlen);
 678                   break;
 679             
 680                 case AFM_TYPE_NUMBER:
 681                   if (!get_token (handle, ctx))
 682             	parse_error (handle, AFM_ERROR_SYNTAX);
 683             
 684                   memcpy (buf, ctx->token, ctx->tokenlen);
 685                   buf[ctx->tokenlen] = '\0';
 686                   type_return->u.number = atof (buf);
 687                   break;
 688             
 689                 case AFM_TYPE_INTEGER:
 690                   if (!get_token (handle, ctx))
 691             	parse_error (handle, AFM_ERROR_SYNTAX);
 692             
 693                   memcpy (buf, ctx->token, ctx->tokenlen);
 694 rizwank 1.1       buf[ctx->tokenlen] = '\0';
 695                   type_return->u.integer = atoi (buf);
 696                   break;
 697             
 698                 case AFM_TYPE_ARRAY:
 699                   fprintf (stderr, "Array types not implemented yet.\n");
 700                   abort ();
 701                   break;
 702             
 703                 case AFM_TYPE_BOOLEAN:
 704                   if (!get_token (handle, ctx))
 705             	parse_error (handle, AFM_ERROR_SYNTAX);
 706             
 707                   memcpy (buf, ctx->token, ctx->tokenlen);
 708                   buf[ctx->tokenlen] = '\0';
 709             
 710                   if (strcmp (buf, "true") == 0)
 711             	type_return->u.boolean = AFMTrue;
 712                   else if (strcmp (buf, "false") == 0)
 713             	type_return->u.boolean = AFMFalse;
 714                   else
 715 rizwank 1.1 	parse_error (handle, AFM_ERROR_SYNTAX);
 716                   break;
 717             
 718                 default:
 719                   fprintf (stderr, "get_type(): illegal type %d\n", type_return->type);
 720                   abort ();
 721                   break;
 722                 }
 723             }
 724             
 725             
 726             static void
 727             read_character_metrics (AFMHandle handle, ParseCtx *ctx, AFMFont font)
 728             {
 729               int i = 0;
 730               AFMNode node;
 731               AFMIndividualCharacterMetrics *cm = NULL;
 732               AFMKey key;
 733               int done = 0;
 734               int first = 1;
 735             
 736 rizwank 1.1   while (!done)
 737                 {
 738                   get_key (handle, ctx, &key);
 739                   switch (key)
 740             	{
 741             	case kC:
 742             	  if (first)
 743             	    first = 0;
 744             	  else
 745             	    i++;
 746             	  if (i >= font->num_character_metrics)
 747             	    parse_error (handle, AFM_ERROR_SYNTAX);
 748             
 749             	  cm = &font->character_metrics[i];
 750             	  GET_VALUE (AFM_TYPE_INTEGER);
 751             	  cm->character_code = node.u.integer;
 752             	  if (cm->character_code >= 0 && cm->character_code <= 255)
 753             	    font->encoding[cm->character_code] = cm;
 754             	  break;
 755             
 756             	case kCH:
 757 rizwank 1.1 	  printf ("* CH\n");
 758             	  break;
 759             
 760             	case kWX:
 761             	case kW0X:
 762             	  GET_VALUE (AFM_TYPE_NUMBER);
 763             	  cm->w0x = node.u.number;
 764             	  cm->w0y = 0.0;
 765             	  break;
 766             
 767             	case kW1X:
 768             	  GET_VALUE (AFM_TYPE_NUMBER);
 769             	  cm->w1x = node.u.number;
 770             	  cm->w1y = 0.0;
 771             	  break;
 772             
 773             	case kWY:
 774             	case kW0Y:
 775             	  GET_VALUE (AFM_TYPE_NUMBER);
 776             	  cm->w0y = node.u.number;
 777             	  cm->w0x = 0.0;
 778 rizwank 1.1 	  break;
 779             
 780             	case kW1Y:
 781             	  GET_VALUE (AFM_TYPE_NUMBER);
 782             	  cm->w1y = node.u.number;
 783             	  cm->w1x = 0.0;
 784             	  break;
 785             
 786             	case kW:
 787             	case kW0:
 788             	  GET_VALUE (AFM_TYPE_NUMBER);
 789             	  cm->w0x = node.u.number;
 790             	  GET_VALUE (AFM_TYPE_NUMBER);
 791             	  cm->w0y = node.u.number;
 792             	  break;
 793             
 794             	case kW1:
 795             	  GET_VALUE (AFM_TYPE_NUMBER);
 796             	  cm->w1x = node.u.number;
 797             	  GET_VALUE (AFM_TYPE_NUMBER);
 798             	  cm->w1y = node.u.number;
 799 rizwank 1.1 	  break;
 800             
 801             	case kVV:
 802             	  GET_VALUE (AFM_TYPE_NUMBER);
 803             	  cm->vv_x = node.u.number;
 804             	  GET_VALUE (AFM_TYPE_NUMBER);
 805             	  cm->vv_y = node.u.number;
 806             	  break;
 807             
 808             	case kN:
 809             	  GET_VALUE (AFM_TYPE_NAME);
 810             	  cm->name = node.u.name;
 811             	  if (!strhash_put (font->private->fontnames, cm->name,
 812             			    strlen (cm->name), cm, NULL))
 813             	    parse_error (handle, AFM_ERROR_MEMORY);
 814             	  break;
 815             
 816             	case kB:
 817             	  GET_VALUE (AFM_TYPE_NUMBER);
 818             	  cm->llx = node.u.number;
 819             	  GET_VALUE (AFM_TYPE_NUMBER);
 820 rizwank 1.1 	  cm->lly = node.u.number;
 821             	  GET_VALUE (AFM_TYPE_NUMBER);
 822             	  cm->urx = node.u.number;
 823             	  GET_VALUE (AFM_TYPE_NUMBER);
 824             	  cm->ury = node.u.number;
 825             	  break;
 826             
 827             	case kL:
 828             	  /* XXX Skip ligatures. */
 829             	  get_line_token (handle, ctx);
 830             	  break;
 831             
 832             	case kEndCharMetrics:
 833             	  if (i != font->num_character_metrics - 1)
 834             	    {
 835             	      /*
 836             	       * My opinion is that this is a syntax error; the
 837             	       * creator of this AFM file should have been smart
 838             	       * enought to count these character metrics.  Well,
 839             	       * maybe that is too much asked...
 840             	       */
 841 rizwank 1.1 	      font->num_character_metrics = i + 1;
 842             	    }
 843             
 844             	  done = 1;
 845             	  break;
 846             
 847             	default:
 848             	  parse_error (handle, AFM_ERROR_SYNTAX);
 849             	  break;
 850             	}
 851                 }
 852             }
 853             
 854             
 855             static void
 856             read_kern_pairs (AFMHandle handle, ParseCtx *ctx, AFMFont font)
 857             {
 858               int i;
 859               AFMNode node;
 860               AFMPairWiseKerning *kp;
 861               AFMKey key;
 862 rizwank 1.1 
 863               for (i = 0; i < font->num_kern_pairs; i++)
 864                 {
 865                   kp = &font->kern_pairs[i];
 866                   get_key (handle, ctx, &key);
 867             
 868                   switch (key)
 869             	{
 870             	case kKP:
 871             	case kKPX:
 872             	case kKPY:
 873             	  GET_VALUE (AFM_TYPE_NAME);
 874             	  kp->name1 = node.u.name;
 875             
 876             	  GET_VALUE (AFM_TYPE_NAME);
 877             	  kp->name2 = node.u.name;
 878             
 879             	  GET_VALUE (AFM_TYPE_NUMBER);
 880             
 881             	  switch (key)
 882             	    {
 883 rizwank 1.1 	    case kKP:
 884             	      kp->kx = node.u.number;
 885             	      GET_VALUE (AFM_TYPE_NUMBER);
 886             	      kp->ky = node.u.number;
 887             	      break;
 888             
 889             	    case kKPX:
 890             	      kp->kx = node.u.number;
 891             	      kp->ky = 0.0;
 892             	      break;
 893             
 894             	    case kKPY:
 895             	      kp->ky = node.u.number;
 896             	      kp->kx = 0.0;
 897             	      break;
 898             
 899             	    default:
 900             	      fprintf (stderr, "AFM: fatal corruption\n");
 901             	      abort ();
 902             	      break;
 903             	    }
 904 rizwank 1.1 	  break;
 905             
 906             	case kKPH:
 907             	  /* XXX ignore. */
 908             	  break;
 909             
 910             	default:
 911             	  parse_error (handle, AFM_ERROR_SYNTAX);
 912             	  break;
 913             	}
 914                 }
 915             
 916               /* Get end token. */
 917               get_key (handle, ctx, &key);
 918               if (key != kEndKernPairs)
 919                 parse_error (handle, AFM_ERROR_SYNTAX);
 920             }
 921             
 922             
 923             static void
 924             read_track_kerns (AFMHandle handle, ParseCtx *ctx, AFMFont font)
 925 rizwank 1.1 {
 926               int i;
 927               AFMNode node;
 928               AFMTrackKern *tk;
 929               AFMKey key;
 930             
 931               for (i = 0; i < font->num_kern_pairs; i++)
 932                 {
 933                   tk = &font->track_kerns[i];
 934                   get_key (handle, ctx, &key);
 935             
 936                   /* TrackKern degree min-ptsize min-kern max-ptrsize max-kern */
 937             
 938                   if (key != kTrackKern)
 939             	parse_error (handle, AFM_ERROR_SYNTAX);
 940             
 941                   GET_VALUE (AFM_TYPE_INTEGER);
 942                   tk->degree = node.u.integer;
 943             
 944                   GET_VALUE (AFM_TYPE_NUMBER);
 945                   tk->min_ptsize = node.u.number;
 946 rizwank 1.1 
 947                   GET_VALUE (AFM_TYPE_NUMBER);
 948                   tk->min_kern = node.u.number;
 949             
 950                   GET_VALUE (AFM_TYPE_NUMBER);
 951                   tk->max_ptsize = node.u.number;
 952             
 953                   GET_VALUE (AFM_TYPE_NUMBER);
 954                   tk->max_kern = node.u.number;
 955                 }
 956             
 957               /* Get end token. */
 958               get_key (handle, ctx, &key);
 959               if (key != kEndTrackKern)
 960                 parse_error (handle, AFM_ERROR_SYNTAX);
 961             }
 962             
 963             
 964             static void
 965             read_composites (AFMHandle handle, ParseCtx *ctx, AFMFont font)
 966             {
 967 rizwank 1.1   int i, j;
 968               AFMNode node;
 969               AFMComposite *cm;
 970               AFMKey key;
 971             
 972               for (i = 0; i < font->num_composites; i++)
 973                 {
 974                   cm = &font->composites[i];
 975                   get_key (handle, ctx, &key);
 976             
 977                   if (key != kCC)
 978             	parse_error (handle, AFM_ERROR_SYNTAX);
 979             
 980                   GET_VALUE (AFM_TYPE_NAME);
 981                   cm->name = node.u.name;
 982             
 983                   /* Create name -> AFMComposite mapping. */
 984                   if (!strhash_put (font->private->compositenames, cm->name,
 985             			strlen (cm->name), cm, NULL))
 986             	parse_error (handle, AFM_ERROR_MEMORY);
 987             
 988 rizwank 1.1       GET_VALUE (AFM_TYPE_INTEGER);
 989                   cm->num_components = node.u.integer;
 990                   cm->components
 991             	= (AFMCompositeComponent *) calloc (cm->num_components + 1,
 992             					    sizeof (AFMCompositeComponent));
 993             
 994                   /* Read composite components. */
 995                   for (j = 0; j < cm->num_components; j++)
 996             	{
 997             	  /* Read "PCC". */
 998             	  get_key (handle, ctx, &key);
 999             	  if (key != kPCC)
1000             	    parse_error (handle, AFM_ERROR_SYNTAX);
1001             
1002             	  /* Read values. */
1003             
1004             	  GET_VALUE (AFM_TYPE_NAME);
1005             	  cm->components[j].name = node.u.name;
1006             
1007             	  GET_VALUE (AFM_TYPE_NUMBER);
1008             	  cm->components[j].deltax = node.u.number;
1009 rizwank 1.1 
1010             	  GET_VALUE (AFM_TYPE_NUMBER);
1011             	  cm->components[j].deltay = node.u.number;
1012             	}
1013                 }
1014             
1015               /* Get end token. */
1016               get_key (handle, ctx, &key);
1017               if (key != kEndComposites)
1018                 parse_error (handle, AFM_ERROR_SYNTAX);
1019             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2