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  }