shithub: riscv

Download patch

ref: e3b49509662cc1da997db4113b743d477a9e1ac0
parent: b7ab1354e3fdf32d2a587de00b4b324779b34b20
author: cinap_lenrek <[email protected]>
date: Sun Jan 5 22:49:14 EST 2014

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()

--- a/sys/src/libdraw/font.c
+++ b/sys/src/libdraw/font.c
@@ -10,7 +10,7 @@
 int
 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;
 	Rune r, *rp, vr;
 	ulong a;
@@ -81,12 +81,9 @@
 		if(c->age == f->age)	/* flush pending string output */
 			break;
 
-		ld = loadchar(f, r, c, h, i, subfontname);
-		if(ld <= 0){
-			if(ld == 0)
-				continue;
+		if(loadchar(f, r, c, h, i, subfontname) <= 0)
 			break;
-		}
+
 		c = &f->cache[h];	/* may have reallocated f->cache */
 	
 	    Found:
--- a/sys/src/libdraw/string.c
+++ b/sys/src/libdraw/string.c
@@ -58,13 +58,12 @@
 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)
 {
-	int m, n, wid, max;
+	int m, n, wid, max, try;
 	ushort cbuf[Max], *c, *ec;
 	uchar *b;
 	char *subfontname;
 	char **sptr;
-	Rune **rptr;
-	Font *def;
+	Rune **rptr, rune;
 	Subfont *sf;
 
 	if(s == nil){
@@ -78,63 +77,76 @@
 	}else
 		rptr = &r;
 	sf = nil;
-	while((*s || *r) && len){
+	try = 0;
+	while((*s || *r) && len > 0){
 		max = Max;
 		if(len < max)
 			max = len;
-		n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname);
-		if(n > 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((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
+			if(subfontname){
+				if(++try > 10)
+					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(bg)
-				b[0] = 'x';
+			if(*r)
+				r++;
 			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;
+				s += chartorune(&rune, s);
+			len--;
+			continue;
 		}
-		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;
-			}
+		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);
 	return pt;
--- a/sys/src/libdraw/stringwidth.c
+++ b/sys/src/libdraw/stringwidth.c
@@ -5,13 +5,11 @@
 int
 _stringnwidth(Font *f, char *s, Rune *r, int len)
 {
-	int wid, twid, n, max, l;
-	char *name;
+	int wid, twid, n, max, try;
 	enum { Max = 64 };
 	ushort cbuf[Max];
 	Rune rune, **rptr;
 	char *subfontname, **sptr;
-	Font *def;
 	Subfont *sf;
 
 	if(s == nil){
@@ -26,38 +24,38 @@
 		rptr = &r;
 	sf = nil;
 	twid = 0;
-	while(len>0 && (*s || *r)){
+	try = 0;
+	while((*s || *r) && len > 0){
 		max = Max;
 		if(len < max)
 			max = len;
-		n = 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((n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
 			if(subfontname){
+				if(++try > 10)
+					break;
+			Nextfont:
 				freesubfont(sf);
-				if((sf=_getsubfont(f->display, subfontname)) == 0){
-					def = f->display->defaultfont;
-					if(def && f!=def)
-						f = def;
-					else
-						break;
-				}
+				if((sf=_getsubfont(f->display, subfontname)) != nil)
+					continue;
+				if(f->display == nil || 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;
 		agefont(f);
 		twid += wid;
-		len -= l;
+		len -= n;
+
+		if(subfontname)
+			goto Nextfont;
 	}
 	freesubfont(sf);
 	return twid;