/*
 
mmafm.c

M Goossens, S Rahtz June 10th 1995

read multiple master AFM files, apply weight factor
and write instance AFM

derived from parseAFMclient.c:
 * (C) 1988, 1989 by Adobe Systems Incorporated. All rights reserved.
 *
 * This file may be freely copied and redistributed as long as:
 *   1) This entire notice continues to be included in the file, 
 *   2) If the file has been modified in any way, a notice of such
 *      modification is conspicuously indicated.
 *
 * PostScript, Display PostScript, and Adobe are registered trademarks of
 * Adobe Systems Incorporated.
........
 * History:
 *	original: DSM  Thu Oct 20 17:39:59 PDT 1988
 *  modified: DSM  Mon Jul  3 14:17:50 PDT 1989
 *    - added 'storageProblem' check in main
 */

#define lineterm EOL	/* line terminating character */
#define MAXMM 16
#include <stdio.h>
#include "parseAFM.h"
static char *ident = NULL; /* storage buffer for keywords */


/*************************** GLOBALS ***************************/
FontInfo *fi, *otherfi;
FLAGS myflags = 0;
  

/*************************** printGlobals **********************/

printGlobals()
{
    printf("StartFontMetrics %s\n", fi->gfi->afmVersion);
    printf("FontName %s\n", fi->gfi->fontName);
    printf("FullName %s\n", fi->gfi->fullName);
    printf("FamilyName %s\n", fi->gfi->familyName);
    printf("Weight %s\n", fi->gfi->weight);
    printf("ItalicAngle %f\n", fi->gfi->italicAngle);
    if (fi->gfi->isFixedPitch)
        printf("IsFixedPitch true\n");
    else
        printf("IsFixedPitch false\n");
    printf("UnderlinePosition %d\n", fi->gfi->underlinePosition);
    printf("UnderlineThickness %d\n", fi->gfi->underlineThickness);
    printf("Version %s\n", fi->gfi->version);
    printf("FontBBox %d %d %d %d\n", 
        fi->gfi->fontBBox.llx, fi->gfi->fontBBox.lly, 
        fi->gfi->fontBBox.urx, fi->gfi->fontBBox.ury);
    printf("Notice %s\n", fi->gfi->notice);
    printf("EncodingScheme %s\n", fi->gfi->encodingScheme);
    printf("CapHeight %d\n", fi->gfi->capHeight);
    printf("XHeight %d\n", fi->gfi->xHeight);
    printf("Descender %d\n", fi->gfi->descender);
    printf("Ascender %d\n", fi->gfi->ascender);
    
} /* printGlobals */


/*************************** printCharWidths *********************/
printCharWidths()
{
    int i = 0;
    for (i = 0; i < 256; ++i)
        printf("  code: %3d   width: %4d\n", i, fi->cwi[i]);
    printf("\n");
 
} /* printCharWidths */


/*************************** printAllCharMetrics *****************/
printAllCharMetrics()
{
    int i = 0;
    CharMetricInfo *temp = fi->cmi;
    Ligature *node = temp->ligs;
   printf("StartCharMetrics %d\n", fi->numOfChars);
    for (i = 0; i < fi->numOfChars; ++i)
    {
        printf(
          "C %d ; WX %d ; N %s ; B %d %d %d %d ;",
            temp->code, temp->wx, temp->name, temp->charBBox.llx, 
            temp->charBBox.lly, temp->charBBox.urx, temp->charBBox.ury);
        for (node = temp->ligs; node != NULL; node = node->next)
        {
            printf(" L %s %s ;",  node->succ, node->lig);
        }
        printf("\n");
        temp++;
    } /* for */
    printf("EndCharMetrics\n");

} /* printAllCharMetrics */


/*************************** printKernPairData ******************/
printKernPairData()
{
    int i = 0;
    PairKernData *pkd = fi->pkd;
    
    if (fi->numOfPairs != 0)
    {
        printf("StartKernData\n");
        printf("StartKernPairs %d\n",fi->numOfPairs);
        for (i = 0; i < fi->numOfPairs; ++i)
        printf(
          "KPX %s %s %d\n", 
            pkd[i].name1, pkd[i].name2, pkd[i].xamt);
/*          "KPX %s %s %d %d\n", 
            pkd[i].name1, pkd[i].name2, pkd[i].xamt, pkd[i].yamt); */
        printf("EndKernPairs\n");
        printf("EndKernData\n");
    }
    
} /* printKernPairData */


