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  }