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

     1  package frame
     2  
     3  import (
     4  	"unicode/utf8"
     5  
     6  	"9fans.net/go/draw"
     7  )
     8  
     9  func (f *Frame) ptofcharptb(p int, pt draw.Point, bn int) draw.Point {
    10  	for ; bn < len(f.box); bn++ {
    11  		b := &f.box[bn]
    12  		f.cklinewrap(&pt, b)
    13  		l := b.NRUNE()
    14  		if p < l {
    15  			if b.nrune > 0 {
    16  				s := b.bytes
    17  				for ; p > 0; p-- {
    18  					if len(s) == 0 {
    19  						drawerror(f.Display, "frptofchar")
    20  					}
    21  					_, size := utf8.DecodeRune(s)
    22  					pt.X += f.Font.BytesWidth(s[:size])
    23  					s = s[size:]
    24  					if pt.X > f.R.Max.X {
    25  						drawerror(f.Display, "frptofchar")
    26  					}
    27  				}
    28  			}
    29  			break
    30  		}
    31  		p -= l
    32  		f.advance(&pt, b)
    33  	}
    34  	return pt
    35  }
    36  
    37  // PointOf returns
    38  // the location of the upper left corner of the p'th rune,
    39  // starting from 0, in the Frame f. If f holds fewer than p
    40  // runes, frptofchar returns the location of the upper right
    41  // corner of the last character in f.
    42  func (f *Frame) PointOf(p int) draw.Point {
    43  	return f.ptofcharptb(p, f.R.Min, 0)
    44  }
    45  
    46  func (f *Frame) ptofcharnb(p, nb int) draw.Point {
    47  	// doesn't do final f.advance to next line
    48  	box := f.box
    49  	f.box = f.box[:nb]
    50  	pt := f.ptofcharptb(p, f.R.Min, 0)
    51  	f.box = box
    52  	return pt
    53  }
    54  
    55  func (f *Frame) grid(p draw.Point) draw.Point {
    56  	p.Y -= f.R.Min.Y
    57  	p.Y -= p.Y % f.Font.Height
    58  	p.Y += f.R.Min.Y
    59  	if p.X > f.R.Max.X {
    60  		p.X = f.R.Max.X
    61  	}
    62  	return p
    63  }
    64  
    65  // CharOf is the
    66  // inverse of PointOf: it returns the index of the closest rune whose
    67  // image's upper left corner is up and to the left of pt.
    68  func (f *Frame) CharOf(pt draw.Point) int {
    69  	pt = f.grid(pt)
    70  	qt := f.R.Min
    71  	p := 0
    72  	bn := 0
    73  	for ; bn < len(f.box) && qt.Y < pt.Y; bn++ {
    74  		b := &f.box[bn]
    75  		f.cklinewrap(&qt, b)
    76  		if qt.Y >= pt.Y {
    77  			break
    78  		}
    79  		f.advance(&qt, b)
    80  		p += b.NRUNE()
    81  	}
    82  	for ; bn < len(f.box) && qt.X <= pt.X; bn++ {
    83  		b := &f.box[bn]
    84  		f.cklinewrap(&qt, b)
    85  		if qt.Y > pt.Y {
    86  			break
    87  		}
    88  		if qt.X+b.wid > pt.X {
    89  			if b.nrune < 0 {
    90  				f.advance(&qt, b)
    91  			} else {
    92  				s := b.bytes
    93  				for {
    94  					if len(s) == 0 {
    95  						drawerror(f.Display, "end of string in frcharofpt")
    96  					}
    97  					_, size := utf8.DecodeRune(s)
    98  					qt.X += f.Font.BytesWidth(s[:size])
    99  					s = s[size:]
   100  					if qt.X > pt.X {
   101  						break
   102  					}
   103  					p++
   104  				}
   105  			}
   106  		} else {
   107  			p += b.NRUNE()
   108  			f.advance(&qt, b)
   109  		}
   110  	}
   111  	return p
   112  }