ref: 6d42f323eb2dcb1a93433963aa7d6ddee3e048db
parent: ee1f2d5014ad12cddf2ed134d9e9e2dd757c6082
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;
--
⑨