/*************************** printKernTrackData *******************/
printKernTrackData()
{
    int i = 0;
    TrackKernData *tkd = fi->tkd;
    
    if (fi->numOfTracks != 0)
    {
        printf("StartTrackKern %d\n",fi->numOfTracks);
        for (i = 0; i < fi->numOfTracks; ++i)
            printf(
              "TrackKern %d %d %d %d %d\n", 
                tkd[i].degree, tkd[i].minPtSize, tkd[i].minKernAmt, 
                tkd[i].maxPtSize, tkd[i].maxKernAmt);
        printf("EndTrackKern\n");
    }
    
} /* printKernTrackData */


/*************************** printCompCharData ********************/
printCompCharData()
{
    int i = 0, j = 0;
    CompCharData *ccd = fi->ccd;
    
    if (fi->numOfComps != 0)
    {
        printf("StartComposites %d\n",fi->numOfComps);
        for (i = 0; i < fi->numOfComps; ++i)
        {
            printf("CC %s %d ;", 
                ccd[i].ccName, ccd[i].numOfPieces);
            for (j = 0; j < ccd[i].numOfPieces; ++j)
                printf(
                  " PCC %s %d %d ;", ccd[i].pieces[j].pccName, 
                    ccd[i].pieces[j].deltax, ccd[i].pieces[j].deltay);
            printf("\n");
        }
        printf("EndComposites\n");
    }
    
} /* printCompCharData */



/*************************** freeStorage ***********************/

freeStorage()
{
    if (fi != NULL)
    {
        if (fi->gfi != NULL)
        { 
            free(fi->gfi->afmVersion); fi->gfi->afmVersion = NULL;
            free(fi->gfi->fontName); fi->gfi->fontName = NULL;
            free(fi->gfi->fullName); fi->gfi->fullName = NULL;
            free(fi->gfi->familyName); fi->gfi->familyName = NULL;
            free(fi->gfi->weight); fi->gfi->weight = NULL;
            free(fi->gfi->version); fi->gfi->version = NULL;
            free(fi->gfi->notice); fi->gfi->notice = NULL;
            free(fi->gfi->encodingScheme); fi->gfi->encodingScheme = NULL;
            free(fi->gfi); fi->gfi = NULL;
        }
  
        if (fi->cwi != NULL)
        { free(fi->cwi); fi->cwi = NULL; }

        if (fi->cmi != NULL)
        { 
            int i = 0;
            CharMetricInfo *temp = fi->cmi;
            Ligature *node = temp->ligs;
            
            for (i = 0; i < fi->numOfChars; ++i)
            {
                for (node = temp->ligs; node != NULL; node = node->next)
                {
                    free(node->succ); node->succ = NULL;
                    free(node->lig); node->lig = NULL;
                }
                
                free(temp->name); temp->name = NULL;
                temp++;
            }
            
            free(fi->cmi); fi->cmi = NULL;
        }

        if (fi->tkd != NULL)
        { free(fi->tkd); fi->tkd = NULL; }
  
        if (fi->pkd != NULL)
        { 
            free(fi->pkd->name1); fi->pkd->name1 = NULL;
            free(fi->pkd->name2); fi->pkd->name2 = NULL;
            free(fi->pkd); fi->pkd = NULL;
        }

        if (fi->ccd != NULL)
        { 
            int i = 0, j = 0;
    	    CompCharData *ccd = fi->ccd;
    	    
    	    for (i = 0; i < fi->numOfComps; ++i)
    	    {
    	        for (j = 0; j < ccd[i].numOfPieces; ++j)
    	        {
    	            free(ccd[i].pieces[j].pccName); 
    	            ccd[i].pieces[j].pccName = NULL;
    	        }
    	        
    	        free(ccd[i].ccName); ccd[i].ccName = NULL;
    	    }
    
            free(fi->ccd); fi->ccd = NULL;
        }
        
        free(fi);

    } /* if */ 
  
} /* freeStorage */


/*************************** printValues **************************/

