Commit Diff


commit - 3b634dc7e4ab32a6854c8ec93107b2750bf906e8
commit + b2f9ee0de55f3c59c83f479d12cfe8c894935bd7
blob - 4dfb27faa5d15e00ce525ac8c9dc2947f42aab14
blob + 4e876c170b7def9e2a15ee33da7558ae41b78a48
--- src/libdraw/string.c
+++ src/libdraw/string.c
@@ -65,6 +65,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Fo
 	char **sptr;
 	Rune **rptr;
 	Font *def;
+	Subfont *sf;
 
 	if(s == nil){
 		s = "";
@@ -76,6 +77,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Fo
 		rptr = nil;
 	}else
 		rptr = &r;
+	sf = nil;
 	while((*s || *r) && len){
 		max = Max;
 		if(len < max)
@@ -124,13 +126,18 @@ _string(Image *dst, Point pt, Image *src, Point sp, Fo
 			len -= n;
 		}
 		if(subfontname){
-			if(_getsubfont(f->display, subfontname) == 0){
-				def = f->display->defaultfont;
+			freesubfont(sf);
+			if((sf=_getsubfont(f->display, subfontname)) == 0){
+				def = f->display ? f->display->defaultfont : nil;
 				if(def && f!=def)
 					f = def;
 				else
 					break;
 			}
+			/* 
+			 * must not free sf until cachechars has found it in the cache
+			 * and picked up its own reference.
+			 */
 		}
 	}
 	return pt;
blob - 8d8c6d081a1be0219ccf6c1136b574b1fa869259
blob + 522fbc0115d07609314b5133b5ef1adf11eddbb7
--- src/libdraw/stringwidth.c
+++ src/libdraw/stringwidth.c
@@ -13,6 +13,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
 	Rune rune, **rptr;
 	char *subfontname, **sptr;
 	Font *def;
+	Subfont *sf;
 
 	if(s == nil){
 		s = "";
@@ -30,6 +31,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
 		if(len < max)
 			max = len;
 		n = 0;
+		sf = nil;
 		while((l = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
 			if(++n > 10){
 				if(*r)
@@ -40,19 +42,26 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
 					name = f->name;
 				else
 					name = "unnamed font";
+				freesubfont(sf);
 				fprint(2, "stringwidth: bad character set for rune 0x%.4ux in %s\n", rune, name);
 				return twid;
 			}
 			if(subfontname){
-				if(_getsubfont(f->display, subfontname) == 0){
-					def = f->display->defaultfont;
+				freesubfont(sf);
+				if((sf=_getsubfont(f->display, subfontname)) == 0){
+					def = f->display ? f->display->defaultfont : nil;
 					if(def && f!=def)
 						f = def;
 					else
 						break;
 				}
+				/* 
+				 * must not free sf until cachechars has found it in the cache
+				 * and picked up its own reference.
+				 */
 			}
 		}
+		freesubfont(sf);
 		agefont(f);
 		twid += wid;
 		len -= l;
blob - 61838b0548190d1e622ea654e7a5acc9c9cc3acb
blob + 085afba31bb0b2162bba1a7b7f8a5558515e4eb1
--- src/libdraw/subfont.c
+++ src/libdraw/subfont.c
@@ -5,13 +5,14 @@
 Subfont*
 allocsubfont(char *name, int n, int height, int ascent, Fontchar *info, Image *i)
 {
-	Subfont *f;
+	Subfont *f, *cf;
 
 	assert(height != 0 /* allocsubfont */);
 
 	f = malloc(sizeof(Subfont));
 	if(f == 0)
 		return 0;
+fprint(2, "allocsubfont %p\n", f);
 	f->n = n;
 	f->height = height;
 	f->ascent = ascent;
@@ -19,9 +20,18 @@ allocsubfont(char *name, int n, int height, int ascent
 	f->bits = i;
 	f->ref = 1;
 	if(name){
+		/*
+		 * if already caching this subfont, leave older 
+		 * (and hopefully more widely used) copy in cache.
+		 * this case should not happen -- we got called 
+		 * because cachechars needed this subfont and it
+		 * wasn't in the cache.
+		 */
 		f->name = strdup(name);
-		if(lookupsubfont(i->display, name) == 0)
+		if((cf=lookupsubfont(i->display, name)) == 0)
 			installsubfont(name, f);
+		else
+			freesubfont(cf);	/* drop ref we just picked up */
 	}else
 		f->name = 0;
 	return f;