generated html version of bdf2ttf.cHOME

/* this program is designed to convert my neoletters font into a ttf */

#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
#include "u8.h"

#define ei else if
int xdgval(int c){
	if(c >= '0' && c <= '9')return c - '0';
	if(c >= 'A' && c <= 'F')return c - 'A' + 10;
	if(c >= 'a' && c <= 'f')return c - 'a' + 10;
}

uint32_t read32(FILE *f){
	uint32_t c;
	fread(&c,4,1,f);
	c = c >> 16 | c << 16;
	c = c >> 8 & 0xFF00FF | c << 8 & 0xFF00FF00;
	return c;
}

void write32(FILE *f,uint32_t c){
	c = c >> 16 | c << 16;
	c = c >> 8 & 0xFF00FF | c << 8 & 0xFF00FF00;
	fwrite(&c,4,1,f);
}

void write64(FILE *f,uint64_t c){
	c = c >> 32 | c << 32;
	c = c >> 16 & 0xFFFF0000FFFF | c << 16 & 0xFFFF0000FFFF0000;
	c = c >> 8 & 0xFF00FF00FF00FF | c << 8 & 0xFF00FF00FF00FF00;
	fwrite(&c,8,1,f);
}

void writestr(FILE *f,char*s){
	fwrite(s,1,strlen(s),f);
}

uint16_t read16(FILE *f){
	uint16_t c;
	fread(&c,2,1,f);
	c = c >> 8 | c << 8;
	return c;
}

void write16(FILE *f, uint16_t c){
	c = c >> 8 | c << 8;
	fwrite(&c,2,1,f);
}

void write8(FILE *f, uint8_t c){
	fwrite(&c,1,1,f);
}

void goloc(FILE *f, long loc){
	fseek(f,loc,SEEK_SET);
}

void gorel(FILE *f, long x){
	fseek(f,x,SEEK_CUR);
}

void ffastfw(FILE *f){
	fseek(f,0,SEEK_END);
}


struct bdfglyph {
	char name[16];
	int encoding;
	int dwidth;
	int bbox[4];
	unsigned bitmap[16];
};

unsigned leftshft(unsigned x,int i){
	if(i>0)return x << i;
	if(i<0)return x >> -i;
	return x;
}


void writenameent(FILE *f,FILE *sf, int plat,int code,int lang, int name,char *s, int len){
	write16(f,plat);//windows
	write16(f,code);//ucs
	write16(f,lang);//english
	write16(f,name);//name id 1 font family
	write16(f,len);//string length
	write16(f,ftell(sf)); //offset
	fwrite(s,len,1,sf);
}

void makepathmap(struct bdfglyph*g);
//temporary storage;
char bitmap[1000];
char line[300];
char pathmap[17*19];
struct point {char x,y,start;} pathlist[17*19*2];
int pathend;

int bdfpthchk(struct bdfglyph g,int x,int y);
int addpath(int x,int y);

unsigned writefile(FILE *f,FILE*g){
	rewind(g);
	int c;
	while((c=fgetc(g))!=EOF)fputc(c,f);
}

unsigned writeblanktable(FILE *f,char*s){
	writestr(f,s);
	unsigned x = ftell(f);
	write32(f,0);//cksum
	write32(f,0);//location
	write32(f,0);//length
	return x;
}

unsigned finalizetable(FILE *f,unsigned tblent,unsigned tblloc,unsigned tbllen){
	int padc = tbllen % 4;
	if(padc==1)fwrite("\0\0\0",1,3,f);
	if(padc==2)fwrite("\0\0",1,2,f);
	if(padc==3)fwrite("\0",1,1,f);
	unsigned lenwpad = tbllen/4 + (padc?1:0);
	uint32_t sum;
	goloc(f,tblloc);
	int i;
	for(i=0;i<lenwpad;i++)sum += read32(f);
	goloc(f,tblent);
	write32(f,sum);
	write32(f,tblloc);
	write32(f,tbllen);
	ffastfw(f);
	if(ftell(f) % 4 != 0){printf("ERRO misaligned padc=%d ftell=%d tblloc=%d tbllen=%d\n",padc,ftell(f),tblloc,tbllen);exit(1);}
}

