github.com/jmigpin/editor@v1.6.0/util/drawutil/drawer4/drawer_test.go (about)

     1  package drawer4
     2  
     3  import (
     4  	"fmt"
     5  	"image"
     6  	"image/color"
     7  	"image/draw"
     8  	"image/png"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/golang/freetype/truetype"
    14  	"github.com/jmigpin/editor/util/fontutil"
    15  	"github.com/jmigpin/editor/util/iout/iorw"
    16  	"golang.org/x/image/colornames"
    17  )
    18  
    19  //godebug:annotatepackage
    20  
    21  func init() {
    22  	useSpaceForMargin = true
    23  }
    24  
    25  func TestEmpty(t *testing.T) {
    26  	d := New()
    27  	d.SetFontFace(fontutil.DefaultFontFace())
    28  	d.SetBounds(image.Rect(0, 0, 100, 100))
    29  
    30  	s := ""
    31  	r := iorw.NewStringReaderAt(s)
    32  	d.SetReader(r)
    33  
    34  	w := d.wlineStartIndex(true, 10, 0, nil)
    35  	if w != 0 {
    36  		t.Fatal()
    37  	}
    38  }
    39  
    40  func TestNLinesStartIndex1(t *testing.T) {
    41  	d := New()
    42  	d.SetFontFace(fontutil.DefaultFontFace())
    43  	d.SetBounds(image.Rect(0, 0, 100, 100))
    44  
    45  	s := "111\n222\n333"
    46  	r := iorw.NewStringReaderAt(s)
    47  	d.SetReader(r)
    48  	pos := r.Max()
    49  	d.SetRuneOffset(pos)
    50  	w := d.iters.lineStart.lineStartIndex(pos, 0)
    51  	if w != 8 {
    52  		t.Fatal()
    53  	}
    54  	w = d.iters.lineStart.lineStartIndex(pos, 1)
    55  	if w != 4 {
    56  		t.Fatal()
    57  	}
    58  	w = d.iters.lineStart.lineStartIndex(pos, 2)
    59  	if w != 0 {
    60  		t.Fatal()
    61  	}
    62  	w = d.iters.lineStart.lineStartIndex(pos, 100)
    63  	if w != 0 {
    64  		t.Fatal()
    65  	}
    66  }
    67  
    68  //----------
    69  
    70  func TestImg01(t *testing.T) {
    71  	d, img := newTestDrawer()
    72  
    73  	s := "11111\n22222\n33333\n44444"
    74  	r := iorw.NewStringReaderAt(s)
    75  	d.SetReader(r)
    76  
    77  	d.Draw(img)
    78  	cmpResult(t, img, "img01")
    79  }
    80  
    81  func TestImg01bDrawFullLineAtEndOfLineOffset(t *testing.T) {
    82  	d, img := newTestDrawer()
    83  
    84  	s := "11111\n22222\n33333\n44444"
    85  	r := iorw.NewStringReaderAt(s)
    86  	d.SetReader(r)
    87  
    88  	d.SetRuneOffset(5)
    89  
    90  	d.Draw(img)
    91  	cmpResult(t, img, "img01b")
    92  }
    93  
    94  func TestImg02WrapLine(t *testing.T) {
    95  	d, img := newTestDrawer()
    96  
    97  	s := "111111111\n22222\n33333\n44444"
    98  	r := iorw.NewStringReaderAt(s)
    99  	d.SetReader(r)
   100  
   101  	d.Draw(img)
   102  	cmpResult(t, img, "img02")
   103  }
   104  
   105  func TestImg03Ident(t *testing.T) {
   106  	d, img := newTestDrawer()
   107  
   108  	s := "  11111111111\n22222\n33333\n44444"
   109  	r := iorw.NewStringReaderAt(s)
   110  	d.SetReader(r)
   111  
   112  	d.Draw(img)
   113  	cmpResult(t, img, "img03")
   114  }
   115  
   116  func TestImg04Offset1(t *testing.T) {
   117  	d, img := newTestDrawer()
   118  
   119  	s := "  111111111111\n22222\n33333\n44444"
   120  	r := iorw.NewStringReaderAt(s)
   121  	d.SetReader(r)
   122  	d.SetRuneOffset(8)
   123  
   124  	d.Draw(img)
   125  	cmpResult(t, img, "img04")
   126  }
   127  
   128  func TestImg04bOffset2(t *testing.T) {
   129  	d, img := newTestDrawer()
   130  
   131  	s := "  1111111\n22222\n33333\n44444"
   132  	r := iorw.NewStringReaderAt(s)
   133  	d.SetReader(r)
   134  	d.SetRuneOffset(8)
   135  
   136  	d.Draw(img)
   137  	cmpResult(t, img, "img04b")
   138  }
   139  
   140  func TestImg05RunePerLine(t *testing.T) {
   141  	rect := image.Rect(0, 0, 14, 100)
   142  	d, img := newTestDrawerRect(rect)
   143  
   144  	s := "WWW"
   145  	r := iorw.NewStringReaderAt(s)
   146  	d.SetReader(r)
   147  
   148  	d.Draw(img)
   149  	cmpResult(t, img, "img05")
   150  }
   151  
   152  func TestImg06Scroll1(t *testing.T) {
   153  	d, img := newTestDrawer()
   154  
   155  	s := "111111\n22222\n33333\n44444"
   156  	r := iorw.NewStringReaderAt(s)
   157  	d.SetReader(r)
   158  
   159  	sy := d.scrollSizeYDown(2)
   160  	d.SetScrollOffset(image.Point{0, sy})
   161  
   162  	d.Draw(img)
   163  	cmpResult(t, img, "img06")
   164  }
   165  
   166  func TestImg07Scroll2(t *testing.T) {
   167  	d, img := newTestDrawer()
   168  
   169  	s := "  11111111111\n22222\n33333\n44444"
   170  	r := iorw.NewStringReaderAt(s)
   171  	d.SetReader(r)
   172  
   173  	sy := d.scrollSizeYDown(1)
   174  	d.SetRuneOffset(sy)
   175  
   176  	sy = d.scrollSizeYDown(1) // 2nd line
   177  	d.SetRuneOffset(sy)
   178  
   179  	d.Draw(img)
   180  	cmpResult(t, img, "img07")
   181  }
   182  
   183  func TestImg08Scroll3(t *testing.T) {
   184  	d, img := newTestDrawer()
   185  
   186  	s := "  11111111111\n22222\n33333\n44444"
   187  	r := iorw.NewStringReaderAt(s)
   188  	d.SetReader(r)
   189  
   190  	d.SetRuneOffset(15)
   191  
   192  	sy := d.scrollSizeYUp(1)
   193  	d.SetRuneOffset(sy)
   194  
   195  	sy = d.scrollSizeYUp(1) // 2nd line
   196  	d.SetRuneOffset(sy)
   197  
   198  	d.Draw(img)
   199  	cmpResult(t, img, "img08")
   200  }
   201  
   202  func TestImg09Visible(t *testing.T) {
   203  	d, img := newTestDrawer()
   204  
   205  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   206  	r := iorw.NewStringReaderAt(s)
   207  	d.SetReader(r)
   208  
   209  	o := d.RangeVisibleOffset(r.Max(), 0)
   210  	d.SetRuneOffset(o)
   211  
   212  	d.Draw(img)
   213  	cmpResult(t, img, "img09")
   214  }
   215  
   216  func TestImg10Visible(t *testing.T) {
   217  	d, img := newTestDrawer()
   218  
   219  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   220  	r := iorw.NewStringReaderAt(s)
   221  	d.SetReader(r)
   222  
   223  	o := d.RangeVisibleOffset(19, 4) // line with 4's
   224  	d.SetRuneOffset(o)
   225  
   226  	d.Draw(img)
   227  	cmpResult(t, img, "img10")
   228  }
   229  
   230  func TestImg11Visible(t *testing.T) {
   231  	d, img := newTestDrawer()
   232  
   233  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   234  	r := iorw.NewStringReaderAt(s)
   235  	d.SetReader(r)
   236  
   237  	o := d.RangeVisibleOffset(19, 7) // line with 4's
   238  	d.SetRuneOffset(o)
   239  
   240  	d.Draw(img)
   241  	cmpResult(t, img, "img11")
   242  }
   243  
   244  func TestImg12Cursor(t *testing.T) {
   245  	d, img := newTestDrawer()
   246  
   247  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   248  	r := iorw.NewStringReaderAt(s)
   249  	d.SetReader(r)
   250  
   251  	d.Opt.Cursor.On = true
   252  
   253  	c := 17
   254  	d.SetRuneOffset(c)
   255  	d.SetCursorOffset(c)
   256  
   257  	p := d.LocalPointOf(c)
   258  	p.Y -= d.LineHeight() - 1
   259  	k := d.LocalIndexOf(p)
   260  
   261  	d.SetRuneOffset(k)
   262  	d.SetCursorOffset(k)
   263  
   264  	d.Draw(img)
   265  	cmpResult(t, img, "img12")
   266  }
   267  
   268  func TestImg13Cursor(t *testing.T) {
   269  	d, img := newTestDrawer()
   270  
   271  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   272  	r := iorw.NewStringReaderAt(s)
   273  	d.SetReader(r)
   274  
   275  	d.Opt.Cursor.On = true
   276  
   277  	c := r.Max()
   278  	d.SetRuneOffset(c - 3)
   279  	d.SetCursorOffset(c)
   280  
   281  	// range visible when offset was eof was causing draw at bottom
   282  	u := d.RangeVisibleOffset(c, 1)
   283  	d.SetRuneOffset(u)
   284  
   285  	d.Draw(img)
   286  	cmpResult(t, img, "img13")
   287  }
   288  
   289  func TestImg14Cursor(t *testing.T) {
   290  	d, img := newTestDrawer()
   291  
   292  	s := "11111\n22222\n33333\n44444\n55555\n66666\n77777\n88888"
   293  	rw := iorw.NewBytesReadWriterAt([]byte(s))
   294  	d.SetReader(rw)
   295  
   296  	d.Opt.Cursor.On = true
   297  
   298  	c := rw.Max()
   299  	d.SetRuneOffset(c)
   300  
   301  	l := 8
   302  	rw.OverwriteAt(rw.Max()-l, l, nil)
   303  
   304  	d.Draw(img)
   305  	cmpResult(t, img, "img14")
   306  }
   307  
   308  func TestImg15Visible(t *testing.T) {
   309  	d, img := newTestDrawer()
   310  
   311  	s := "11111\n22222\n33333"
   312  	rw := iorw.NewBytesReadWriterAt([]byte(s))
   313  	d.SetReader(rw)
   314  
   315  	d.Opt.Cursor.On = true
   316  
   317  	c := rw.Max()
   318  	d.SetRuneOffset(c)
   319  
   320  	rw.OverwriteAt(rw.Min(), rw.Max()-rw.Min(), nil)
   321  	b, _ := rw.ReadFastAt(rw.Min(), rw.Max()-rw.Min())
   322  	_ = string(b)
   323  
   324  	o := d.RangeVisibleOffset(0, 0)
   325  	d.SetRuneOffset(o)
   326  
   327  	rw.OverwriteAt(rw.Min(), 0, []byte("44444\n"))
   328  
   329  	d.Draw(img)
   330  	cmpResult(t, img, "img15")
   331  }
   332  
   333  func TestImg16Select(t *testing.T) {
   334  	rect := image.Rect(0, 0, 100, 100)
   335  	d, img := newTestDrawerRect(rect)
   336  
   337  	tmp := limitedReaderPadding
   338  	defer func() { limitedReaderPadding = tmp }()
   339  	limitedReaderPadding = 3
   340  
   341  	s := ""
   342  	for i := 0; i < 10; i++ {
   343  		s += fmt.Sprintf("%v", i%10)
   344  	}
   345  
   346  	r := iorw.NewStringReaderAt(s)
   347  	d.SetReader(r)
   348  
   349  	d.Opt.Cursor.On = true
   350  
   351  	d.SetRuneOffset(7)
   352  	d.SetCursorOffset(7)
   353  
   354  	d.Draw(img)
   355  	cmpResult(t, img, "img16")
   356  }
   357  
   358  func TestImg17Tab(t *testing.T) {
   359  	d, img := newTestDrawer()
   360  
   361  	s := "012\t456\t89"
   362  
   363  	r := iorw.NewStringReaderAt(s)
   364  	d.SetReader(r)
   365  
   366  	//d.SetRuneOffset(0)
   367  	d.SetRuneOffset(7)
   368  
   369  	// problem: prints 8th forward on the same line (y), but the image shows runes on another line
   370  	//for i := 5; i <= 9; i++ {
   371  	//	p := d.LocalPointOf(i)
   372  	//	fmt.Printf("%v: %v\n", i, p)
   373  	//}
   374  
   375  	d.Draw(img)
   376  	cmpResult(t, img, "img17")
   377  }
   378  
   379  func TestImg18LongWrap(t *testing.T) {
   380  	d, img := newTestDrawer()
   381  
   382  	s := ""
   383  	for i := 0; i < 10000; i++ {
   384  		s += fmt.Sprintf("%010d;", i)
   385  	}
   386  
   387  	r := iorw.NewStringReaderAt(s)
   388  	d.SetReader(r)
   389  
   390  	d.SetRuneOffset(len(s) / 2)
   391  
   392  	d.Draw(img)
   393  	cmpResult(t, img, "img18")
   394  }
   395  
   396  //----------
   397  
   398  func newTestDrawer() (*Drawer, draw.Image) {
   399  	rect := image.Rect(0, 0, 70, 70)
   400  	return newTestDrawerRect(rect)
   401  }
   402  
   403  func newTestDrawerRect(rect image.Rectangle) (*Drawer, draw.Image) {
   404  	face := newTestFace()
   405  	d := New()
   406  	d.SetFontFace(face)
   407  	d.SetBounds(rect)
   408  	d.SetFg(color.Black)
   409  
   410  	d.smoothScroll = false
   411  	d.Opt.LineWrap.Bg = colornames.Red
   412  
   413  	NoPaddedIndentedLines = true
   414  
   415  	img := image.NewRGBA(rect)
   416  	return d, img
   417  }
   418  
   419  func newTestFace() *fontutil.FontFace {
   420  	f := fontutil.DefaultFont()
   421  	opt := truetype.Options{DPI: 100}
   422  	return f.FontFace(opt)
   423  
   424  }
   425  
   426  var testImg0Dir = "testimgs"
   427  
   428  func imgFilename(name string) string {
   429  	return filepath.Join(testImg0Dir, name+".png")
   430  }
   431  
   432  func cmpResult(t *testing.T, img image.Image, name string) {
   433  	t.Helper()
   434  
   435  	// auto save if file doesn't exit
   436  	fname := imgFilename(name)
   437  	if _, err := os.Stat(fname); os.IsNotExist(err) {
   438  		saveResult(img, name)
   439  		return
   440  	}
   441  
   442  	compareResult(t, img, name)
   443  }
   444  
   445  func saveResult(img image.Image, name string) {
   446  	fname := filepath.Join(testImg0Dir, name+".png")
   447  	f, err := os.Create(fname)
   448  	if err != nil {
   449  		panic(err)
   450  	}
   451  	defer f.Close()
   452  	if err := png.Encode(f, img); err != nil {
   453  		panic(err)
   454  	}
   455  }
   456  
   457  func openResult(name string) image.Image {
   458  	fname := filepath.Join(testImg0Dir, name+".png")
   459  	f, err := os.Open(fname)
   460  	if err != nil {
   461  		panic(err)
   462  	}
   463  	defer f.Close()
   464  	img, err := png.Decode(f)
   465  	if err != nil {
   466  		panic(err)
   467  	}
   468  	return img
   469  }
   470  
   471  func compareResult(t *testing.T, img image.Image, name string) {
   472  	t.Helper()
   473  	img2 := openResult(name)
   474  	if img.Bounds() != img2.Bounds() {
   475  		saveResult(img, name+"_err")
   476  		t.Fatal("different bounds")
   477  	}
   478  	b := img.Bounds()
   479  	for y := b.Min.Y; y < b.Max.Y; y++ {
   480  		for x := b.Min.X; x < b.Max.X; x++ {
   481  			c := color.RGBAModel.Convert(img.At(x, y))
   482  			c2 := color.RGBAModel.Convert(img2.At(x, y))
   483  			if c != c2 {
   484  				saveResult(img, name+"_err")
   485  				t.Fatalf("different color value: %vx%v: %v %v", x, y, c, c2)
   486  			}
   487  		}
   488  	}
   489  }