9fans.net/go@v0.0.5/draw/stringwidth.go (about) 1 package draw 2 3 import ( 4 "fmt" 5 "os" 6 ) 7 8 func stringnwidth(f *Font, s string, b []byte, r []rune) int { 9 const Max = 64 10 cbuf := make([]uint16, Max) 11 var in input 12 in.init(s, b, r) 13 twid := 0 14 for !in.done { 15 max := Max 16 n := 0 17 var sf *subfont 18 var l, wid int 19 var subfontname string 20 for { 21 if l, wid, subfontname = cachechars(f, &in, cbuf, max); l > 0 { 22 break 23 } 24 if n++; n > 10 { 25 r := in.ch 26 name := f.Name 27 if name == "" { 28 name = "unnamed font" 29 } 30 sf.free() 31 fmt.Fprintf(os.Stderr, "stringwidth: bad character set for rune %U in %s\n", r, name) 32 return twid 33 } 34 if subfontname != "" { 35 sf.free() 36 var err error 37 sf, err = getsubfont(f.Display, subfontname) 38 if err != nil { 39 if f.Display != nil && f != f.Display.Font { 40 f = f.Display.Font 41 continue 42 } 43 break 44 } 45 /* 46 * must not free sf until cachechars has found it in the cache 47 * and picked up its own reference. 48 */ 49 } 50 } 51 sf.free() 52 agefont(f) 53 twid += wid 54 } 55 return twid 56 } 57 58 // StringWidth returns the number of horizontal pixels that would be occupied 59 // by the string if it were drawn using the font. 60 func (f *Font) StringWidth(s string) int { 61 f.lock() 62 defer f.unlock() 63 return stringnwidth(f, s, nil, nil) 64 } 65 66 // ByteWidth returns the number of horizontal pixels that would be occupied by 67 // the byte slice if it were drawn using the font. 68 func (f *Font) BytesWidth(b []byte) int { 69 f.lock() 70 defer f.unlock() 71 return stringnwidth(f, "", b, nil) 72 } 73 74 // RuneWidth returns the number of horizontal pixels that would be occupied by 75 // the rune slice if it were drawn using the font. 76 func (f *Font) RunesWidth(r []rune) int { 77 f.lock() 78 defer f.unlock() 79 return stringnwidth(f, "", nil, r) 80 } 81 82 // StringSize returns the number of horizontal and vertical pixels that would 83 // be occupied by the string if it were drawn using the font. 84 func (f *Font) StringSize(s string) Point { 85 return Pt(f.StringWidth(s), f.Height) 86 } 87 88 // ByteSize returns the number of horizontal and vertical pixels that would be 89 // occupied by the byte slice if it were drawn using the font. 90 func (f *Font) BytesSize(b []byte) Point { 91 return Pt(f.BytesWidth(b), f.Height) 92 } 93 94 // RuneSize returns the number of horizontal and vertical pixels that would be 95 // occupied by the rune slice if it were drawn using the font. 96 func (f *Font) RunesSize(r []rune) Point { 97 return Pt(f.RunesWidth(r), f.Height) 98 }