...

Source file src/golang.org/x/image/vector/vector_test.go

Documentation: golang.org/x/image/vector

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package vector
     6  
     7  // TODO: add tests for NaN and Inf coordinates.
     8  
     9  import (
    10  	"fmt"
    11  	"image"
    12  	"image/color"
    13  	"image/draw"
    14  	"image/png"
    15  	"math"
    16  	"math/rand"
    17  	"os"
    18  	"path/filepath"
    19  	"testing"
    20  )
    21  
    22  // encodePNG is useful for manually debugging the tests.
    23  func encodePNG(dstFilename string, src image.Image) error {
    24  	f, err := os.Create(dstFilename)
    25  	if err != nil {
    26  		return err
    27  	}
    28  	encErr := png.Encode(f, src)
    29  	closeErr := f.Close()
    30  	if encErr != nil {
    31  		return encErr
    32  	}
    33  	return closeErr
    34  }
    35  
    36  func pointOnCircle(center, radius, index, number int) (x, y float32) {
    37  	c := float64(center)
    38  	r := float64(radius)
    39  	i := float64(index)
    40  	n := float64(number)
    41  	return float32(c + r*(math.Cos(2*math.Pi*i/n))),
    42  		float32(c + r*(math.Sin(2*math.Pi*i/n)))
    43  }
    44  
    45  func TestRasterizeOutOfBounds(t *testing.T) {
    46  	// Set this to a non-empty string such as "/tmp" to manually inspect the
    47  	// rasterization.
    48  	//
    49  	// If empty, this test simply checks that calling LineTo with points out of
    50  	// the rasterizer's bounds doesn't panic.
    51  	const tmpDir = ""
    52  
    53  	const center, radius, n = 16, 20, 16
    54  	var z Rasterizer
    55  	for i := 0; i < n; i++ {
    56  		for j := 1; j < n/2; j++ {
    57  			z.Reset(2*center, 2*center)
    58  			z.MoveTo(1*center, 1*center)
    59  			z.LineTo(pointOnCircle(center, radius, i+0, n))
    60  			z.LineTo(pointOnCircle(center, radius, i+j, n))
    61  			z.ClosePath()
    62  
    63  			z.MoveTo(0*center, 0*center)
    64  			z.LineTo(0*center, 2*center)
    65  			z.LineTo(2*center, 2*center)
    66  			z.LineTo(2*center, 0*center)
    67  			z.ClosePath()
    68  
    69  			dst := image.NewAlpha(z.Bounds())
    70  			z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
    71  
    72  			if tmpDir == "" {
    73  				continue
    74  			}
    75  
    76  			filename := filepath.Join(tmpDir, fmt.Sprintf("out-%02d-%02d.png", i, j))
    77  			if err := encodePNG(filename, dst); err != nil {
    78  				t.Error(err)
    79  			}
    80  			t.Logf("wrote %s", filename)
    81  		}
    82  	}
    83  }
    84  
    85  func TestRasterizePolygon(t *testing.T) {
    86  	var z Rasterizer
    87  	for radius := 4; radius <= 256; radius *= 2 {
    88  		for n := 3; n <= 19; n += 4 {
    89  			z.Reset(2*radius, 2*radius)
    90  			z.MoveTo(float32(2*radius), float32(1*radius))
    91  			for i := 1; i < n; i++ {
    92  				z.LineTo(pointOnCircle(radius, radius, i, n))
    93  			}
    94  			z.ClosePath()
    95  
    96  			dst := image.NewAlpha(z.Bounds())
    97  			z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
    98  
    99  			if err := checkCornersCenter(dst); err != nil {
   100  				t.Errorf("radius=%d, n=%d: %v", radius, n, err)
   101  			}
   102  		}
   103  	}
   104  }
   105  
   106  func TestRasterizeAlmostAxisAligned(t *testing.T) {
   107  	z := NewRasterizer(8, 8)
   108  	z.MoveTo(2, 2)
   109  	z.LineTo(6, math.Nextafter32(2, 0))
   110  	z.LineTo(6, 6)
   111  	z.LineTo(math.Nextafter32(2, 0), 6)
   112  	z.ClosePath()
   113  
   114  	dst := image.NewAlpha(z.Bounds())
   115  	z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
   116  
   117  	if err := checkCornersCenter(dst); err != nil {
   118  		t.Error(err)
   119  	}
   120  }
   121  
   122  func TestRasterizeWideAlmostHorizontalLines(t *testing.T) {
   123  	var z Rasterizer
   124  	for i := uint(3); i < 16; i++ {
   125  		x := float32(int(1 << i))
   126  
   127  		z.Reset(8, 8)
   128  		z.MoveTo(-x, 3)
   129  		z.LineTo(+x, 4)
   130  		z.LineTo(+x, 6)
   131  		z.LineTo(-x, 6)
   132  		z.ClosePath()
   133  
   134  		dst := image.NewAlpha(z.Bounds())
   135  		z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
   136  
   137  		if err := checkCornersCenter(dst); err != nil {
   138  			t.Errorf("i=%d: %v", i, err)
   139  		}
   140  	}
   141  }
   142  
   143  func TestRasterize30Degrees(t *testing.T) {
   144  	z := NewRasterizer(8, 8)
   145  	z.MoveTo(4, 4)
   146  	z.LineTo(8, 4)
   147  	z.LineTo(4, 6)
   148  	z.ClosePath()
   149  
   150  	dst := image.NewAlpha(z.Bounds())
   151  	z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
   152  
   153  	if err := checkCornersCenter(dst); err != nil {
   154  		t.Error(err)
   155  	}
   156  }
   157  
   158  func TestRasterizeRandomLineTos(t *testing.T) {
   159  	var z Rasterizer
   160  	for i := 5; i < 50; i++ {
   161  		n, rng := 0, rand.New(rand.NewSource(int64(i)))
   162  
   163  		z.Reset(i+2, i+2)
   164  		z.MoveTo(float32(i/2), float32(i/2))
   165  		for ; rng.Intn(16) != 0; n++ {
   166  			x := 1 + rng.Intn(i)
   167  			y := 1 + rng.Intn(i)
   168  			z.LineTo(float32(x), float32(y))
   169  		}
   170  		z.ClosePath()
   171  
   172  		dst := image.NewAlpha(z.Bounds())
   173  		z.Draw(dst, dst.Bounds(), image.Opaque, image.Point{})
   174  
   175  		if err := checkCorners(dst); err != nil {
   176  			t.Errorf("i=%d (%d nodes): %v", i, n, err)
   177  		}
   178  	}
   179  }
   180  
   181  // checkCornersCenter checks that the corners of the image are all 0x00 and the
   182  // center is 0xff.
   183  func checkCornersCenter(m *image.Alpha) error {
   184  	if err := checkCorners(m); err != nil {
   185  		return err
   186  	}
   187  	size := m.Bounds().Size()
   188  	center := m.Pix[(size.Y/2)*m.Stride+(size.X/2)]
   189  	if center != 0xff {
   190  		return fmt.Errorf("center: got %#02x, want 0xff", center)
   191  	}
   192  	return nil
   193  }
   194  
   195  // checkCorners checks that the corners of the image are all 0x00.
   196  func checkCorners(m *image.Alpha) error {
   197  	size := m.Bounds().Size()
   198  	corners := [4]uint8{
   199  		m.Pix[(0*size.Y+0)*m.Stride+(0*size.X+0)],
   200  		m.Pix[(0*size.Y+0)*m.Stride+(1*size.X-1)],
   201  		m.Pix[(1*size.Y-1)*m.Stride+(0*size.X+0)],
   202  		m.Pix[(1*size.Y-1)*m.Stride+(1*size.X-1)],
   203  	}
   204  	if corners != [4]uint8{} {
   205  		return fmt.Errorf("corners were not all zero: %v", corners)
   206  	}
   207  	return nil
   208  }
   209  
   210  var basicMask = []byte{
   211  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   212  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   213  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xaa, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
   214  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x5f, 0x00, 0x00, 0x00, 0x00,
   215  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x24, 0x00, 0x00, 0x00,
   216  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa1, 0x00, 0x00, 0x00,
   217  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x14, 0x00, 0x00,
   218  	0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x00, 0x00,
   219  	0x00, 0x00, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0x00, 0x00,
   220  	0x00, 0x00, 0x66, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xe4, 0xff, 0xff, 0xff, 0xb6, 0x00, 0x00,
   221  	0x00, 0x00, 0x0c, 0xf2, 0xff, 0xff, 0xfe, 0x9e, 0x15, 0x00, 0x15, 0x96, 0xff, 0xce, 0x00, 0x00,
   222  	0x00, 0x00, 0x00, 0x88, 0xfc, 0xe3, 0x43, 0x00, 0x00, 0x00, 0x00, 0x06, 0xcd, 0xdc, 0x00, 0x00,
   223  	0x00, 0x00, 0x00, 0x00, 0x10, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0xde, 0x00, 0x00,
   224  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x00, 0x00,
   225  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   226  	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   227  }
   228  
   229  func testBasicPath(t *testing.T, prefix string, dst draw.Image, src image.Image, op draw.Op, want []byte) {
   230  	z := NewRasterizer(16, 16)
   231  	z.MoveTo(2, 2)
   232  	z.LineTo(8, 2)
   233  	z.QuadTo(14, 2, 14, 14)
   234  	z.CubeTo(8, 2, 5, 20, 2, 8)
   235  	z.ClosePath()
   236  
   237  	z.DrawOp = op
   238  	z.Draw(dst, z.Bounds(), src, image.Point{})
   239  
   240  	var got []byte
   241  	switch dst := dst.(type) {
   242  	case *image.Alpha:
   243  		got = dst.Pix
   244  	case *image.RGBA:
   245  		got = dst.Pix
   246  	default:
   247  		t.Errorf("%s: unrecognized dst image type %T", prefix, dst)
   248  	}
   249  
   250  	if len(got) != len(want) {
   251  		t.Errorf("%s: len(got)=%d and len(want)=%d differ", prefix, len(got), len(want))
   252  		return
   253  	}
   254  	for i := range got {
   255  		delta := int(got[i]) - int(want[i])
   256  		// The +/- 2 allows different implementations to give different
   257  		// rounding errors.
   258  		if delta < -2 || +2 < delta {
   259  			t.Errorf("%s: i=%d: got %#02x, want %#02x", prefix, i, got[i], want[i])
   260  			return
   261  		}
   262  	}
   263  }
   264  
   265  func TestBasicPathDstAlpha(t *testing.T) {
   266  	for _, background := range []uint8{0x00, 0x80} {
   267  		for _, op := range []draw.Op{draw.Over, draw.Src} {
   268  			for _, xPadding := range []int{0, 7} {
   269  				bounds := image.Rect(0, 0, 16+xPadding, 16)
   270  				dst := image.NewAlpha(bounds)
   271  				for i := range dst.Pix {
   272  					dst.Pix[i] = background
   273  				}
   274  
   275  				want := make([]byte, len(dst.Pix))
   276  				copy(want, dst.Pix)
   277  
   278  				if op == draw.Over && background == 0x80 {
   279  					for y := 0; y < 16; y++ {
   280  						for x := 0; x < 16; x++ {
   281  							ma := basicMask[16*y+x]
   282  							i := dst.PixOffset(x, y)
   283  							want[i] = 0xff - (0xff-ma)/2
   284  						}
   285  					}
   286  				} else {
   287  					for y := 0; y < 16; y++ {
   288  						for x := 0; x < 16; x++ {
   289  							ma := basicMask[16*y+x]
   290  							i := dst.PixOffset(x, y)
   291  							want[i] = ma
   292  						}
   293  					}
   294  				}
   295  
   296  				prefix := fmt.Sprintf("background=%#02x, op=%v, xPadding=%d", background, op, xPadding)
   297  				testBasicPath(t, prefix, dst, image.Opaque, op, want)
   298  			}
   299  		}
   300  	}
   301  }
   302  
   303  func TestBasicPathDstRGBA(t *testing.T) {
   304  	blue := image.NewUniform(color.RGBA{0x00, 0x00, 0xff, 0xff})
   305  
   306  	for _, op := range []draw.Op{draw.Over, draw.Src} {
   307  		for _, xPadding := range []int{0, 7} {
   308  			bounds := image.Rect(0, 0, 16+xPadding, 16)
   309  			dst := image.NewRGBA(bounds)
   310  			for y := bounds.Min.Y; y < bounds.Max.Y; y++ {
   311  				for x := bounds.Min.X; x < bounds.Max.X; x++ {
   312  					dst.SetRGBA(x, y, color.RGBA{
   313  						R: uint8(y * 0x07),
   314  						G: uint8(x * 0x05),
   315  						B: 0x00,
   316  						A: 0x80,
   317  					})
   318  				}
   319  			}
   320  
   321  			want := make([]byte, len(dst.Pix))
   322  			copy(want, dst.Pix)
   323  
   324  			if op == draw.Over {
   325  				for y := 0; y < 16; y++ {
   326  					for x := 0; x < 16; x++ {
   327  						ma := basicMask[16*y+x]
   328  						i := dst.PixOffset(x, y)
   329  						want[i+0] = uint8((uint32(0xff-ma) * uint32(y*0x07)) / 0xff)
   330  						want[i+1] = uint8((uint32(0xff-ma) * uint32(x*0x05)) / 0xff)
   331  						want[i+2] = ma
   332  						want[i+3] = ma/2 + 0x80
   333  					}
   334  				}
   335  			} else {
   336  				for y := 0; y < 16; y++ {
   337  					for x := 0; x < 16; x++ {
   338  						ma := basicMask[16*y+x]
   339  						i := dst.PixOffset(x, y)
   340  						want[i+0] = 0x00
   341  						want[i+1] = 0x00
   342  						want[i+2] = ma
   343  						want[i+3] = ma
   344  					}
   345  				}
   346  			}
   347  
   348  			prefix := fmt.Sprintf("op=%v, xPadding=%d", op, xPadding)
   349  			testBasicPath(t, prefix, dst, blue, op, want)
   350  		}
   351  	}
   352  }
   353  
   354  const (
   355  	benchmarkGlyphWidth  = 893
   356  	benchmarkGlyphHeight = 1122
   357  )
   358  
   359  type benchmarkGlyphDatum struct {
   360  	// n being 0, 1 or 2 means moveTo, lineTo or quadTo.
   361  	n  uint32
   362  	px float32
   363  	py float32
   364  	qx float32
   365  	qy float32
   366  }
   367  
   368  // benchmarkGlyphData is the 'a' glyph from the Roboto Regular font, translated
   369  // so that its top left corner is (0, 0).
   370  var benchmarkGlyphData = []benchmarkGlyphDatum{
   371  	{0, 699, 1102, 0, 0},
   372  	{2, 683, 1070, 673, 988},
   373  	{2, 544, 1122, 365, 1122},
   374  	{2, 205, 1122, 102.5, 1031.5},
   375  	{2, 0, 941, 0, 802},
   376  	{2, 0, 633, 128.5, 539.5},
   377  	{2, 257, 446, 490, 446},
   378  	{1, 670, 446, 0, 0},
   379  	{1, 670, 361, 0, 0},
   380  	{2, 670, 264, 612, 206.5},
   381  	{2, 554, 149, 441, 149},
   382  	{2, 342, 149, 275, 199},
   383  	{2, 208, 249, 208, 320},
   384  	{1, 22, 320, 0, 0},
   385  	{2, 22, 239, 79.5, 163.5},
   386  	{2, 137, 88, 235.5, 44},
   387  	{2, 334, 0, 452, 0},
   388  	{2, 639, 0, 745, 93.5},
   389  	{2, 851, 187, 855, 351},
   390  	{1, 855, 849, 0, 0},
   391  	{2, 855, 998, 893, 1086},
   392  	{1, 893, 1102, 0, 0},
   393  	{1, 699, 1102, 0, 0},
   394  	{0, 392, 961, 0, 0},
   395  	{2, 479, 961, 557, 916},
   396  	{2, 635, 871, 670, 799},
   397  	{1, 670, 577, 0, 0},
   398  	{1, 525, 577, 0, 0},
   399  	{2, 185, 577, 185, 776},
   400  	{2, 185, 863, 243, 912},
   401  	{2, 301, 961, 392, 961},
   402  }
   403  
   404  func scaledBenchmarkGlyphData(height int) (width int, data []benchmarkGlyphDatum) {
   405  	scale := float32(height) / benchmarkGlyphHeight
   406  
   407  	// Clone the benchmarkGlyphData slice and scale its coordinates.
   408  	data = append(data, benchmarkGlyphData...)
   409  	for i := range data {
   410  		data[i].px *= scale
   411  		data[i].py *= scale
   412  		data[i].qx *= scale
   413  		data[i].qy *= scale
   414  	}
   415  
   416  	return int(math.Ceil(float64(benchmarkGlyphWidth * scale))), data
   417  }
   418  
   419  // benchGlyph benchmarks rasterizing a TrueType glyph.
   420  //
   421  // Note that, compared to the github.com/google/font-go prototype, the height
   422  // here is the height of the bounding box, not the pixels per em used to scale
   423  // a glyph's vectors. A height of 64 corresponds to a ppem greater than 64.
   424  func benchGlyph(b *testing.B, colorModel byte, loose bool, height int, op draw.Op) {
   425  	width, data := scaledBenchmarkGlyphData(height)
   426  	z := NewRasterizer(width, height)
   427  
   428  	bounds := z.Bounds()
   429  	if loose {
   430  		bounds.Max.X++
   431  	}
   432  	dst, src := draw.Image(nil), image.Image(nil)
   433  	switch colorModel {
   434  	case 'A':
   435  		dst = image.NewAlpha(bounds)
   436  		src = image.Opaque
   437  	case 'N':
   438  		dst = image.NewNRGBA(bounds)
   439  		src = image.NewUniform(color.NRGBA{0x40, 0x80, 0xc0, 0xff})
   440  	case 'R':
   441  		dst = image.NewRGBA(bounds)
   442  		src = image.NewUniform(color.RGBA{0x40, 0x80, 0xc0, 0xff})
   443  	default:
   444  		b.Fatal("unsupported color model")
   445  	}
   446  	bounds = z.Bounds()
   447  
   448  	b.ResetTimer()
   449  	for i := 0; i < b.N; i++ {
   450  		z.Reset(width, height)
   451  		z.DrawOp = op
   452  		for _, d := range data {
   453  			switch d.n {
   454  			case 0:
   455  				z.MoveTo(d.px, d.py)
   456  			case 1:
   457  				z.LineTo(d.px, d.py)
   458  			case 2:
   459  				z.QuadTo(d.px, d.py, d.qx, d.qy)
   460  			}
   461  		}
   462  		z.Draw(dst, bounds, src, image.Point{})
   463  	}
   464  }
   465  
   466  // The heights 16, 32, 64, 128, 256, 1024 include numbers both above and below
   467  // the floatingPointMathThreshold constant (512).
   468  
   469  func BenchmarkGlyphAlpha16Over(b *testing.B)   { benchGlyph(b, 'A', false, 16, draw.Over) }
   470  func BenchmarkGlyphAlpha16Src(b *testing.B)    { benchGlyph(b, 'A', false, 16, draw.Src) }
   471  func BenchmarkGlyphAlpha32Over(b *testing.B)   { benchGlyph(b, 'A', false, 32, draw.Over) }
   472  func BenchmarkGlyphAlpha32Src(b *testing.B)    { benchGlyph(b, 'A', false, 32, draw.Src) }
   473  func BenchmarkGlyphAlpha64Over(b *testing.B)   { benchGlyph(b, 'A', false, 64, draw.Over) }
   474  func BenchmarkGlyphAlpha64Src(b *testing.B)    { benchGlyph(b, 'A', false, 64, draw.Src) }
   475  func BenchmarkGlyphAlpha128Over(b *testing.B)  { benchGlyph(b, 'A', false, 128, draw.Over) }
   476  func BenchmarkGlyphAlpha128Src(b *testing.B)   { benchGlyph(b, 'A', false, 128, draw.Src) }
   477  func BenchmarkGlyphAlpha256Over(b *testing.B)  { benchGlyph(b, 'A', false, 256, draw.Over) }
   478  func BenchmarkGlyphAlpha256Src(b *testing.B)   { benchGlyph(b, 'A', false, 256, draw.Src) }
   479  func BenchmarkGlyphAlpha1024Over(b *testing.B) { benchGlyph(b, 'A', false, 1024, draw.Over) }
   480  func BenchmarkGlyphAlpha1024Src(b *testing.B)  { benchGlyph(b, 'A', false, 1024, draw.Src) }
   481  
   482  func BenchmarkGlyphAlphaLoose16Over(b *testing.B)   { benchGlyph(b, 'A', true, 16, draw.Over) }
   483  func BenchmarkGlyphAlphaLoose16Src(b *testing.B)    { benchGlyph(b, 'A', true, 16, draw.Src) }
   484  func BenchmarkGlyphAlphaLoose32Over(b *testing.B)   { benchGlyph(b, 'A', true, 32, draw.Over) }
   485  func BenchmarkGlyphAlphaLoose32Src(b *testing.B)    { benchGlyph(b, 'A', true, 32, draw.Src) }
   486  func BenchmarkGlyphAlphaLoose64Over(b *testing.B)   { benchGlyph(b, 'A', true, 64, draw.Over) }
   487  func BenchmarkGlyphAlphaLoose64Src(b *testing.B)    { benchGlyph(b, 'A', true, 64, draw.Src) }
   488  func BenchmarkGlyphAlphaLoose128Over(b *testing.B)  { benchGlyph(b, 'A', true, 128, draw.Over) }
   489  func BenchmarkGlyphAlphaLoose128Src(b *testing.B)   { benchGlyph(b, 'A', true, 128, draw.Src) }
   490  func BenchmarkGlyphAlphaLoose256Over(b *testing.B)  { benchGlyph(b, 'A', true, 256, draw.Over) }
   491  func BenchmarkGlyphAlphaLoose256Src(b *testing.B)   { benchGlyph(b, 'A', true, 256, draw.Src) }
   492  func BenchmarkGlyphAlphaLoose1024Over(b *testing.B) { benchGlyph(b, 'A', true, 1024, draw.Over) }
   493  func BenchmarkGlyphAlphaLoose1024Src(b *testing.B)  { benchGlyph(b, 'A', true, 1024, draw.Src) }
   494  
   495  func BenchmarkGlyphRGBA16Over(b *testing.B)   { benchGlyph(b, 'R', false, 16, draw.Over) }
   496  func BenchmarkGlyphRGBA16Src(b *testing.B)    { benchGlyph(b, 'R', false, 16, draw.Src) }
   497  func BenchmarkGlyphRGBA32Over(b *testing.B)   { benchGlyph(b, 'R', false, 32, draw.Over) }
   498  func BenchmarkGlyphRGBA32Src(b *testing.B)    { benchGlyph(b, 'R', false, 32, draw.Src) }
   499  func BenchmarkGlyphRGBA64Over(b *testing.B)   { benchGlyph(b, 'R', false, 64, draw.Over) }
   500  func BenchmarkGlyphRGBA64Src(b *testing.B)    { benchGlyph(b, 'R', false, 64, draw.Src) }
   501  func BenchmarkGlyphRGBA128Over(b *testing.B)  { benchGlyph(b, 'R', false, 128, draw.Over) }
   502  func BenchmarkGlyphRGBA128Src(b *testing.B)   { benchGlyph(b, 'R', false, 128, draw.Src) }
   503  func BenchmarkGlyphRGBA256Over(b *testing.B)  { benchGlyph(b, 'R', false, 256, draw.Over) }
   504  func BenchmarkGlyphRGBA256Src(b *testing.B)   { benchGlyph(b, 'R', false, 256, draw.Src) }
   505  func BenchmarkGlyphRGBA1024Over(b *testing.B) { benchGlyph(b, 'R', false, 1024, draw.Over) }
   506  func BenchmarkGlyphRGBA1024Src(b *testing.B)  { benchGlyph(b, 'R', false, 1024, draw.Src) }
   507  
   508  func BenchmarkGlyphNRGBA16Over(b *testing.B)   { benchGlyph(b, 'N', false, 16, draw.Over) }
   509  func BenchmarkGlyphNRGBA16Src(b *testing.B)    { benchGlyph(b, 'N', false, 16, draw.Src) }
   510  func BenchmarkGlyphNRGBA32Over(b *testing.B)   { benchGlyph(b, 'N', false, 32, draw.Over) }
   511  func BenchmarkGlyphNRGBA32Src(b *testing.B)    { benchGlyph(b, 'N', false, 32, draw.Src) }
   512  func BenchmarkGlyphNRGBA64Over(b *testing.B)   { benchGlyph(b, 'N', false, 64, draw.Over) }
   513  func BenchmarkGlyphNRGBA64Src(b *testing.B)    { benchGlyph(b, 'N', false, 64, draw.Src) }
   514  func BenchmarkGlyphNRGBA128Over(b *testing.B)  { benchGlyph(b, 'N', false, 128, draw.Over) }
   515  func BenchmarkGlyphNRGBA128Src(b *testing.B)   { benchGlyph(b, 'N', false, 128, draw.Src) }
   516  func BenchmarkGlyphNRGBA256Over(b *testing.B)  { benchGlyph(b, 'N', false, 256, draw.Over) }
   517  func BenchmarkGlyphNRGBA256Src(b *testing.B)   { benchGlyph(b, 'N', false, 256, draw.Src) }
   518  func BenchmarkGlyphNRGBA1024Over(b *testing.B) { benchGlyph(b, 'N', false, 1024, draw.Over) }
   519  func BenchmarkGlyphNRGBA1024Src(b *testing.B)  { benchGlyph(b, 'N', false, 1024, draw.Src) }
   520  

View as plain text