libdraw: fix stringwidth problems

cachechars() used to skip over characters on its own when
loadchar() could not find the character or a PJW replacement.
this resulted in wrong width calculation. now we just return
and handle the case inside _string and _stringwidth.

fix subfont leak in stringwidth()

remove annoying prints in stringwidth()
front
cinap_lenrek 2014-01-06 03:49:14 +01:00
parent b7ab1354e3
commit e3b4950966
3 changed files with 93 additions and 86 deletions

View File

@ -10,7 +10,7 @@ static int freeup(Font*);
int int
cachechars(Font *f, char **ss, Rune **rr, ushort *cp, int max, int *wp, char **subfontname) cachechars(Font *f, char **ss, Rune **rr, ushort *cp, int max, int *wp, char **subfontname)
{ {
int i, th, sh, h, ld, w, rw, wid, nc; int i, th, sh, h, w, rw, wid, nc;
char *sp; char *sp;
Rune r, *rp, vr; Rune r, *rp, vr;
ulong a; ulong a;
@ -81,12 +81,9 @@ 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(c->age == f->age) /* flush pending string output */
break; break;
ld = loadchar(f, r, c, h, i, subfontname); if(loadchar(f, r, c, h, i, subfontname) <= 0)
if(ld <= 0){
if(ld == 0)
continue;
break; break;
}
c = &f->cache[h]; /* may have reallocated f->cache */ c = &f->cache[h]; /* may have reallocated f->cache */
Found: Found:

View File

@ -58,13 +58,12 @@ runestringnop(Image *dst, Point pt, Image *src, Point sp, Font *f, Rune *r, int
Point Point
_string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp, Drawop op) _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp, Drawop op)
{ {
int m, n, wid, max; int m, n, wid, max, try;
ushort cbuf[Max], *c, *ec; ushort cbuf[Max], *c, *ec;
uchar *b; uchar *b;
char *subfontname; char *subfontname;
char **sptr; char **sptr;
Rune **rptr; Rune **rptr, rune;
Font *def;
Subfont *sf; Subfont *sf;
if(s == nil){ if(s == nil){
@ -78,63 +77,76 @@ _string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, i
}else }else
rptr = &r; rptr = &r;
sf = nil; sf = nil;
while((*s || *r) && len){ try = 0;
while((*s || *r) && len > 0){
max = Max; max = Max;
if(len < max) if(len < max)
max = len; max = len;
n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname); if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
if(n > 0){ if(subfontname){
_setdrawop(dst->display, op); if(++try > 10)
m = 47+2*n;
if(bg)
m += 4+2*4;
b = bufimage(dst->display, m);
if(b == 0){
fprint(2, "string: %r\n");
break;
}
if(bg)
b[0] = 'x';
else
b[0] = 's';
BPLONG(b+1, dst->id);
BPLONG(b+5, src->id);
BPLONG(b+9, f->cacheimage->id);
BPLONG(b+13, pt.x);
BPLONG(b+17, pt.y+f->ascent);
BPLONG(b+21, clipr.min.x);
BPLONG(b+25, clipr.min.y);
BPLONG(b+29, clipr.max.x);
BPLONG(b+33, clipr.max.y);
BPLONG(b+37, sp.x);
BPLONG(b+41, sp.y);
BPSHORT(b+45, n);
b += 47;
if(bg){
BPLONG(b, bg->id);
BPLONG(b+4, bgp.x);
BPLONG(b+8, bgp.y);
b += 12;
}
ec = &cbuf[n];
for(c=cbuf; c<ec; c++, b+=2)
BPSHORT(b, *c);
pt.x += wid;
bgp.x += wid;
agefont(f);
len -= n;
}
if(subfontname){
freesubfont(sf);
if((sf=_getsubfont(f->display, subfontname)) == 0){
def = f->display ? f->display->defaultfont : nil;
if(def && f!=def)
f = def;
else
break; break;
Nextfont:
freesubfont(sf);
if((sf=_getsubfont(f->display, subfontname)) != nil)
continue;
if(f->display->defaultfont == nil || f->display->defaultfont == f)
break;
f = f->display->defaultfont;
continue;
} }
if(*r)
r++;
else
s += chartorune(&rune, s);
len--;
continue;
} }
try = 0;
_setdrawop(dst->display, op);
m = 47+2*n;
if(bg)
m += 4+2*4;
b = bufimage(dst->display, m);
if(b == 0){
fprint(2, "string: %r\n");
break;
}
if(bg)
b[0] = 'x';
else
b[0] = 's';
BPLONG(b+1, dst->id);
BPLONG(b+5, src->id);
BPLONG(b+9, f->cacheimage->id);
BPLONG(b+13, pt.x);
BPLONG(b+17, pt.y+f->ascent);
BPLONG(b+21, clipr.min.x);
BPLONG(b+25, clipr.min.y);
BPLONG(b+29, clipr.max.x);
BPLONG(b+33, clipr.max.y);
BPLONG(b+37, sp.x);
BPLONG(b+41, sp.y);
BPSHORT(b+45, n);
b += 47;
if(bg){
BPLONG(b, bg->id);
BPLONG(b+4, bgp.x);
BPLONG(b+8, bgp.y);
b += 12;
}
ec = &cbuf[n];
for(c=cbuf; c<ec; c++, b+=2)
BPSHORT(b, *c);
pt.x += wid;
bgp.x += wid;
agefont(f);
len -= n;
if(subfontname)
goto Nextfont;
} }
freesubfont(sf); freesubfont(sf);
return pt; return pt;

View File

@ -5,13 +5,11 @@
int int
_stringnwidth(Font *f, char *s, Rune *r, int len) _stringnwidth(Font *f, char *s, Rune *r, int len)
{ {
int wid, twid, n, max, l; int wid, twid, n, max, try;
char *name;
enum { Max = 64 }; enum { Max = 64 };
ushort cbuf[Max]; ushort cbuf[Max];
Rune rune, **rptr; Rune rune, **rptr;
char *subfontname, **sptr; char *subfontname, **sptr;
Font *def;
Subfont *sf; Subfont *sf;
if(s == nil){ if(s == nil){
@ -26,38 +24,38 @@ _stringnwidth(Font *f, char *s, Rune *r, int len)
rptr = &r; rptr = &r;
sf = nil; sf = nil;
twid = 0; twid = 0;
while(len>0 && (*s || *r)){ try = 0;
while((*s || *r) && len > 0){
max = Max; max = Max;
if(len < max) if(len < max)
max = len; max = len;
n = 0; if((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
while((l = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
if(++n > 10){
if(*r)
rune = *r;
else
chartorune(&rune, s);
if(f->name != nil)
name = f->name;
else
name = "unnamed font";
fprint(2, "stringwidth: bad character set for rune 0x%.4ux in %s\n", rune, name);
return twid;
}
if(subfontname){ if(subfontname){
if(++try > 10)
break;
Nextfont:
freesubfont(sf); freesubfont(sf);
if((sf=_getsubfont(f->display, subfontname)) == 0){ if((sf=_getsubfont(f->display, subfontname)) != nil)
def = f->display->defaultfont; continue;
if(def && f!=def) if(f->display == nil || f->display->defaultfont == nil || f->display->defaultfont == f)
f = def; break;
else f = f->display->defaultfont;
break; continue;
}
} }
if(*r)
r++;
else
s += chartorune(&rune, s);
len--;
continue;
} }
try = 0;
agefont(f); agefont(f);
twid += wid; twid += wid;
len -= l; len -= n;
if(subfontname)
goto Nextfont;
} }
freesubfont(sf); freesubfont(sf);
return twid; return twid;