printValues()
{
    if (fi->gfi != NULL) printGlobals();
    if (fi->cmi != NULL) printAllCharMetrics();
    if (fi->pkd != NULL) printKernPairData();
    if (fi->tkd != NULL) printKernTrackData(); 
    if (fi->ccd != NULL) printCompCharData();
    printf("EndFontMetrics\n");
} /* printValues */


/*************************** sumValues **************************/

sumValues (FACTOR)
float FACTOR;
{
int i,j = 0;
CharMetricInfo *temp = fi->cmi;
CharMetricInfo *othertemp = otherfi->cmi;
PairKernData *pkd = fi->pkd;
PairKernData *otherpkd = otherfi->pkd;
TrackKernData *tkd = fi->tkd;
TrackKernData *othertkd = otherfi->tkd;
CompCharData *ccd = fi->ccd;
CompCharData *otherccd = otherfi->ccd;
    
fi->gfi->italicAngle += otherfi->gfi->italicAngle * FACTOR;
fi->gfi->underlinePosition += otherfi->gfi->underlinePosition * FACTOR;
fi->gfi->underlineThickness += otherfi->gfi->underlineThickness * FACTOR;
fi->gfi->fontBBox.llx += otherfi->gfi->fontBBox.llx * FACTOR;
fi->gfi->fontBBox.lly += otherfi->gfi->fontBBox.lly * FACTOR;
fi->gfi->fontBBox.urx += otherfi->gfi->fontBBox.urx * FACTOR;
fi->gfi->fontBBox.ury += otherfi->gfi->fontBBox.ury * FACTOR;
fi->gfi->capHeight += otherfi->gfi->capHeight * FACTOR;
fi->gfi->xHeight += otherfi->gfi->xHeight * FACTOR;
fi->gfi->descender += otherfi->gfi->descender * FACTOR;
fi->gfi->ascender += otherfi->gfi->ascender * FACTOR;


for (i = 0; i < fi->numOfChars; ++i)
    {
	temp->wx += othertemp->wx * FACTOR;
	temp->charBBox.llx += othertemp->charBBox.llx * FACTOR;
	temp->charBBox.lly += othertemp->charBBox.lly * FACTOR;
	temp->charBBox.urx += othertemp->charBBox.urx * FACTOR;
	temp->charBBox.ury += othertemp->charBBox.ury * FACTOR;
        temp++;
        othertemp++;
    } /* for */

   i = 0;
    
    if (fi->numOfPairs != 0)
    {
        for (i = 0; i < fi->numOfPairs; ++i)
		pkd[i].xamt += otherpkd[i].xamt * FACTOR;
    }
    

i = 0;
    
    if (fi->numOfTracks != 0)
    {
        for (i = 0; i < fi->numOfTracks; ++i)
	{
        tkd[i].degree += othertkd[i].degree * FACTOR;
	tkd[i].minPtSize += othertkd[i].minPtSize * FACTOR;
	tkd[i].minKernAmt += othertkd[i].minKernAmt * FACTOR;
        tkd[i].maxPtSize += othertkd[i].maxPtSize * FACTOR;
	tkd[i].maxKernAmt += othertkd[i].maxKernAmt * FACTOR;
	}
    }
    

i = 0;
j = 0;
    if (fi->numOfComps != 0)
    {
        for (i = 0; i < fi->numOfComps; ++i)
        {
            for (j = 0; j < ccd[i].numOfPieces; ++j)
		{
            ccd[i].pieces[j].deltax += otherccd[i].pieces[j].deltax * FACTOR;
    	    ccd[i].pieces[j].deltay += otherccd[i].pieces[j].deltay * FACTOR;
		}
        }
    }
   
}


/*************************** IniValues **************************/

