9fans.net/go@v0.0.5/draw/frame/frutil.go (about) 1 package frame 2 3 import ( 4 "unicode/utf8" 5 6 "9fans.net/go/draw" 7 ) 8 9 // canfit returns the number of runes from b that 10 // will fit into the frame when drawn starting at pt. 11 func (f *Frame) canfit(pt draw.Point, b *box) int { 12 left := f.R.Max.X - pt.X 13 if b.nrune < 0 { 14 if b.minwid <= left { 15 return 1 16 } 17 return 0 18 } 19 if left >= b.wid { 20 return b.nrune 21 } 22 p := b.bytes 23 for nr := 0; nr < b.nrune; nr++ { 24 _, size := utf8.DecodeRune(p) 25 left -= f.Font.BytesWidth(p[:size]) 26 p = p[size:] 27 if left < 0 { 28 return nr 29 } 30 } 31 drawerror(f.Display, "_frcanfit can't") 32 return 0 33 } 34 35 // cklinewrap checks whether b when drawn at p will 36 // fit within f.R. If not, it updates p to the start of the next line. 37 func (f *Frame) cklinewrap(p *draw.Point, b *box) { 38 w := b.wid 39 if b.nrune < 0 { 40 w = b.minwid 41 } 42 if w > f.R.Max.X-p.X { 43 p.X = f.R.Min.X 44 p.Y += f.Font.Height 45 } 46 } 47 48 // cklinewrap0 is like cklinewrap but with a weaker criterion 49 // for wrapping: it only wraps if none of the text of b 50 // will fit. 51 func (f *Frame) cklinewrap0(p *draw.Point, b *box) { 52 if f.canfit(*p, b) == 0 { 53 p.X = f.R.Min.X 54 p.Y += f.Font.Height 55 } 56 } 57 58 func (f *Frame) advance(p *draw.Point, b *box) { 59 if b.nrune < 0 && b.bc == '\n' { 60 p.X = f.R.Min.X 61 p.Y += f.Font.Height 62 } else { 63 p.X += b.wid 64 } 65 } 66 67 func (f *Frame) newwid(pt draw.Point, b *box) int { 68 b.wid = f.newwid0(pt, b) 69 return b.wid 70 } 71 72 func (f *Frame) newwid0(pt draw.Point, b *box) int { 73 c := f.R.Max.X 74 x := pt.X 75 if b.nrune >= 0 || b.bc != '\t' { 76 return b.wid 77 } 78 if x+b.minwid > c { 79 pt.X = f.R.Min.X 80 x = pt.X 81 } 82 x += f.MaxTab 83 x -= (x - f.R.Min.X) % f.MaxTab 84 if x-pt.X < b.minwid || x > c { 85 x = pt.X + b.minwid 86 } 87 return x - pt.X 88 } 89 90 func (f *Frame) clean(pt draw.Point, n0, n1 int) { 91 // look for mergeable boxes 92 93 c := f.R.Max.X 94 nb := n0 95 for ; nb < n1-1; nb++ { 96 b := &f.box[nb] 97 f.cklinewrap(&pt, b) 98 for b.nrune >= 0 && nb < n1-1 && f.box[nb+1].nrune >= 0 && pt.X+b.wid+f.box[nb+1].wid < c { 99 f.mergebox(nb) 100 n1-- 101 b = &f.box[nb] 102 } 103 f.advance(&pt, &f.box[nb]) 104 } 105 for ; nb < len(f.box); nb++ { 106 b := &f.box[nb] 107 f.cklinewrap(&pt, b) 108 f.advance(&pt, &f.box[nb]) 109 } 110 f.LastLineFull = pt.Y >= f.R.Max.Y 111 }