#include <stdio.h>
#include <ft.h>
#include "font.h"

/*
**	convert a nu-machine font to an apm font
**
**	FDC, 10/5/84
*/

char	nuFont[20000];		/* contents of nu font file	*/
FILE	*ifd, *ofd;
struct	fontinfo apmFont;	/* apm font header		*/
struct	diminfo dimtab[256];	/* apm dimension table		*/
int	dimlast = -1;		/* last entry in dimtab		*/
short	dimindex[256];		/* temporary index table	*/


/*****************************************************************************
 	MAIN - main program loop
 *****************************************************************************/
main(argc, argv)
int argc;
char **argv;
{
	register i; 

	if (argc != 3) {
		fprintf(stderr, "usage: nutoapm nufont apmfont\n");
		exit(1);
	}
	if ((ifd = fopen(argv[1], "r")) == NULL) {
		printf("can't open %s\n", argv[1]);
		exit(1);
	}
	if ((ofd = fopen(argv[2], "w")) == NULL) {
		printf("can't open %s\n", argv[2]);
		exit(1);
	}
	i = fread(nuFont, 1, sizeof(nuFont), ifd);
	if (i >= sizeof(nuFont)) {
		printf("font buffer is too small (%d bytes)\n", sizeof(nuFont));
		exit(1);
	}
	if (i <= 128 * sizeof(struct CharDef)) {
		printf("%s too short\n", argv[1]);
		exit(1);
	}
	preprocess();
	process();
	return(0);
}

static preprocess()
{
	register int c, fc, ro;
	register struct CharDef *p;

	fc = -1;
	for (c = 0; c < 256; c++)
		apmFont.raster_offset[c] = -1;
	for (c = 0; c < FONTSIZE; c++) {
		p = (struct CharDef *) (nuFont + c * sizeof(struct CharDef));
		if (c == ' ' || (p->Raster != 0xffff && RasterSize(p) > 0)) {
			if (fc == -1) {
				fc = c;
				apmFont.raster_offset[0] = ro = 0;
			}
			else
				apmFont.raster_offset[c - fc] = ro;
			ro += RasterSize(p) + 2;
			apmFont.lastchar = c;
			enterdim(c, p);		/* make dimtab entry */
		}
	}
	apmFont.firstchar = fc;
}

static process()
{
	register struct fontinfo *f = &apmFont;
	register int c, rb;
	register struct CharDef *p;
	register int *ro;

	f->dimtab_offset = (char *) &(f->raster_offset[f->lastchar + 1]) -
				(char *) f;
	rb = f->dimtab_offset + (dimlast + 1) * sizeof(struct diminfo);
	for (c = 0; c <= f->lastchar - f->firstchar; c++) {
		ro = &(f->raster_offset[c]);
		*ro = (*ro == -1) ? *ro = 0 : *ro += rb;
	}
	fwrite(f, sizeof(*f) - (255 + f->firstchar - f->lastchar) * sizeof(int),
		1, ofd);
	fwrite(dimtab, sizeof(*dimtab), dimlast + 1, ofd);
	p = (struct CharDef *) nuFont;
	for (c = 0; c < FONTSIZE; c++)
		dump(p++, c);
}

static enterdim(c, p)
int c;
register struct CharDef *p;
{
	register struct diminfo *d = dimtab, *de = &dimtab[dimlast];

	while (d <= de) {
		if (d->HSize == p->HSize && d->VSize == p->VSize &&
			d->HOffs == p->HAdj && d->VOffs == p->VAdj &&
			d->HIncr == p->HIncr && d->VIncr == p->VIncr) {
			dimindex[c] = d - dimtab;
			return;
		}
		else
			d++;
	}
	d->HSize = p->HSize;
	d->VSize = p->VSize;
	d->HOffs = p->HAdj;
	d->VOffs = p->VAdj;
	d->HIncr = p->HIncr;
	d->VIncr = p->VIncr;
	dimlast++;
	dimindex[c] = d - dimtab;
}

static dump(p, c)
register struct CharDef *p;
char c;
{
	register unsigned short *rp, *rp1;
	register int h, v;
	unsigned short s;

	unsigned reverse();

	fwrite(&dimindex[c], 2, 1, ofd);
	if (p->Raster == 0xffff || RasterSize(p) <= 0)
		return;
	rp = (unsigned short *) CharRaster(p);
	for (h = 0; h < (p->HSize + 15)>>4; h++) {
		rp1 = rp + h * p->VSize;
		for (v = 0; v < p->VSize; v++) {
			s = reverse(*rp1++);
			fwrite(&s, 1, 2, ofd);
		}
	}
}

static unsigned reverse(n)
register unsigned n;
{
	register unsigned r = 0, y = 0x8000, c = 16;

	do {
		if (n & 1) r += y;
		n >>= 1;
		y >>= 1;
	} while (c--);
	return(r);
}