IniValues (FACTOR)
float FACTOR;
{
int i,j = 0;
CharMetricInfo *temp = fi->cmi;
PairKernData *pkd =  fi->pkd;
TrackKernData *tkd = fi->tkd;
CompCharData *ccd = fi->ccd;
    
fi->gfi->italicAngle = fi->gfi->italicAngle * FACTOR;
fi->gfi->underlinePosition = fi->gfi->underlinePosition * FACTOR;
fi->gfi->underlineThickness = fi->gfi->underlineThickness * FACTOR;
fi->gfi->fontBBox.llx = fi->gfi->fontBBox.llx * FACTOR;
fi->gfi->fontBBox.lly = fi->gfi->fontBBox.lly * FACTOR;
fi->gfi->fontBBox.urx = fi->gfi->fontBBox.urx * FACTOR;
fi->gfi->fontBBox.ury = fi->gfi->fontBBox.ury * FACTOR;
fi->gfi->capHeight = fi->gfi->capHeight * FACTOR;
fi->gfi->xHeight = fi->gfi->xHeight * FACTOR;
fi->gfi->descender = fi->gfi->descender * FACTOR;
fi->gfi->ascender = fi->gfi->ascender * FACTOR;


for (i = 0; i < fi->numOfChars; ++i)
    {
	temp->wx = temp->wx * FACTOR;
	temp->charBBox.llx = temp->charBBox.llx * FACTOR;
	temp->charBBox.lly = temp->charBBox.lly * FACTOR;
	temp->charBBox.urx = temp->charBBox.urx * FACTOR;
	temp->charBBox.ury = temp->charBBox.ury * FACTOR;
        temp++;
    } /* for */

   i = 0;
    
    if (fi->numOfPairs != 0)
    {
        for (i = 0; i < fi->numOfPairs; ++i)
		pkd[i].xamt = pkd[i].xamt * FACTOR;
    }
    

i = 0;
    
    if (fi->numOfTracks != 0)
    {
        for (i = 0; i < fi->numOfTracks; ++i)
	{
        tkd[i].degree = tkd[i].degree * FACTOR;
	tkd[i].minPtSize = tkd[i].minPtSize * FACTOR;
	tkd[i].minKernAmt = tkd[i].minKernAmt * FACTOR;
        tkd[i].maxPtSize = tkd[i].maxPtSize * FACTOR;
	tkd[i].maxKernAmt = tkd[i].maxKernAmt * FACTOR;
	}
    }
    

i = 0;
j = 0;
    if (fi->numOfComps != 0)
    {
        for (i = 0; i < fi->numOfComps; ++i)
        {
            for (j = 0; j < ccd[i].numOfPieces; ++j)
		{
            ccd[i].pieces[j].deltax = ccd[i].pieces[j].deltax * FACTOR;
    	    ccd[i].pieces[j].deltay = ccd[i].pieces[j].deltay * FACTOR;
		}
        }
    }
   
}


/*************************** main *********************************/

main (argc, argv) 
  int argc; 
  char **argv;
{

    char *filename, *prog = *argv;
    FILE *fp, *fpmain;
    char mastafm[MAXMM][128];
    char Line[128];
    char newafm[128];
    float Weight;
    int NofM, i, j, k, l;
    
    ++argv; --argc; myflags |= P_ALL; 

    if (!argc)
    {
                printf("    usage: parseAFM [AFM File]\n");
                exit(0);
    }
    else 
        filename = *argv;

    if (!filename[0]) 
    {
	printf ("*** ERROR: can't open. filename is missing.\n",
		filename );
	return 0;
    }
       
    fpmain = fopen(filename, "r" );
    if (fpmain == NULL) 
    {
	fprintf (stderr,"*** ERROR: can't find: %s\n", filename );
        exit(1);
    }
    fgets(mastafm[0],128,fpmain);
    NofM = atoi(mastafm[0]);
    fprintf(stderr,"Now read %d lines\n",NofM);
    for (j = 0; j < NofM; j++)  
      {
      fscanf(fpmain,"%s",&mastafm[j]);
     }
    fscanf(fpmain,"%s",&newafm);
    fprintf(stderr,"Make new AFM file: %s\n",newafm);
    for (j = 0; j < NofM; j++)  
     {
       fscanf(fpmain,"%f",&Weight);
       fprintf(stderr,"Process file %d: %s with weight %f\n",j,mastafm[j],Weight);
       fp = fopen(mastafm[j], "r" );
    if (fp == NULL) 
    {
	fprintf (stderr,"*** ERROR: can't find: %s\n", mastafm[j] );
        exit(1);
    }
       if ( j == 0 ) 
       {
          parseFile(fp, &fi, myflags);
          IniValues(Weight);
       }
       else
       {
          parseFile(fp, &otherfi, myflags);
          sumValues(Weight);
       }
        fclose(fp);
     }
  printValues();
  freeStorage();
 fclose(fpmain);
} 
