xref: /plan9/sys/src/libdraw/stringwidth.c (revision be93767fd3d9b466f5cc98d40df522ccdbbcd2c0)
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
_stringnwidth(Font * f,char * s,Rune * r,int len)67dd7cddfSDavid du Colombier _stringnwidth(Font *f, char *s, Rune *r, int len)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	int wid, twid, n, max, l;
99a747e4fSDavid du Colombier 	char *name;
107dd7cddfSDavid du Colombier 	enum { Max = 64 };
117dd7cddfSDavid du Colombier 	ushort cbuf[Max];
129a747e4fSDavid 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;
27*be93767fSDavid du Colombier 	while(len>0 && (*s || *r)){
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){
349a747e4fSDavid du Colombier 				if(*r)
359a747e4fSDavid du Colombier 					rune = *r;
369a747e4fSDavid du Colombier 				else
379a747e4fSDavid du Colombier 					chartorune(&rune, s);
389a747e4fSDavid du Colombier 				if(f->name != nil)
399a747e4fSDavid du Colombier 					name = f->name;
409a747e4fSDavid du Colombier 				else
419a747e4fSDavid du Colombier 					name = "unnamed font";
429a747e4fSDavid 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
stringnwidth(Font * f,char * s,int len)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
stringwidth(Font * f,char * s)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
stringsize(Font * f,char * s)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
runestringnwidth(Font * f,Rune * r,int len)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
runestringwidth(Font * f,Rune * r)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
runestringsize(Font * f,Rune * r)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