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 }