shithub: riscv

Download patch

ref: 2c0490a26ed0565d5e69c88e64c8b185ecab0947
parent: 760b3d06679aa690a5c83d6c9aeed6003f93fdc1
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Mar 10 02:41:45 EDT 2014

libdraw: fix zero stringwidth() bug

stringwidth() and string() sometimes failed spuriously due
to the wrong assumption that cachechars() will only fail
when a different subfont is needed. in fact, cachechars()
can fail for other reasons like when it resizes the fontcache
(or fails todo so).

theres also the case when loadchar() is unable to translate
a character and returns 0. this case needs to be differentiated
from such temporary conditions like fontcache resize or subfont
load to stop the retry loop in string() and stringwidth().

now cachechars() returns -1 to indicate that it cannot
proceed and we test this in string() and stringwidth()
to skip over untranslatable characters to make progress
instead of retrying.

--- a/sys/src/libdraw/font.c
+++ b/sys/src/libdraw/font.c
@@ -7,10 +7,11 @@
 
 #define	PJW	0	/* use NUL==pjw for invisible characters */
 
+/* return number of translated cache indices, 0 must retry, -1 on error */
 int
 cachechars(Font *f, char **ss, Rune **rr, ushort *cp, int max, int *wp, char **subfontname)
 {
-	int i, th, sh, h, w, rw, wid, nc;
+	int i, j, th, sh, h, w, rw, wid, nc;
 	char *sp;
 	Rune r, *rp, vr;
 	ulong a;
@@ -78,14 +79,16 @@
 			}
 		}
 
-		if(c->age == f->age)	/* flush pending string output */
+		if(i > 0 && c->age == f->age)	/* flush pending string output */
 			break;
 
-		if(loadchar(f, r, c, h, i, subfontname) <= 0)
-			break;
+		j = loadchar(f, r, c, h, i, subfontname);
+		if(j <= 0){
+			if(j < 0 || i > 0)	/* flush output or retry */ 
+				break;
+			return -1;		/* stop retrying */
+		}
 
-		c = &f->cache[h];	/* may have reallocated f->cache */
-	
 	    Found:
 		wid += c->width;
 		c->age = f->age;
@@ -282,9 +285,8 @@
 			f->width = wid;
 		if(f->maxdepth < subf->f->bits->depth)
 			f->maxdepth = subf->f->bits->depth;
-		i = fontresize(f, f->width, f->ncache, f->maxdepth);
-		if(i <= 0)
-			return i;
+		if(fontresize(f, f->width, f->ncache, f->maxdepth) <= 0)
+			return -1;
 		/* c is still valid as didn't reallocate f->cache */
 	}
 	c->value = r;
@@ -340,7 +342,7 @@
 	return nf;
 }
 
-/* return whether resize succeeded && f->cache is unchanged */
+/* returns whether resize succeeded && f->cache is unchanged */
 static int
 fontresize(Font *f, int wid, int ncache, int depth)
 {
--- a/sys/src/libdraw/string.c
+++ b/sys/src/libdraw/string.c
@@ -92,7 +92,7 @@
 			}
 		}
 		if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
-			if(subfontname){
+			if(n == 0){
 				if(++try > 10)
 					break;
 				continue;
--- a/sys/src/libdraw/stringwidth.c
+++ b/sys/src/libdraw/stringwidth.c
@@ -39,7 +39,7 @@
 			}
 		}
 		if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
-			if(subfontname){
+			if(n == 0){
 				if(++try > 10)
 					break;
 				continue;