/*
 * 
 * Author:
 *	Per Lindqvist, pgd@compuram.bbt.se
 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <math.h>
#include <ctype.h>
#include <memory.h>

#include "parseAFM.h"

#define	max(A, B)	(A > B ? A : B)
#define	min(A, B)	(A < B ? A : B)

FILE *ifp, *ofp;
FontInfo *gfi;

int i_width;				/* Width of an i */
int i_lsb;				/* left side bearing of i */
int xheight;				/* x-height */
int Xheight;				/* X-height */
int italicangle;			/* italic angle */
double sinfi, cosfi;

int cccomp();

CharMetricInfo *findmetric ( char *nm );
CompCharData *findcomp(char *nm);

main(argc, argv)
	int argc;
	char **argv;
{
	CharMetricInfo *mp;
	CompCharData *ccp;
	char line[200], ident[40], *cp;
	int i, j;
	int cci;
	int hashires;

	argc--; argv++;		/* Skip program name */
	while (argc >= 0 && **argv == '-') {
		switch ((*argv)[1]) {
		default:
			fprintf(stderr, "Illegal switch %s\n", *argv);
			exit(1);
		}
		argc--;
		argv++;
	}
	if (argc < 1) {
		fprintf(stderr, "Usage: fixfont afmfile infile {outfile}\n");
		exit(1);
	}
	ifp = fopen(argv[0], "r");
	if (ifp == NULL) {
		perror(argv[0]);
		exit(1);
	}

	switch (parseFile(ifp, &gfi, P_ALL)) {
        case parseError:
		fprintf(stderr, "*** ERROR: problem in parsing the AFM File.\n");
		exit(1);
		
	case earlyEOF:
		fprintf(stderr, "The AFM File ended prematurely.\n");
		exit(1);
		break;
        case storageProblem:
		fprintf(stderr, "*** ERROR: problem allocating storage.\n");
		exit(1);
		break;
	}
	fclose(ifp);

	ifp = fopen(argv[1], "r");
	if (ifp == NULL) {
		perror(argv[1]);
		exit(1);
	}

	if (argc > 2) {
		if ((ofp = fopen(argv[2], "w")) == NULL) {
			perror(argv[2]);
			exit(1);
		}
	} else
		ofp = stdout;

	/*
	 * Order the composite characters in alphabetic order
	 */
	qsort(gfi->ccd, gfi->numOfComps, sizeof(CompCharData), cccomp);

	/*
	 * First emit the disk load prefix
	 */
	fputs("%%!PS\n", ofp);
	fputs("(CopyToDisk) run\n", ofp);
	fprintf(ofp, "(fonts/%s) CopyToDisk\n", gfi->gfi->fontName);

	/*
	 * Skip to the CharStrings dictionary definition
	 * we have to modifiy the count of characters in the
	 * dictionary
	 */
	while (fgets(line, sizeof line - 1, ifp)) {
		if (strncmp(line, "dup/CharStrings ", 16) == 0)
			break;
		fputs(line, ofp);
	}

	if (strncmp(line, "dup/CharStrings hires", 21) == 0) {
		fputs(line, ofp);
		fgets(line, sizeof line - 1, ifp);
		if (strcmp(line+4, "dict dup begin\n") != 0) {
			fprintf(stderr, "I cannot handle this font\n");
			exit(1);
		}
		fprintf(ofp, "%d dict dup begin\n", gfi->numOfChars+1);
	} else
		fprintf(ofp, "dup/CharStrings %d dict dup begin\n", gfi->numOfChars+1);
	 
 process:
	/*
	 * We modify the font the simple way.
	 * Just scan the font source. Each line starting with a "/"
	 * and is checked for a character name.
	 * If it is a composite character, we replace it,
	 * We insert the other composite characters in alphabetic
	 * order.
	 */
	cci = 0;
	while (fgets(line, sizeof line - 1, ifp)) {
		if (strcmp(line, "end\n") == 0)
			break;
		if (line[0] != '/' || !strchr(line, '<')) {
			fputs(line, ofp);
			continue;
		}
		ident[0] = line[0];
		for (i = 1; isalpha(line[i]); i++)
			ident[i] = line[i];
		ident[i] = '\0';
		mp = findmetric(ident+1);
		if (mp == NULL) {
			fputs(line, ofp);
			continue;
		}
		ccp = findcomp(ident+1);
		if (ccp) {
			/*
			 * Remove the old definition
			 */
			while (fgets(line, sizeof line - 1, ifp))
				if (strchr(line, '>'))
					break;
			continue;
		}
		/*
		 * Check if a definitions should be inserted
		 * in alphabetic order, before this one
		 */
		while (cci < gfi->numOfComps && strcmp(gfi->ccd[cci].ccName, ident+1) < 0) {
			makechar(&gfi->ccd[cci]);
			cci++;
		}
		fputs(line, ofp);
	}
	/*
	 * Check for hires font
	 */
	fgets(line, sizeof(line)-1, ifp);
	if (strncmp(line, "hires{", 6) == 0) {
		/*
		 * Emit the last characters
		 */
		while (cci < gfi->numOfComps) {
			makechar(&gfi->ccd[cci]);
			cci++;
		}
		fputs("end\n", ofp);
		fputs(line, ofp);
		fgets(line, sizeof(line)-1, ifp);
		if (strcmp(line+4, "dict dup begin\n") != 0) {
			fprintf(stderr, "I cannot handle this font\n");
			exit(1);
		}
		fprintf(ofp, "%d dict dup begin\n", gfi->numOfChars+1);
		goto process;
	} else {
		while (cci < gfi->numOfComps) {
			makechar(&gfi->ccd[cci]);
			cci++;
		}
	}
	fputs("end\n", ofp);
	do {
		fputs(line, ofp);
		if (fgets(line, sizeof(line) - 1, ifp) == NULL) {
			fprintf(stderr, "Premature end-of-file\n");
			break;
		}
	} while (strncmp(line, "mark", 4) != 0);
	fclose(ofp);
	exit(0);
}

