xref: /plan9-contrib/sys/src/libdraw/buildfont.c (revision eaba85aa6b158bdf68fdb77f770e3ba0899a8b5e)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier static char*
skip(char * s)67dd7cddfSDavid du Colombier skip(char *s)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	while(*s==' ' || *s=='\n' || *s=='\t')
97dd7cddfSDavid du Colombier 		s++;
107dd7cddfSDavid du Colombier 	return s;
117dd7cddfSDavid du Colombier }
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier Font*
buildfont(Display * d,char * buf,char * name)147dd7cddfSDavid du Colombier buildfont(Display *d, char *buf, char *name)
157dd7cddfSDavid du Colombier {
167dd7cddfSDavid du Colombier 	Font *fnt;
177dd7cddfSDavid du Colombier 	Cachefont *c;
187dd7cddfSDavid du Colombier 	char *s, *t;
197dd7cddfSDavid du Colombier 	ulong min, max;
207dd7cddfSDavid du Colombier 	int offset;
2180ee5cbfSDavid du Colombier 	char badform[] = "bad font format: number expected (char position %d)";
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier 	s = buf;
247dd7cddfSDavid du Colombier 	fnt = malloc(sizeof(Font));
257dd7cddfSDavid du Colombier 	if(fnt == 0)
267dd7cddfSDavid du Colombier 		return 0;
277dd7cddfSDavid du Colombier 	memset(fnt, 0, sizeof(Font));
287dd7cddfSDavid du Colombier 	fnt->display = d;
297dd7cddfSDavid du Colombier 	fnt->name = strdup(name);
307dd7cddfSDavid du Colombier 	fnt->ncache = NFCACHE+NFLOOK;
317dd7cddfSDavid du Colombier 	fnt->nsubf = NFSUBF;
327dd7cddfSDavid du Colombier 	fnt->cache = malloc(fnt->ncache * sizeof(fnt->cache[0]));
337dd7cddfSDavid du Colombier 	fnt->subf = malloc(fnt->nsubf * sizeof(fnt->subf[0]));
347dd7cddfSDavid du Colombier 	if(fnt->name==0 || fnt->cache==0 || fnt->subf==0){
357dd7cddfSDavid du Colombier     Err2:
367dd7cddfSDavid du Colombier 		free(fnt->name);
377dd7cddfSDavid du Colombier 		free(fnt->cache);
387dd7cddfSDavid du Colombier 		free(fnt->subf);
397dd7cddfSDavid du Colombier 		free(fnt->sub);
407dd7cddfSDavid du Colombier 		free(fnt);
417dd7cddfSDavid du Colombier 		return 0;
427dd7cddfSDavid du Colombier 	}
437dd7cddfSDavid du Colombier 	fnt->height = strtol(s, &s, 0);
447dd7cddfSDavid du Colombier 	s = skip(s);
457dd7cddfSDavid du Colombier 	fnt->ascent = strtol(s, &s, 0);
467dd7cddfSDavid du Colombier 	s = skip(s);
477dd7cddfSDavid du Colombier 	if(fnt->height<=0 || fnt->ascent<=0){
4880ee5cbfSDavid du Colombier 		werrstr("bad height or ascent in font file");
497dd7cddfSDavid du Colombier 		goto Err2;
507dd7cddfSDavid du Colombier 	}
517dd7cddfSDavid du Colombier 	fnt->width = 0;
527dd7cddfSDavid du Colombier 	fnt->nsub = 0;
537dd7cddfSDavid du Colombier 	fnt->sub = 0;
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	memset(fnt->subf, 0, fnt->nsubf * sizeof(fnt->subf[0]));
567dd7cddfSDavid du Colombier 	memset(fnt->cache, 0, fnt->ncache*sizeof(fnt->cache[0]));
577dd7cddfSDavid du Colombier 	fnt->age = 1;
587dd7cddfSDavid du Colombier 	do{
5980ee5cbfSDavid du Colombier 		/* must be looking at a number now */
6080ee5cbfSDavid du Colombier 		if(*s<'0' || '9'<*s){
6180ee5cbfSDavid du Colombier 			werrstr(badform, s-buf);
6280ee5cbfSDavid du Colombier 			goto Err3;
6380ee5cbfSDavid du Colombier 		}
647dd7cddfSDavid du Colombier 		min = strtol(s, &s, 0);
657dd7cddfSDavid du Colombier 		s = skip(s);
6680ee5cbfSDavid du Colombier 		/* must be looking at a number now */
6780ee5cbfSDavid du Colombier 		if(*s<'0' || '9'<*s){
6880ee5cbfSDavid du Colombier 			werrstr(badform, s-buf);
6980ee5cbfSDavid du Colombier 			goto Err3;
7080ee5cbfSDavid du Colombier 		}
717dd7cddfSDavid du Colombier 		max = strtol(s, &s, 0);
727dd7cddfSDavid du Colombier 		s = skip(s);
73*eaba85aaSDavid du Colombier 		if(*s==0 || min>=Runemax || max>=Runemax || min>max){
747dd7cddfSDavid du Colombier 			werrstr("illegal subfont range");
757dd7cddfSDavid du Colombier     Err3:
767dd7cddfSDavid du Colombier 			freefont(fnt);
777dd7cddfSDavid du Colombier 			return 0;
787dd7cddfSDavid du Colombier 		}
797dd7cddfSDavid du Colombier 		t = s;
807dd7cddfSDavid du Colombier 		offset = strtol(s, &t, 0);
817dd7cddfSDavid du Colombier 		if(t>s && (*t==' ' || *t=='\t' || *t=='\n'))
827dd7cddfSDavid du Colombier 			s = skip(t);
837dd7cddfSDavid du Colombier 		else
847dd7cddfSDavid du Colombier 			offset = 0;
857dd7cddfSDavid du Colombier 		fnt->sub = realloc(fnt->sub, (fnt->nsub+1)*sizeof(Cachefont*));
867dd7cddfSDavid du Colombier 		if(fnt->sub == 0){
877dd7cddfSDavid du Colombier 			/* realloc manual says fnt->sub may have been destroyed */
887dd7cddfSDavid du Colombier 			fnt->nsub = 0;
897dd7cddfSDavid du Colombier 			goto Err3;
907dd7cddfSDavid du Colombier 		}
917dd7cddfSDavid du Colombier 		c = malloc(sizeof(Cachefont));
927dd7cddfSDavid du Colombier 		if(c == 0)
937dd7cddfSDavid du Colombier 			goto Err3;
947dd7cddfSDavid du Colombier 		fnt->sub[fnt->nsub] = c;
957dd7cddfSDavid du Colombier 		c->min = min;
967dd7cddfSDavid du Colombier 		c->max = max;
977dd7cddfSDavid du Colombier 		c->offset = offset;
987dd7cddfSDavid du Colombier 		t = s;
997dd7cddfSDavid du Colombier 		while(*s && *s!=' ' && *s!='\n' && *s!='\t')
1007dd7cddfSDavid du Colombier 			s++;
1017dd7cddfSDavid du Colombier 		*s++ = 0;
1027dd7cddfSDavid du Colombier 		c->subfontname = 0;
1037dd7cddfSDavid du Colombier 		c->name = strdup(t);
1047dd7cddfSDavid du Colombier 		if(c->name == 0){
1057dd7cddfSDavid du Colombier 			free(c);
1067dd7cddfSDavid du Colombier 			goto Err3;
1077dd7cddfSDavid du Colombier 		}
1087dd7cddfSDavid du Colombier 		s = skip(s);
1097dd7cddfSDavid du Colombier 		fnt->nsub++;
1107dd7cddfSDavid du Colombier 	}while(*s);
1117dd7cddfSDavid du Colombier 	return fnt;
1127dd7cddfSDavid du Colombier }
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier void
freefont(Font * f)1157dd7cddfSDavid du Colombier freefont(Font *f)
1167dd7cddfSDavid du Colombier {
1177dd7cddfSDavid du Colombier 	int i;
1187dd7cddfSDavid du Colombier 	Cachefont *c;
1197dd7cddfSDavid du Colombier 	Subfont *s;
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	if(f == 0)
1227dd7cddfSDavid du Colombier 		return;
1237dd7cddfSDavid du Colombier 
1247dd7cddfSDavid du Colombier 	for(i=0; i<f->nsub; i++){
1257dd7cddfSDavid du Colombier 		c = f->sub[i];
1267dd7cddfSDavid du Colombier 		free(c->subfontname);
1277dd7cddfSDavid du Colombier 		free(c->name);
1287dd7cddfSDavid du Colombier 		free(c);
1297dd7cddfSDavid du Colombier 	}
1307dd7cddfSDavid du Colombier 	for(i=0; i<f->nsubf; i++){
1317dd7cddfSDavid du Colombier 		s = f->subf[i].f;
132175630faSDavid du Colombier 		if(s && display && s!=display->defaultsubfont)
1337dd7cddfSDavid du Colombier 			freesubfont(s);
1347dd7cddfSDavid du Colombier 	}
1357dd7cddfSDavid du Colombier 	freeimage(f->cacheimage);
1367dd7cddfSDavid du Colombier 	free(f->name);
1377dd7cddfSDavid du Colombier 	free(f->cache);
1387dd7cddfSDavid du Colombier 	free(f->subf);
1397dd7cddfSDavid du Colombier 	free(f->sub);
1407dd7cddfSDavid du Colombier 	free(f);
1417dd7cddfSDavid du Colombier }
142