Initial revision
diff --git a/src/libdraw/buildfont.c b/src/libdraw/buildfont.c
new file mode 100644
index 0000000..ba32e77
--- /dev/null
+++ b/src/libdraw/buildfont.c
@@ -0,0 +1,141 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+static char*
+skip(char *s)
+{
+	while(*s==' ' || *s=='\n' || *s=='\t')
+		s++;
+	return s;
+}
+
+Font*
+buildfont(Display *d, char *buf, char *name)
+{
+	Font *fnt;
+	Cachefont *c;
+	char *s, *t;
+	ulong min, max;
+	int offset;
+	char badform[] = "bad font format: number expected (char position %d)";
+
+	s = buf;
+	fnt = malloc(sizeof(Font));
+	if(fnt == 0)
+		return 0;
+	memset(fnt, 0, sizeof(Font));
+	fnt->display = d;
+	fnt->name = strdup(name);
+	fnt->ncache = NFCACHE+NFLOOK;
+	fnt->nsubf = NFSUBF;
+	fnt->cache = malloc(fnt->ncache * sizeof(fnt->cache[0]));
+	fnt->subf = malloc(fnt->nsubf * sizeof(fnt->subf[0]));
+	if(fnt->name==0 || fnt->cache==0 || fnt->subf==0){
+    Err2:
+		free(fnt->name);
+		free(fnt->cache);
+		free(fnt->subf);
+		free(fnt->sub);
+		free(fnt);
+		return 0;
+	}
+	fnt->height = strtol(s, &s, 0);
+	s = skip(s);
+	fnt->ascent = strtol(s, &s, 0);
+	s = skip(s);
+	if(fnt->height<=0 || fnt->ascent<=0){
+		werrstr("bad height or ascent in font file");
+		goto Err2;
+	}
+	fnt->width = 0;
+	fnt->nsub = 0;
+	fnt->sub = 0;
+
+	memset(fnt->subf, 0, fnt->nsubf * sizeof(fnt->subf[0]));
+	memset(fnt->cache, 0, fnt->ncache*sizeof(fnt->cache[0]));
+	fnt->age = 1;
+	do{
+		/* must be looking at a number now */
+		if(*s<'0' || '9'<*s){
+			werrstr(badform, s-buf);
+			goto Err3;
+		}
+		min = strtol(s, &s, 0);
+		s = skip(s);
+		/* must be looking at a number now */
+		if(*s<'0' || '9'<*s){
+			werrstr(badform, s-buf);
+			goto Err3;
+		}
+		max = strtol(s, &s, 0);
+		s = skip(s);
+		if(*s==0 || min>=65536 || max>=65536 || min>max){
+			werrstr("illegal subfont range");
+    Err3:
+			freefont(fnt);
+			return 0;
+		}
+		t = s;
+		offset = strtol(s, &t, 0);
+		if(t>s && (*t==' ' || *t=='\t' || *t=='\n'))
+			s = skip(t);
+		else
+			offset = 0;
+		fnt->sub = realloc(fnt->sub, (fnt->nsub+1)*sizeof(Cachefont*));
+		if(fnt->sub == 0){
+			/* realloc manual says fnt->sub may have been destroyed */
+			fnt->nsub = 0;
+			goto Err3;
+		}
+		c = malloc(sizeof(Cachefont));
+		if(c == 0)
+			goto Err3;
+		fnt->sub[fnt->nsub] = c;
+		c->min = min;
+		c->max = max;
+		c->offset = offset;
+		t = s;
+		while(*s && *s!=' ' && *s!='\n' && *s!='\t')
+			s++;
+		*s++ = 0;
+		c->subfontname = 0;
+		c->name = strdup(t);
+		if(c->name == 0){
+			free(c);
+			goto Err3;
+		}
+		s = skip(s);
+		fnt->nsub++;
+	}while(*s);
+	return fnt;
+}
+
+void
+freefont(Font *f)
+{
+	int i;
+	Cachefont *c;
+	Subfont *s;
+
+	if(f == 0)
+		return;
+
+	for(i=0; i<f->nsub; i++){
+		c = f->sub[i];
+		free(c->subfontname);
+		free(c->name);
+		free(c);
+	}
+	for(i=0; i<f->nsubf; i++){
+		s = f->subf[i].f;
+		if(s && s!=display->defaultsubfont)
+			freesubfont(s);
+	}
+	freeimage(f->cacheimage);
+	free(f->name);
+	free(f->cache);
+	free(f->subf);
+	free(f->sub);
+	free(f);
+}