9fans.net/go@v0.0.5/draw/string.go (about)

     1  package draw
     2  
     3  // String draws the string in the specified font, placing the upper left corner at p.
     4  // It draws the text using src, with sp aligned to p, using operation SoverD onto dst.
     5  // String returns a Point that is the position of the next character that would be drawn
     6  // if the string were longer.
     7  //
     8  // For characters with undefined or zero-width images in the font,
     9  // the character at font position 0 (NUL) is drawn instead.
    10  func (dst *Image) String(p Point, src *Image, sp Point, f *Font, s string) Point {
    11  	dst.Display.mu.Lock()
    12  	defer dst.Display.mu.Unlock()
    13  	return _string(dst, p, src, sp, f, s, nil, nil, dst.Clipr, nil, ZP, SoverD)
    14  }
    15  
    16  // StringOp is like String but specifies an explicit Porter-Duff operator.
    17  func (dst *Image) StringOp(p Point, src *Image, sp Point, f *Font, s string, op Op) Point {
    18  	dst.Display.mu.Lock()
    19  	defer dst.Display.mu.Unlock()
    20  	return _string(dst, p, src, sp, f, s, nil, nil, dst.Clipr, nil, ZP, op)
    21  }
    22  
    23  // StringBg is like String but draws the background bg behind the characters,
    24  // with bgp aligned to p, before drawing the text.
    25  func (dst *Image) StringBg(p Point, src *Image, sp Point, f *Font, s string, bg *Image, bgp Point) Point {
    26  	dst.Display.mu.Lock()
    27  	defer dst.Display.mu.Unlock()
    28  	return _string(dst, p, src, sp, f, s, nil, nil, dst.Clipr, bg, bgp, SoverD)
    29  }
    30  
    31  // StringBgOp is like StringBg but specifies an explicit Porter-Duff operator.
    32  func (dst *Image) StringBgOp(p Point, src *Image, sp Point, f *Font, s string, bg *Image, bgp Point, op Op) Point {
    33  	dst.Display.mu.Lock()
    34  	defer dst.Display.mu.Unlock()
    35  	return _string(dst, p, src, sp, f, s, nil, nil, dst.Clipr, bg, bgp, op)
    36  }
    37  
    38  // Runes is like String but accepts a rune slice instead of a string.
    39  func (dst *Image) Runes(p Point, src *Image, sp Point, f *Font, r []rune) Point {
    40  	dst.Display.mu.Lock()
    41  	defer dst.Display.mu.Unlock()
    42  	return _string(dst, p, src, sp, f, "", nil, r, dst.Clipr, nil, ZP, SoverD)
    43  }
    44  
    45  // RunesOp is like StringOp but accepts a rune slice instead of a string.
    46  func (dst *Image) RunesOp(p Point, src *Image, sp Point, f *Font, r []rune, op Op) Point {
    47  	dst.Display.mu.Lock()
    48  	defer dst.Display.mu.Unlock()
    49  	return _string(dst, p, src, sp, f, "", nil, r, dst.Clipr, nil, ZP, op)
    50  }
    51  
    52  // RunesBg is like StringBg but accepts a rune slice instead of a string.
    53  func (dst *Image) RunesBg(p Point, src *Image, sp Point, f *Font, r []rune, bg *Image, bgp Point) Point {
    54  	dst.Display.mu.Lock()
    55  	defer dst.Display.mu.Unlock()
    56  	return _string(dst, p, src, sp, f, "", nil, r, dst.Clipr, bg, bgp, SoverD)
    57  }
    58  
    59  // RunesBgOp is like StringBgOp but accepts a rune slice instead of a string.
    60  func (dst *Image) RunesBgOp(p Point, src *Image, sp Point, f *Font, r []rune, bg *Image, bgp Point, op Op) Point {
    61  	dst.Display.mu.Lock()
    62  	defer dst.Display.mu.Unlock()
    63  	return _string(dst, p, src, sp, f, "", nil, r, dst.Clipr, bg, bgp, op)
    64  }
    65  
    66  // Bytes is like String but accepts a UTF-8-encoded byte slice instead of a string.
    67  func (dst *Image) Bytes(p Point, src *Image, sp Point, f *Font, b []byte) Point {
    68  	dst.Display.mu.Lock()
    69  	defer dst.Display.mu.Unlock()
    70  	return _string(dst, p, src, sp, f, "", b, nil, dst.Clipr, nil, ZP, SoverD)
    71  }
    72  
    73  // BytesOp is like StringOp but accepts a UTF-8-encoded byte slice instead of a string.
    74  func (dst *Image) BytesOp(p Point, src *Image, sp Point, f *Font, b []byte, op Op) Point {
    75  	dst.Display.mu.Lock()
    76  	defer dst.Display.mu.Unlock()
    77  	return _string(dst, p, src, sp, f, "", b, nil, dst.Clipr, nil, ZP, op)
    78  }
    79  
    80  // BytesBg is like StringBg but accepts a UTF-8-encoded byte slice instead of a string.
    81  func (dst *Image) BytesBg(p Point, src *Image, sp Point, f *Font, b []byte, bg *Image, bgp Point) Point {
    82  	dst.Display.mu.Lock()
    83  	defer dst.Display.mu.Unlock()
    84  	return _string(dst, p, src, sp, f, "", b, nil, dst.Clipr, bg, bgp, SoverD)
    85  }
    86  
    87  // BytesBgOp is like StringBgOp but accepts a UTF-8-encoded byte slice instead of a string.
    88  func (dst *Image) BytesBgOp(p Point, src *Image, sp Point, f *Font, b []byte, bg *Image, bgp Point, op Op) Point {
    89  	dst.Display.mu.Lock()
    90  	defer dst.Display.mu.Unlock()
    91  	return _string(dst, p, src, sp, f, "", b, nil, dst.Clipr, bg, bgp, op)
    92  }
    93  
    94  func _string(dst *Image, p Point, src *Image, sp Point, f *Font, s string, b []byte, r []rune, clipr Rectangle, bg *Image, bgp Point, op Op) Point {
    95  	var in input
    96  	in.init(s, b, r)
    97  	const Max = 100
    98  	cbuf := make([]uint16, Max)
    99  	var sf *subfont
   100  	for !in.done {
   101  		max := Max
   102  		n, wid, subfontname := cachechars(f, &in, cbuf, max)
   103  		if n > 0 {
   104  			setdrawop(dst.Display, op)
   105  			m := 47 + 2*n
   106  			if bg != nil {
   107  				m += 4 + 2*4
   108  			}
   109  			b := dst.Display.bufimage(m)
   110  			if bg != nil {
   111  				b[0] = 'x'
   112  			} else {
   113  				b[0] = 's'
   114  			}
   115  			bplong(b[1:], uint32(dst.id))
   116  			bplong(b[5:], uint32(src.id))
   117  			bplong(b[9:], uint32(f.cacheimage.id))
   118  			bplong(b[13:], uint32(p.X))
   119  			bplong(b[17:], uint32(p.Y+f.Ascent))
   120  			bplong(b[21:], uint32(clipr.Min.X))
   121  			bplong(b[25:], uint32(clipr.Min.Y))
   122  			bplong(b[29:], uint32(clipr.Max.X))
   123  			bplong(b[33:], uint32(clipr.Max.Y))
   124  			bplong(b[37:], uint32(sp.X))
   125  			bplong(b[41:], uint32(sp.Y))
   126  			bpshort(b[45:], uint16(n))
   127  			b = b[47:]
   128  			if bg != nil {
   129  				bplong(b, uint32(bg.id))
   130  				bplong(b[4:], uint32(bgp.X))
   131  				bplong(b[8:], uint32(bgp.Y))
   132  				b = b[12:]
   133  			}
   134  			for i, c := range cbuf[:n] {
   135  				bpshort(b[2*i:], c)
   136  			}
   137  			p.X += wid
   138  			bgp.X += wid
   139  			agefont(f)
   140  		}
   141  		if subfontname != "" {
   142  			sf.free()
   143  			var err error
   144  			sf, err = getsubfont(f.Display, subfontname)
   145  			if err != nil {
   146  				if f.Display != nil && f != f.Display.Font {
   147  					f = f.Display.Font
   148  					continue
   149  				}
   150  				break
   151  			}
   152  			/*
   153  			 * must not free sf until cachechars has found it in the cache
   154  			 * and picked up its own reference.
   155  			 */
   156  		}
   157  	}
   158  	return p
   159  }