CharMetricInfo *
findmetric(nm)
	char *nm;
{
	register int i;

	for (i = 0; i < gfi->numOfChars; i++)
		if (strcmp(nm, gfi->cmi[i].name) == 0)
			return &gfi->cmi[i];
	return NULL;
}

CompCharData*
findcomp(nm)
	char *nm;
{
	register int i;

	for (i = 0; i < gfi->numOfComps; i++)
		if (strcmp(nm, gfi->ccd[i].ccName) == 0)
			return &gfi->ccd[i];
	return NULL;
}


int
cccomp(p1, p2)
	CompCharData *p1, *p2;
{
	return strcmp(p1->ccName, p2->ccName);
}

/*
 * this routine makes a lot of assumptions.
 * But all are the normal case for adobe fonts.
 */
makechar(ccp)
	CompCharData *ccp;
{
	CharMetricInfo *cmp, *bmp, *amp;	

	cmp = findmetric(ccp->ccName);
	/* Assume that the first piece is the base character */
	bmp = findmetric(ccp->pieces[0].pccName);
	/* Assume that the second piece is the accent character */
	amp = findmetric(ccp->pieces[1].pccName);
	fprintf(ofp, "/%s  <	%d %d Hsbw\n",
		ccp->ccName, cmp->charBBox.llx, cmp->wx);
	/* Assume that deltax,deltay for the base character are both zero */
	/* Assume the afm codes are the standard encoding */
	fprintf(ofp, "\t\t%d %d %d %d %d Seac\n",
		amp->charBBox.llx,
		ccp->pieces[1].deltax + amp->charBBox.llx - bmp->charBBox.llx,
		ccp->pieces[1].deltay,
		bmp->code, amp->code);
	fprintf(ofp, "\t\t> ND\n");
}
