summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2014-03-10 06:41:45 +0100
committercinap_lenrek <cinap_lenrek@felloff.net>2014-03-10 06:41:45 +0100
commit2c0490a26ed0565d5e69c88e64c8b185ecab0947 (patch)
tree31255a83056af8b36712da1906df1d9c552ab561 /sys
parent760b3d06679aa690a5c83d6c9aeed6003f93fdc1 (diff)
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/src/libdraw/font.c22
-rw-r--r--sys/src/libdraw/string.c2
-rw-r--r--sys/src/libdraw/stringwidth.c2
3 files changed, 14 insertions, 12 deletions
diff --git a/sys/src/libdraw/font.c b/sys/src/libdraw/font.c
index 4eaeb9e8d..7247c9a92 100644
--- a/sys/src/libdraw/font.c
+++ b/sys/src/libdraw/font.c
@@ -7,10 +7,11 @@ static int freeup(Font*);
#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 @@ cachechars(Font *f, char **ss, Rune **rr, ushort *cp, int max, int *wp, char **s
}
}
- 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 @@ loadchar(Font *f, Rune r, Cacheinfo *c, int h, int noflush, char **subfontname)
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 @@ freeup(Font *f)
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)
{
diff --git a/sys/src/libdraw/string.c b/sys/src/libdraw/string.c
index 2dc2a63e7..c15bf2777 100644
--- a/sys/src/libdraw/string.c
+++ b/sys/src/libdraw/string.c
@@ -92,7 +92,7 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
}
}
if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
- if(subfontname){
+ if(n == 0){
if(++try > 10)
break;
continue;
diff --git a/sys/src/libdraw/stringwidth.c b/sys/src/libdraw/stringwidth.c
index f0757a095..3548aba0b 100644
--- a/sys/src/libdraw/stringwidth.c
+++ b/sys/src/libdraw/stringwidth.c
@@ -39,7 +39,7 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
}
}
if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
- if(subfontname){
+ if(n == 0){
if(++try > 10)
break;
continue;