// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package draw

import (
	"image"
	"image/color"
	"reflect"
	"testing"
)

const (
	dstw, dsth = 640, 480
	srcw, srch = 400, 300
)

var palette = color.Palette{
	color.Black,
	color.White,
}

// bench benchmarks drawing src and mask images onto a dst image with the
// given op and the color models to create those images from.
// The created images' pixels are initialized to non-zero values.
func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
	b.StopTimer()

	var dst Image
	switch dcm {
	case color.RGBAModel:
		dst1 := image.NewRGBA(image.Rect(0, 0, dstw, dsth))
		for y := 0; y < dsth; y++ {
			for x := 0; x < dstw; x++ {
				dst1.SetRGBA(x, y, color.RGBA{
					uint8(5 * x % 0x100),
					uint8(7 * y % 0x100),
					uint8((7*x + 5*y) % 0x100),
					0xff,
				})
			}
		}
		dst = dst1
	case color.RGBA64Model:
		dst1 := image.NewRGBA64(image.Rect(0, 0, dstw, dsth))
		for y := 0; y < dsth; y++ {
			for x := 0; x < dstw; x++ {
				dst1.SetRGBA64(x, y, color.RGBA64{
					uint16(53 * x % 0x10000),
					uint16(59 * y % 0x10000),
					uint16((59*x + 53*y) % 0x10000),
					0xffff,
				})
			}
		}
		dst = dst1
	default:
		// The == operator isn't defined on a color.Palette (a slice), so we
		// use reflection.
		if reflect.DeepEqual(dcm, palette) {
			dst1 := image.NewPaletted(image.Rect(0, 0, dstw, dsth), palette)
			for y := 0; y < dsth; y++ {
				for x := 0; x < dstw; x++ {
					dst1.SetColorIndex(x, y, uint8(x^y)&1)
				}
			}
			dst = dst1
		} else {
			b.Fatal("unknown destination color model", dcm)
		}
	}

	var src image.Image
	switch scm {
	case nil:
		src = &image.Uniform{C: color.RGBA{0x11, 0x22, 0x33, 0x44}}
	case color.CMYKModel:
		src1 := image.NewCMYK(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetCMYK(x, y, color.CMYK{
					uint8(13 * x % 0x100),
					uint8(11 * y % 0x100),
					uint8((11*x + 13*y) % 0x100),
					uint8((31*x + 37*y) % 0x100),
				})
			}
		}
		src = src1
	case color.GrayModel:
		src1 := image.NewGray(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetGray(x, y, color.Gray{
					uint8((11*x + 13*y) % 0x100),
				})
			}
		}
		src = src1
	case color.RGBAModel:
		src1 := image.NewRGBA(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetRGBA(x, y, color.RGBA{
					uint8(13 * x % 0x80),
					uint8(11 * y % 0x80),
					uint8((11*x + 13*y) % 0x80),
					0x7f,
				})
			}
		}
		src = src1
	case color.RGBA64Model:
		src1 := image.NewRGBA64(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetRGBA64(x, y, color.RGBA64{
					uint16(103 * x % 0x8000),
					uint16(101 * y % 0x8000),
					uint16((101*x + 103*y) % 0x8000),
					0x7fff,
				})
			}
		}
		src = src1
	case color.NRGBAModel:
		src1 := image.NewNRGBA(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				src1.SetNRGBA(x, y, color.NRGBA{
					uint8(13 * x % 0x100),
					uint8(11 * y % 0x100),
					uint8((11*x + 13*y) % 0x100),
					0x7f,
				})
			}
		}
		src = src1
	case color.YCbCrModel:
		yy := make([]uint8, srcw*srch)
		cb := make([]uint8, srcw*srch)
		cr := make([]uint8, srcw*srch)
		for i := range yy {
			yy[i] = uint8(3 * i % 0x100)
			cb[i] = uint8(5 * i % 0x100)
			cr[i] = uint8(7 * i % 0x100)
		}
		src = &image.YCbCr{
			Y:              yy,
			Cb:             cb,
			Cr:             cr,
			YStride:        srcw,
			CStride:        srcw,
			SubsampleRatio: image.YCbCrSubsampleRatio444,
			Rect:           image.Rect(0, 0, srcw, srch),
		}
	default:
		b.Fatal("unknown source color model", scm)
	}

	var mask image.Image
	switch mcm {
	case nil:
		// No-op.
	case color.AlphaModel:
		mask1 := image.NewAlpha(image.Rect(0, 0, srcw, srch))
		for y := 0; y < srch; y++ {
			for x := 0; x < srcw; x++ {
				a := uint8((23*x + 29*y) % 0x100)
				// Glyph masks are typically mostly zero,
				// so we only set a quarter of mask1's pixels.
				if a >= 0xc0 {
					mask1.SetAlpha(x, y, color.Alpha{a})
				}
			}
		}
		mask = mask1
	default:
		b.Fatal("unknown mask color model", mcm)
	}

	b.StartTimer()
	for i := 0; i < b.N; i++ {
		// Scatter the destination rectangle to draw into.
		x := 3 * i % (dstw - srcw)
		y := 7 * i % (dsth - srch)

		DrawMask(dst, dst.Bounds().Add(image.Pt(x, y)), src, image.ZP, mask, image.ZP, op)
	}
}

// The BenchmarkFoo functions exercise a drawFoo fast-path function in draw.go.

func BenchmarkFillOver(b *testing.B) {
	bench(b, color.RGBAModel, nil, nil, Over)
}

func BenchmarkFillSrc(b *testing.B) {
	bench(b, color.RGBAModel, nil, nil, Src)
}

func BenchmarkCopyOver(b *testing.B) {
	bench(b, color.RGBAModel, color.RGBAModel, nil, Over)
}

func BenchmarkCopySrc(b *testing.B) {
	bench(b, color.RGBAModel, color.RGBAModel, nil, Src)
}

func BenchmarkNRGBAOver(b *testing.B) {
	bench(b, color.RGBAModel, color.NRGBAModel, nil, Over)
}

func BenchmarkNRGBASrc(b *testing.B) {
	bench(b, color.RGBAModel, color.NRGBAModel, nil, Src)
}

func BenchmarkYCbCr(b *testing.B) {
	bench(b, color.RGBAModel, color.YCbCrModel, nil, Over)
}

func BenchmarkGray(b *testing.B) {
	bench(b, color.RGBAModel, color.GrayModel, nil, Over)
}

func BenchmarkCMYK(b *testing.B) {
	bench(b, color.RGBAModel, color.CMYKModel, nil, Over)
}

func BenchmarkGlyphOver(b *testing.B) {
	bench(b, color.RGBAModel, nil, color.AlphaModel, Over)
}

func BenchmarkRGBA(b *testing.B) {
	bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
}

func BenchmarkPalettedFill(b *testing.B) {
	bench(b, palette, nil, nil, Src)
}

func BenchmarkPalettedRGBA(b *testing.B) {
	bench(b, palette, color.RGBAModel, nil, Src)
}

// The BenchmarkGenericFoo functions exercise the generic, slow-path code.

func BenchmarkGenericOver(b *testing.B) {
	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Over)
}

func BenchmarkGenericMaskOver(b *testing.B) {
	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Over)
}

func BenchmarkGenericSrc(b *testing.B) {
	bench(b, color.RGBA64Model, color.RGBA64Model, nil, Src)
}

func BenchmarkGenericMaskSrc(b *testing.B) {
	bench(b, color.RGBA64Model, color.RGBA64Model, color.AlphaModel, Src)
}