int main () {
	struct bdfglyph g;
	/* PARSE A BDF FROM STDIN */
	FILE *out = fopen("out.ttf","w+");
	printf("status: reading...\n");

	fgets(line,300,stdin);
	float vernum;
	sscanf(line,"STARTFONT %f",&vernum);
	fgets(line,300,stdin);
	char fontname[100];
	sscanf(line,"FONT %99s",fontname);
	fgets(line,300,stdin);
	int ptsz, xdpi, ydpi;
	sscanf(line,"SIZE %d %d %d",&ptsz,&xdpi,&ydpi);
	fgets(line,300,stdin);
	int pxw,pxh,stx,sty;
	sscanf(line,"FONTBOUNDINGBOX %d %d %d %d",&pxw,&pxh,&stx,&sty);
	do fgets(line,300,stdin);
	while(strncmp(line,"STARTPROPERTIES",15));
	int i,nprops;
	int fontasc, fontdesc, pixelsize;
	sscanf(line,"STARTPROPERTIES %d",&nprops);
	for(i=0;i<nprops;i++){
		fgets(line,300,stdin);
		if(!strncmp(line,"PIXEL_SIZE",10)){
			sscanf(line,"PIXEL_SIZE %d",&pixelsize);
		}else if(!strncmp(line,"FONT_ASCENT",11)){
			sscanf(line,"FONT_ASCENT %d",&fontasc);
		}else if(!strncmp(line,"FONT_DESCENT",12)){
			sscanf(line,"FONT_DESCENT %d",&fontdesc);
		}
	}
	do fgets(line,300,stdin);
	while(strncmp(line,"CHARS",5));
	int nchars;
	sscanf(line,"CHARS %d",&nchars);

	printf("status: start %d\n",nchars);
	/* write ttf file header */
	write32(out,0x00010000);
	write16(out,11);
	write16(out,128);
	write16(out,3);
	write16(out,48);
	unsigned os2ent = writeblanktable(out,"OS/2"); // the table entries
	unsigned cmapent = writeblanktable(out,"cmap");
	unsigned cvtent = writeblanktable(out,"cvt ");
	unsigned glyfent = writeblanktable(out,"glyf");
	unsigned headent = writeblanktable(out,"head");
	unsigned hheaent = writeblanktable(out,"hhea");
	unsigned hmtxent = writeblanktable(out,"hmtx");
	unsigned locaent = writeblanktable(out,"loca");
	unsigned maxpent = writeblanktable(out,"maxp");
	unsigned nameent = writeblanktable(out,"name");
	unsigned postent = writeblanktable(out,"post");
#define UPM 16

	unsigned cvtloc = ftell(out);
	write32(out,0x00000000);//AAAAAAAAA
	unsigned cvtlen = ftell(out) - cvtloc;
	finalizetable(out,cvtent,cvtloc,cvtlen);

	printf("status: head\n");
	/* write the head table */
	unsigned headloc = ftell(out);
	write16(out,1);//major
	write16(out,0);//minor
	write32(out,0x00010000);//font version
	write32(out,0);//checksumadjustment
	write32(out,0x5F0F3CF5);//magic number
	write16(out,0x0000);//flags
	write16(out,UPM);//units per em
	write64(out,time(0) + 24107ULL * 86400ULL);//date created
	write64(out,time(0) + 24107ULL * 86400ULL);//date modified
	write16(out,0);//xmin
	write16(out,-4);//ymin
	write16(out,18);//xmax
	write16(out,12);//ymax
	write16(out,0);//macstyle
	write16(out,8);//lowest recommended ppem
	write16(out,2);// deprecated set to 2
	write16(out,1);// 0 short/long 1 format for loca table
	write16(out,0);// glyph data format, always 0
	unsigned headlen = ftell(out) - headloc;
	finalizetable(out,headent,headloc,headlen);

	printf("status: hhea\n");
	/*write the hhea table*/
	unsigned hhealoc = ftell(out);
	write16(out,1);
	write16(out,0);
	write16(out,UPM*3/4);//ascent
	write16(out,UPM/4);//descent
	write16(out,0);//line gap
	write16(out,18);//max advance width
	write16(out,0);//min left sidebearing
	write16(out,0);//min right sidebearing
	write16(out,18);//max extent
	write16(out,0);//slope rise
	write16(out,1);//slope run
	write16(out,0);//slant shift
	write16(out,0);//reserved
	write16(out,0);//reserved
	write16(out,0);//reserved
	write16(out,0);//reserved
	write16(out,0);//metric data fmt always 0
	write16(out,nchars);//number of hmtx
	unsigned hhealen = ftell(out) - hhealoc;
	finalizetable(out,hheaent,hhealoc,hhealen);

	printf("status: OS/2\n");
	/*write the OS/2 table*/
	unsigned os2loc = ftell(out);
	write16(out,4);
	write16(out,UPM*9/16);//average width
	write16(out,500);//Medium Weight
	write16(out,5);//Medium Width
	write16(out,0);//fstype
	write16(out,UPM);//subscript x size
	write16(out,UPM/2);//subscript y size
	write16(out,0);//subscript x offset
	write16(out,UPM/4);//subscript y offset
	write16(out,UPM);//superscript x size
	write16(out,UPM/2);//superscript y size
	write16(out,0);//superscript x offset
	write16(out,UPM/4);//superscript y offset
	write16(out,UPM*2/16);//strikeout size
	write16(out,UPM/4);//strikeout position
	write8(out,8);// neoletters is a sans serif
	write8(out,3);// geometric face.
	/* panose font type */
	write8(out,2);//Latin text
	write8(out,11);//normal sans serif
	write8(out,6);//medium weight
	write8(out,9);//monospaced
	write8(out,2);//no contrast
	write8(out,2);//no variation
	write8(out,0);//blahhhh
	write8(out,0);//blahhhh
	write8(out,0);//blahhhh
	write8(out,0);//blahhhh
	/*unicode range bits, set all on for now*/
	write32(out,0xFFFFFFFF);
	write32(out,0xFFFFFFFF);
	write32(out,0xFFFFFFFF);
	write32(out,0xFFFFFFFF);
	/*vendor id*/
	writestr(out,"OREN");// blah
	write16(out,0x1C0);//style bits
	write16(out,0x0020);//minmum character
	write16(out,0xFFFF);//last char
	write16(out,UPM*3/4);//ideogram ascension
	write16(out,-UPM/4);//ideogram descent
	write16(out,0);//line gap
	write16(out,UPM*3/4);//windows basic ascension
	write16(out,UPM/4);//windows basic descent
	/*code page range bits, set all on for now*/
	write32(out,0x7FFFFFFF);
	write32(out,0xFFFFFFFF);
	write16(out,UPM/2);//x height
	write16(out,UPM*3/4);//cap height
	write16(out,0xFFFD);//character to use as replacement
	write16(out,0x0020);//character to use as space
	write16(out,1);//max context of ligatures
	unsigned os2len = ftell(out) - os2loc;
	finalizetable(out,os2ent,os2loc,os2len);

	printf("status: post\n");
	/*write the post table*/
	unsigned postloc = ftell(out);
	write32(out,0x00030000);//version 3.0
	write32(out,0x00000000);//upright
	write16(out,0x0000);//underline?
	write16(out,0x0002);//thickness?
	write32(out,0x00000001);//font is monospace
	write32(out,0x00000000);//meomory usage unknown
	write32(out,0x00000000);//meomory usage unknown
	write32(out,0x00000000);//meomory usage unknown
	write32(out,0x00000000);//meomory usage unknown
	unsigned postlen = ftell(out) - postloc;
	finalizetable(out,postent,postloc,postlen);

	printf("status: name\n");
	/*write the name table*/
	unsigned nameloc = ftell(out);
	FILE *strng = fopen("strng.temp","w+");
	write16(out,0);
	write16(out,12);//number of name records
	write16(out,6+12*12);//offset to start of strings
	writenameent(out,strng,3,1,0x409,1,"\0n\0e\0o\0l\0e\0t\0t\0e\0r\0s",20);
	writenameent(out,strng,3,1,0x409,2,"\0R\0e\0g\0u\0l\0a\0r",14);
	writenameent(out,strng,3,1,0x409,3,"\0n\0e\0o\0l\0e\0t\0t\0e\0r\0s\0 \0R\0e\0g\0u\0l\0a\0r",36);
	writenameent(out,strng,3,1,0x409,4,"\0n\0e\0o\0l\0e\0t\0t\0e\0r\0s",20);
	writenameent(out,strng,3,1,0x409,5,"\0V\0e\0r\0s\0i\0o\0n\0 \0""1\0.\0""0",20);
	writenameent(out,strng,3,1,0x409,6,"\0n\0e\0o\0l\0e\0t\0t\0e\0r\0s",20);
	writenameent(out,strng,1,0,0,1,"neoletters",10);
	writenameent(out,strng,1,0,0,2,"Regular",7);
	writenameent(out,strng,1,0,0,3,"neoletters Regular",18);
	writenameent(out,strng,1,0,0,4,"neoletters",10);
	writenameent(out,strng,1,0,0,5,"Version 1.0",20);
	writenameent(out,strng,1,0,0,6,"neoletters",10);
	writefile(out,strng);
	unsigned namelen = ftell(out) - nameloc;
	finalizetable(out,nameent,nameloc,namelen);

	unsigned localoc = ftell(out);
	write32(out,0);
	/* open ttf table files */

	FILE *glyf = fopen("glyf.temp","w+");
	FILE *hmtx = fopen("hmtx.temp","w+");
//	write16(hmtx,9);
//	write16(hmtx,0);
	FILE *cmap12 = fopen("cmap12.temp","w+");// format 12 table
	int startccode = -1;
	int endccode = -1;
	int startglyfid = 0;
	int maxpoints = 0;
	int maxcontour = 0;
	int glyfid = 0;
	int ngroups = 0;
	int n2groups = 0;//number of groups below FFFF
	while(glyfid < nchars){
		if(!fgets(line,300,stdin))break;
		sscanf(line,"STARTCHAR %16s",&g.name);
		fgets(line,300,stdin);
		int ccode;
		sscanf(line,"ENCODING %d",&g.encoding);
		ccode = g.encoding;
		printf("status: U%05x\n",ccode);
		do fgets(line,300,stdin);
		while(strncmp(line,"DWIDTH",6));
		int dwidth;
		sscanf(line,"DWIDTH %d",&g.dwidth);
		fgets(line,300,stdin);
		sscanf(line,"BBX %d %d %d %d",g.bbox,g.bbox+1,g.bbox+2,g.bbox+3); 
		// width, height, x offset, y offset (of lower left corner)
		fgets(line,300,stdin);
		sscanf(line,"BITMAP");
		int bwidth = (g.bbox[0]+(g.bbox[0]%8?8-g.bbox[0]%8:0))/8;
		int bottom = 12 - g.bbox[3];
		int top = bottom - g.bbox[1];
		int lsb = g.bbox[2];
		int j,i;
		unsigned bitmap[16];
		for(j=0;j<g.bbox[1];j++){
			fgets(line,300,stdin);
			sscanf(line,"%x",bitmap+j);
		}
		for(j=0;j<16;j++){
			g.bitmap[j]=0;
			if(j >= top && j < bottom) {
				int k = j - top;
				g.bitmap[j] = leftshft(bitmap[k],18 - bwidth * 8 - lsb);
			}
		}
		outputasbitmap(g);
		/* create path map */
		int xmin=20,xmax=0,ymin=16,ymax=0;
		for(i=0;i<=18;i++){
			for(j=0;j<=16;j++){
				pathmap[i+j*19]=bdfpthchk(g,i,j);
				if(pathmap[i+j*19] && pathmap[i+j*19] != 0xF){
					if(i<xmin)xmin=i;
					if(i>xmax)xmax=i;
					if(j<ymin)ymin=j;
					if(j>ymax)ymax=j;
				}
			}
		}
		/* use map to find all paths */
		pathend = 0;
		int n=0;
		for(i=0;i<=18;i++){
			for(j=0;j<=16;j++){
				if(pathmap[i+j*19] && pathmap[i+j*19] != 0xF){
					addpath(i,j);
					n++;
				}
			}
		}
		if(n==0)goto outputloca;
		/* output paths into glyf */
		write16(glyf,n);//number of contours
		write16(glyf,xmin);//xmin
		write16(glyf,12-ymax);//ymin
		write16(glyf,xmax);//xmax
		write16(glyf,12-ymin);//ymax
		printf("status: %d %d %d %d\n",xmin,12-ymax,xmax,12-ymin);
		for(i=1;i<pathend;i++){
			if(pathlist[i].start==1)write16(glyf,i-1);
		}
		write16(glyf,pathend-1);
		write16(glyf,0);// zero bytes of code
		for(i=0;i<pathend;i++){
			struct point p = pathlist[i];
			int flags = 7;
			if(p.x == 0)flags ^= 022;
			ei(p.x > 0)flags |= 020;
			if(p.y == 0)flags ^= 044;
			ei(p.y > 0)flags |= 040;
			write8(glyf,flags);
		}
		for(i=0;i<pathend;i++){
			if(pathlist[i].x!=0)write8(glyf,abs(pathlist[i].x));
		}
		for(i=0;i<pathend;i++){
			if(pathlist[i].y!=0)write8(glyf,abs(pathlist[i].y));
		}
		if (0) {/*16 bit format*/
		i = pathend;
		while(i > 0){
			write8(glyf,0x9);// two bytes for each x and y
			if(i > 1 && i <= 256)write8(glyf,i-1),i=0;
			ei(i > 256)write8(glyf,255),i-=255;
			else i=0;
		}
		for(i=0;i<pathend;i++){
			write16(glyf,(int)pathlist[i].x);
		}
		for(i=0;i<pathend;i++){
			write16(glyf,(int)pathlist[i].y);
		}
		}
		if(pathend > maxpoints)maxpoints = pathend;
		if(n > maxcontour)maxcontour = n;
		//if(ftell(glyf)%2==1)write8(glyf,0x0);//filler
		outputloca:
		write32(out,ftell(glyf));
		//check if we need to output a character range record
		if(startccode == -1 && ccode != 0){startccode=endccode=ccode;startglyfid=glyfid;}
		if(endccode < ccode-1){
			if(endccode < 0x10000 && ccode > 0x10000)n2groups=ngroups +1;
			write32(cmap12,startccode);
			write32(cmap12,endccode);
			write32(cmap12,startglyfid);
			startccode = endccode = ccode;
			startglyfid = glyfid;
			ngroups++;
		}else endccode=ccode;
		//output hmtx
		if(ccode == 0){
			write16(hmtx,9);
		} else {
			write16(hmtx,9*u8chrwid(ccode));
		}
		write16(hmtx,xmin==20?0:xmin);
		glyfid++;
		do fgets(line,300,stdin);
		while(strncmp(line,"ENDCHAR",7));
		printf("status: U%05x, %d %d %d\n",ccode,n,pathend,glyfid);
	}
//	write32(out,ftell(glyf));
	//final group
	write32(cmap12,startccode);
	write32(cmap12,endccode);
	write32(cmap12,startglyfid);
	ngroups++;

	unsigned localen = ftell(out) - localoc;
	finalizetable(out,locaent,localoc,localen);

	unsigned hmtxloc = ftell(out);
	writefile(out,hmtx);
	unsigned hmtxlen = ftell(out) - hmtxloc;
	finalizetable(out,hmtxent,hmtxloc,hmtxlen);

	unsigned cmaploc = ftell(out);
	write16(out,0);
	write16(out,2);//1 subtables
	write16(out,3);//platform 3 windows
	write16(out,1);//code 1 unicode BMP
	write32(out,20);//offset
	write16(out,3);//platform 3 windows
	write16(out,10);//code 10 unicode
	write32(out,0);//offset
	write16(out,4);//subtable format 4
	unsigned nranges = n2groups + 1;
	write16(out,nranges*8 + 16);//length
	write16(out,0);//language (not used)
	write16(out,nranges*2);
	unsigned searchrange=2;
	unsigned selector = 0;
	while(searchrange<=nranges)searchrange*=2,selector++;
	write16(out,searchrange);
	write16(out,selector);
	write16(out,2*nranges - searchrange);
	for(i=0;i<n2groups;i++){
		goloc(cmap12,12*i+4);
		write16(out,read32(cmap12));
	}
	write16(out,0xFFFF);
	write16(out,0);
	for(i=0;i<n2groups;i++){
		goloc(cmap12,12*i);
		write16(out,read32(cmap12));
	}
	write16(out,0xFFFF);
	for(i=0;i<n2groups;i++){
		goloc(cmap12,12*i);
		unsigned short x = read32(cmap12);
	        read32(cmap12);
	        x = read32(cmap12) - x;
		write16(out,x);
	}
	write16(out,1);
	for(i=0;i<n2groups;i++){
		write16(out,0);
	}
	write16(out,0);
	unsigned cmap12loc = ftell(out);
	write16(out,12);//subtable format 12
	write16(out,0);//reserved 0
	write32(out,ngroups*12 + 16);//length
	write32(out,0);//language (not used)
	write32(out,ngroups);//number of groups
	writefile(out,cmap12);
	goloc(out,cmaploc+16);
	write32(out,cmap12loc-cmaploc);
	ffastfw(out);
	unsigned cmaplen = ftell(out) - cmaploc;
	finalizetable(out,cmapent,cmaploc,cmaplen);

	unsigned glyfloc = ftell(out);
	writefile(out,glyf);
	unsigned glyflen = ftell(out) - glyfloc;
	finalizetable(out,glyfent,glyfloc,glyflen);

	unsigned maxploc = ftell(out);
	write32(out,0x00010000);
	write16(out,glyfid);//number of glyphs
	write16(out,maxpoints);
	write16(out,maxcontour);
	write16(out,maxpoints);
	write16(out,maxcontour);
	write16(out,1);//program maxima
	write16(out,0);
	write16(out,0);
	write16(out,0);
	write16(out,0);
	write16(out,0);
	write16(out,0);
	write16(out,0);
	write16(out,0);
	unsigned maxplen = ftell(out) - maxploc;
	finalizetable(out,maxpent,maxploc,maxplen);

	uint32_t sum;
	unsigned len = ftell(out);
	goloc(out,0);
	for(i=0;i<len;i++)sum += read32(out);
	goloc(out,headloc + 8);
	write32(out,sum);

	return 0;
}

