xref: /plan9-contrib/sys/src/libdraw/stringwidth.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier int
67dd7cddfSDavid du Colombier _stringnwidth(Font *f, char *s, Rune *r, int len)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	int wid, twid, n, max, l;
9*9a747e4fSDavid du Colombier 	char *name;
107dd7cddfSDavid du Colombier 	enum { Max = 64 };
117dd7cddfSDavid du Colombier 	ushort cbuf[Max];
12*9a747e4fSDavid du Colombier 	Rune rune, **rptr;
137dd7cddfSDavid du Colombier 	char *subfontname, **sptr;
147dd7cddfSDavid du Colombier 	Font *def;
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier 	if(s == nil){
177dd7cddfSDavid du Colombier 		s = "";
187dd7cddfSDavid du Colombier 		sptr = nil;
197dd7cddfSDavid du Colombier 	}else
207dd7cddfSDavid du Colombier 		sptr = &s;
217dd7cddfSDavid du Colombier 	if(r == nil){
227dd7cddfSDavid du Colombier 		r = L"";
237dd7cddfSDavid du Colombier 		rptr = nil;
247dd7cddfSDavid du Colombier 	}else
257dd7cddfSDavid du Colombier 		rptr = &r;
267dd7cddfSDavid du Colombier 	twid = 0;
277dd7cddfSDavid du Colombier 	while((*s || *r) && len){
287dd7cddfSDavid du Colombier 		max = Max;
297dd7cddfSDavid du Colombier 		if(len < max)
307dd7cddfSDavid du Colombier 			max = len;
317dd7cddfSDavid du Colombier 		n = 0;
327dd7cddfSDavid du Colombier 		while((l = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){
337dd7cddfSDavid du Colombier 			if(++n > 10){
34*9a747e4fSDavid du Colombier 				if(*r)
35*9a747e4fSDavid du Colombier 					rune = *r;
36*9a747e4fSDavid du Colombier 				else
37*9a747e4fSDavid du Colombier 					chartorune(&rune, s);
38*9a747e4fSDavid du Colombier 				if(f->name != nil)
39*9a747e4fSDavid du Colombier 					name = f->name;
40*9a747e4fSDavid du Colombier 				else
41*9a747e4fSDavid du Colombier 					name = "unnamed font";
42*9a747e4fSDavid du Colombier 				fprint(2, "stringwidth: bad character set for rune 0x%.4ux in %s\n", rune, name);
437dd7cddfSDavid du Colombier 				return twid;
447dd7cddfSDavid du Colombier 			}
457dd7cddfSDavid du Colombier 			if(subfontname){
467dd7cddfSDavid du Colombier 				if(_getsubfont(f->display, subfontname) == 0){
477dd7cddfSDavid du Colombier 					def = f->display->defaultfont;
487dd7cddfSDavid du Colombier 					if(def && f!=def)
497dd7cddfSDavid du Colombier 						f = def;
507dd7cddfSDavid du Colombier 					else
517dd7cddfSDavid du Colombier 						break;
527dd7cddfSDavid du Colombier 				}
537dd7cddfSDavid du Colombier 			}
547dd7cddfSDavid du Colombier 		}
557dd7cddfSDavid du Colombier 		agefont(f);
567dd7cddfSDavid du Colombier 		twid += wid;
577dd7cddfSDavid du Colombier 		len -= l;
587dd7cddfSDavid du Colombier 	}
597dd7cddfSDavid du Colombier 	return twid;
607dd7cddfSDavid du Colombier }
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier int
637dd7cddfSDavid du Colombier stringnwidth(Font *f, char *s, int len)
647dd7cddfSDavid du Colombier {
657dd7cddfSDavid du Colombier 	return _stringnwidth(f, s, nil, len);
667dd7cddfSDavid du Colombier }
677dd7cddfSDavid du Colombier 
687dd7cddfSDavid du Colombier int
697dd7cddfSDavid du Colombier stringwidth(Font *f, char *s)
707dd7cddfSDavid du Colombier {
717dd7cddfSDavid du Colombier 	return _stringnwidth(f, s, nil, 1<<24);
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier Point
757dd7cddfSDavid du Colombier stringsize(Font *f, char *s)
767dd7cddfSDavid du Colombier {
777dd7cddfSDavid du Colombier 	return Pt(_stringnwidth(f, s, nil, 1<<24), f->height);
787dd7cddfSDavid du Colombier }
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier int
817dd7cddfSDavid du Colombier runestringnwidth(Font *f, Rune *r, int len)
827dd7cddfSDavid du Colombier {
837dd7cddfSDavid du Colombier 	return _stringnwidth(f, nil, r, len);
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier int
877dd7cddfSDavid du Colombier runestringwidth(Font *f, Rune *r)
887dd7cddfSDavid du Colombier {
897dd7cddfSDavid du Colombier 	return _stringnwidth(f, nil, r, 1<<24);
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier Point
937dd7cddfSDavid du Colombier runestringsize(Font *f, Rune *r)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier 	return Pt(_stringnwidth(f, nil, r, 1<<24), f->height);
967dd7cddfSDavid du Colombier }
97