rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 1 | #include <u.h> |
| 2 | #include <libc.h> |
| 3 | #include <draw.h> |
| 4 | |
| 5 | static Rune empty[] = { 0 }; |
| 6 | int |
| 7 | _stringnwidth(Font *f, char *s, Rune *r, int len) |
| 8 | { |
| 9 | int wid, twid, n, max, l; |
| 10 | char *name; |
| 11 | enum { Max = 64 }; |
| 12 | ushort cbuf[Max]; |
| 13 | Rune rune, **rptr; |
| 14 | char *subfontname, **sptr; |
| 15 | Font *def; |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 16 | Subfont *sf; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 17 | |
| 18 | if(s == nil){ |
| 19 | s = ""; |
| 20 | sptr = nil; |
| 21 | }else |
| 22 | sptr = &s; |
| 23 | if(r == nil){ |
| 24 | r = empty; |
| 25 | rptr = nil; |
| 26 | }else |
| 27 | rptr = &r; |
| 28 | twid = 0; |
rsc | 4e20688 | 2004-04-25 20:26:27 +0000 | [diff] [blame] | 29 | while(len>0 && (*s || *r)){ |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 30 | max = Max; |
| 31 | if(len < max) |
| 32 | max = len; |
| 33 | n = 0; |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 34 | sf = nil; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 35 | while((l = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname)) <= 0){ |
| 36 | if(++n > 10){ |
| 37 | if(*r) |
| 38 | rune = *r; |
| 39 | else |
| 40 | chartorune(&rune, s); |
| 41 | if(f->name != nil) |
| 42 | name = f->name; |
| 43 | else |
| 44 | name = "unnamed font"; |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 45 | freesubfont(sf); |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 46 | fprint(2, "stringwidth: bad character set for rune 0x%.4ux in %s\n", rune, name); |
| 47 | return twid; |
| 48 | } |
| 49 | if(subfontname){ |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 50 | freesubfont(sf); |
| 51 | if((sf=_getsubfont(f->display, subfontname)) == 0){ |
| 52 | def = f->display ? f->display->defaultfont : nil; |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 53 | if(def && f!=def) |
| 54 | f = def; |
| 55 | else |
| 56 | break; |
| 57 | } |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 58 | /* |
| 59 | * must not free sf until cachechars has found it in the cache |
| 60 | * and picked up its own reference. |
| 61 | */ |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 62 | } |
| 63 | } |
rsc | b2f9ee0 | 2005-07-13 03:57:24 +0000 | [diff] [blame] | 64 | freesubfont(sf); |
rsc | 76193d7 | 2003-09-30 17:47:42 +0000 | [diff] [blame] | 65 | agefont(f); |
| 66 | twid += wid; |
| 67 | len -= l; |
| 68 | } |
| 69 | return twid; |
| 70 | } |
| 71 | |
| 72 | int |
| 73 | stringnwidth(Font *f, char *s, int len) |
| 74 | { |
| 75 | return _stringnwidth(f, s, nil, len); |
| 76 | } |
| 77 | |
| 78 | int |
| 79 | stringwidth(Font *f, char *s) |
| 80 | { |
| 81 | return _stringnwidth(f, s, nil, 1<<24); |
| 82 | } |
| 83 | |
| 84 | Point |
| 85 | stringsize(Font *f, char *s) |
| 86 | { |
| 87 | return Pt(_stringnwidth(f, s, nil, 1<<24), f->height); |
| 88 | } |
| 89 | |
| 90 | int |
| 91 | runestringnwidth(Font *f, Rune *r, int len) |
| 92 | { |
| 93 | return _stringnwidth(f, nil, r, len); |
| 94 | } |
| 95 | |
| 96 | int |
| 97 | runestringwidth(Font *f, Rune *r) |
| 98 | { |
| 99 | return _stringnwidth(f, nil, r, 1<<24); |
| 100 | } |
| 101 | |
| 102 | Point |
| 103 | runestringsize(Font *f, Rune *r) |
| 104 | { |
| 105 | return Pt(_stringnwidth(f, nil, r, 1<<24), f->height); |
| 106 | } |