struct point p0;
int addpath(int x,int y){
	int dir;
	int i = pathend;
	char map = pathmap[x+y*19];
	printf("start at %d,%d:",x,y);
	if(i==0){
		pathlist[i] = (struct point){x,12-y,1};
		p0 = (struct point){x,12-y,1};
	}else{
		pathlist[i] = (struct point){x-p0.x,12-y-p0.y,1};
		p0 = (struct point){x,12-y,1};
	}
	if(map == 8){dir = 'R';pathmap[x+y*19]=0;}
	if(map == 7){dir = 'D';pathmap[x+y*19]=0;}
	i++;
	pathlist[i]=(struct point){0,0,0};
	nextpoint:;
	putchar(dir);
	fflush(stdout);
	int olddir = dir;
	if(dir == 'R'){
		x++;
		pathlist[i].x++;
		char map = pathmap[x+y*19];
		if(map == 4){dir = 'D';pathmap[x+y*19]=0;}
		ei(map == 6){dir = 'D';pathmap[x+y*19]=2;}
		ei(map == 12){dir = 'R';pathmap[x+y*19]=0;}
		ei(map == 14){dir = 'U';pathmap[x+y*19]=0;}
		else goto endof;
	}ei(dir == 'D'){
		y++;
		pathlist[i].y--;
		char map = pathmap[x+y*19];
		if(map == 1){dir = 'L';pathmap[x+y*19]=0;}
		ei(map == 5){dir = 'D';pathmap[x+y*19]=0;}
		ei(map == 9){dir = 'L';pathmap[x+y*19]=8;}
		ei(map == 13){dir = 'R';pathmap[x+y*19]=0;}
		else goto endof;
	}ei(dir == 'L'){
		x--;
		pathlist[i].x--;
		char map = pathmap[x+y*19];
		if(map == 2){dir = 'U';pathmap[x+y*19]=0;}
		ei(map == 3){dir = 'L';pathmap[x+y*19]=0;}
		ei(map == 6){dir = 'U';pathmap[x+y*19]=4;}
		ei(map == 7){dir = 'D';pathmap[x+y*19]=0;}
		else goto endof;
	}ei(dir == 'U'){
		y--;
		pathlist[i].y++;
		char map = pathmap[x+y*19];
		if(map == 8){dir = 'R';pathmap[x+y*19]=0;}
		ei(map == 9){dir = 'R';pathmap[x+y*19]=1;}
		ei(map == 10){dir = 'U';pathmap[x+y*19]=0;}
		ei(map == 11){dir = 'L';pathmap[x+y*19]=0;}
		else goto endof;
	}
	if(dir != olddir){
		p0.x += pathlist[i].x;
		p0.y += pathlist[i].y;
		i++;
		pathlist[i]=(struct point){0,0,0};
	}
	goto nextpoint;
	endof:;
	printf(" end at %d,%d\n",p0.x,p0.y);
	pathend = i; // the last segment is not included.
}


int bdfpixchk(struct bdfglyph g,int x,int y){
	if(x<0||y<0||x>17||y>15)return 0;
	return!!(g.bitmap[y]&(0x20000>>x));
}

int bdfpthchk(struct bdfglyph g,int x,int y){
	return	bdfpixchk(g,x-1,y-1) +
		2*bdfpixchk(g,x,y-1) +
		4*bdfpixchk(g,x-1,y) +
		8*bdfpixchk(g,x,y);
}

int outputasbitmap(struct bdfglyph g){
		int j;
		for(j=0;j<4;j++){
			int b;
			for (b=0x20000;b!=0;b/=4) {
				int t =   (g.bitmap[j*4]&b	?0x01:0x00)
					| (g.bitmap[j*4]&(b/2)	?0x08:0x00)
					| (g.bitmap[j*4+1]&b  	?0x02:0x00)
					| (g.bitmap[j*4+1]&(b/2)?0x10:0x00)
					| (g.bitmap[j*4+2]&b	?0x04:0x00)
					| (g.bitmap[j*4+2]&(b/2)?0x20:0x00)
					| (g.bitmap[j*4+3]&b    ?0x40:0x00)
					| (g.bitmap[j*4+3]&(b/2)?0x80:0x00);
				printf("\342%c%c",(t>>6)|0240,(t&077)|0200);
			}
			printf("\n");
		}
}