// blendRGBA returns the interpolation between two sRGB colors with
// pre-multiplied alpha.
164266
func blendRGBA(a, b color.RGBA, x float64) color.RGBA {
	const linThresh = 5
	diff8 := func(a, b uint8) uint8 {
		if a < b {
			return b - a
		}
		return a - b
	}
	if a.A == 255 && b.A == 255 && diff8(a.R, b.R) <= linThresh && diff8(a.G, b.G) <= linThresh && diff8(a.B, b.B) <= linThresh {
		// Perform a quick linear interpolation.
		blend8 := func(a, b uint8, x float64) uint8 {
			c := float64(a)*(1-x) + float64(b)*x
			if c <= 0 {
				return 0
			} else if c >= 255 {
				return 255
			}
			return uint8(c)
		}
		return color.RGBA{
			blend8(a.R, b.R, x),
			blend8(a.G, b.G, x),
			blend8(a.B, b.B, x),
			255,
		}
	}

	blend := func(a, b uint8, x float64, lim uint8) uint8 {
		// Map to linear RGB, blend in linear RGB, and map
		// back to sRGB.
		al, bl := sRGB8ToLinear(a), sRGB8ToLinear(b)
		cl := float64(al)*(1-x) + float64(bl)*x
		if cl < 0 {
			return 0
		} else if cl >= 1<<16-1 {
			return 255
		}
		out := linearTosRGB8(uint16(cl))
		if out > lim {
			out = lim
		}
		return out
	}
	linear := func(a, b uint8, x float64) uint8 {
		c := int(float64(a)*(1-x) + float64(b)*x)
		if c <= 0 {
			return 0
		} else if c >= 255 {
			return 255
		}
		return uint8(c)
	}

	if a.A == b.A {
		// No need to undo the alpha pre-multiplication.
		return color.RGBA{
			blend(a.R, b.R, x, a.A),
			blend(a.G, b.G, x, a.A),
			blend(a.B, b.B, x, a.A),
			a.A,
		}
	}

	// Un-premultiply the alpha, map to linear RGB, blend in
	// linear RGB, map back to sRGB, and re-premultiply the alpha.
	if a.A == 0 {
		return color.RGBA{b.R, b.G, b.B, linear(a.A, b.A, x)}
	} else if b.A == 0 {
		return color.RGBA{a.R, a.G, a.B, linear(a.A, b.A, x)}
	}
	// TODO: This loses precision. Maybe use 16 bit sRGB?
	a.R = uint8(uint16(a.R) * 255 / uint16(a.A))
	a.G = uint8(uint16(a.G) * 255 / uint16(a.A))
	a.B = uint8(uint16(a.B) * 255 / uint16(a.A))
	b.R = uint8(uint16(b.R) * 255 / uint16(b.A))
	b.G = uint8(uint16(b.G) * 255 / uint16(b.A))
	b.B = uint8(uint16(b.B) * 255 / uint16(b.A))
	c := color.RGBA{
		blend(a.R, b.R, x, 255),
		blend(a.G, b.G, x, 255),
		blend(a.B, b.B, x, 255),
		linear(a.A, b.A, x),
	}
	c.R = uint8(uint16(c.R) * uint16(c.A) / 255)
	c.G = uint8(uint16(c.G) * uint16(c.A) / 255)
	c.B = uint8(uint16(c.B) * uint16(c.A) / 255)
	return c
}
1214969
func baseShader(c *Canvas) {
	gs := &glShader{
		vf: defaultCanvasVertexFormat,
		vs: baseCanvasVertexShader,
		fs: baseCanvasFragmentShader,
	}

	gs.setUniform("uTransform", &gs.uniformDefaults.transform)
	gs.setUniform("uColorMask", &gs.uniformDefaults.colormask)
	gs.setUniform("uBounds", &gs.uniformDefaults.bounds)
	gs.setUniform("uTexBounds", &gs.uniformDefaults.texbounds)

	c.shader = gs
}
650708
func (texture *Texture) UpdateRGBA(rect *Rect, pixels []uint32, pitch int) error {
	if pixels == nil {
		return nil
	}
	return errorFromInt(int(
		C.SDL_UpdateTexture(
			texture.cptr(),
			rect.cptr(),
			unsafe.Pointer(&pixels[0]),
			C.int(4*pitch)))) // 4 bytes in one uint32
}
889571
func AsRGBA(src image.Image) *image.RGBA {
	bounds := src.Bounds()
	img := image.NewRGBA(bounds)
	draw.Draw(img, bounds, src, bounds.Min, draw.Src)
	return img
}
965427
func (self GradientTable) GetInterpolatedColorFor(t float64) colorful.Color {
	for i := 0; i < len(self)-1; i++ {
		c1 := self[i]
		c2 := self[i+1]
		if c1.Pos <= t && t <= c2.Pos {
			// We are in between c1 and c2. Go blend them!
			t := (t - c1.Pos) / (c2.Pos - c1.Pos)
			return c1.Col.BlendHcl(c2.Col, t).Clamped()
		}
	}

	// Nothing found? Means we're at (or past) the last gradient keypoint.
	return self[len(self)-1].Col
}
1326415
func blend(d, s uint8, alpha float64) uint8 {
	return uint8(float64(s)*alpha + float64(d)*(1-alpha))
}
511643
func gradient(from, to color.RGBA, scale float64) (result color.RGBA) {
	scale = math.Max(math.Min(scale, 1.0), 0.0)
	result.R = linearScale(from.R, to.R, scale)
	result.G = linearScale(from.G, to.G, scale)
	result.B = linearScale(from.B, to.B, scale)
	return
}
882070
func (col Color) LinearRgb() (r, g, b float64) {
	r = linearize(col.R)
	g = linearize(col.G)
	b = linearize(col.B)
	return
}
1327756
func (c Color) RGBA() (r, g, b, a uint32) {
	fa := float64(c.A) / 255.0
	r = uint32(float64(uint32(c.R)) * fa)
	r |= r << 8
	g = uint32(float64(uint32(c.G)) * fa)
	g |= g << 8
	b = uint32(float64(uint32(c.B)) * fa)
	b |= b << 8
	a = uint32(c.A)
	a |= a << 8
	return
}
742418
func TrueColorFromRGB(r byte, g byte, b byte) TrueColor {
	return TrueColor(((uint(r) & 0xff) << 16) | ((uint(g) & 0xff) << 8) | (uint(b) & 0xff))
}
216381
func (d *APA102Driver) SetRGBA(i int, v color.RGBA) {
	d.vals[i] = v
}
1170321
func (col Color) RGB255() (r, g, b uint8) {
	r = uint8(col.R*255.0 + 0.5)
	g = uint8(col.G*255.0 + 0.5)
	b = uint8(col.B*255.0 + 0.5)
	return
}
761566
func (builder *Builder) RGB3BitB(r, g, b uint8) *Builder {
	return builder.Color3BitB(NewRGB3Bit(r, g, b))
}
1366351
func HSVToRGB(h, s, v float64) color.RGBA {
	var i, f, p, q, t float64

	// Achromatic
	if s == 0 {
		outV := uint8(f64.Clamp(v*255+0.5, 0, 255))
		return color.RGBA{outV, outV, outV, 0xFF}
	}

	h /= 60
	i = math.Floor(h)
	f = h - i
	p = v * (1 - s)
	q = v * (1 - s*f)
	t = v * (1 - s*(1-f))

	var r, g, b float64
	switch i {
	case 0:
		r = v
		g = t
		b = p
	case 1:
		r = q
		g = v
		b = p
	case 2:
		r = p
		g = v
		b = t
	case 3:
		r = p
		g = q
		b = v
	case 4:
		r = t
		g = p
		b = v
	default:
		r = v
		g = p
		b = q
	}

	outR := uint8(f64.Clamp(r*255+0.5, 0, 255))
	outG := uint8(f64.Clamp(g*255+0.5, 0, 255))
	outB := uint8(f64.Clamp(b*255+0.5, 0, 255))
	return color.RGBA{outR, outG, outB, 0xFF}
}
529931
func BezierRGBA(renderer *sdl.Renderer, vx, vy []int16, s int, r, g, b, a uint8) bool {
	_len := C.int(min(len(vx), len(vy)))
	if _len == 0 {
		return true
	}
	_vx := (*C.Sint16)(unsafe.Pointer(&vx[0]))
	_vy := (*C.Sint16)(unsafe.Pointer(&vy[0]))
	_s := C.int(s)
	_r := C.Uint8(r)
	_g := C.Uint8(g)
	_b := C.Uint8(b)
	_a := C.Uint8(a)
	return C.bezierRGBA((*C.SDL_Renderer)(unsafe.Pointer(renderer)), _vx, _vy, _len, _s, _r, _g, _b, _a) == 0
}
949015
func (col Color) RGBA() (r, g, b, a uint32) {
	r = uint32(col.R*65535.0 + 0.5)
	g = uint32(col.G*65535.0 + 0.5)
	b = uint32(col.B*65535.0 + 0.5)
	a = 0xFFFF
	return
}
1132107
func blend(bg image.Image, fg image.Image, fn func(fcolor.RGBAF64, fcolor.RGBAF64) fcolor.RGBAF64) *image.RGBA {
	bgBounds := bg.Bounds()
	fgBounds := fg.Bounds()

	var w, h int
	if bgBounds.Dx() < fgBounds.Dx() {
		w = bgBounds.Dx()
	} else {
		w = fgBounds.Dx()
	}
	if bgBounds.Dy() < fgBounds.Dy() {
		h = bgBounds.Dy()
	} else {
		h = fgBounds.Dy()
	}

	bgSrc := clone.AsRGBA(bg)
	fgSrc := clone.AsRGBA(fg)
	dst := image.NewRGBA(image.Rect(0, 0, w, h))

	parallel.Line(h, func(start, end int) {
		for y := start; y < end; y++ {
			for x := 0; x < w; x++ {
				bgPos := y*bgSrc.Stride + x*4
				fgPos := y*fgSrc.Stride + x*4
				result := fn(
					fcolor.NewRGBAF64(bgSrc.Pix[bgPos+0], bgSrc.Pix[bgPos+1], bgSrc.Pix[bgPos+2], bgSrc.Pix[bgPos+3]),
					fcolor.NewRGBAF64(fgSrc.Pix[fgPos+0], fgSrc.Pix[fgPos+1], fgSrc.Pix[fgPos+2], fgSrc.Pix[fgPos+3]))

				result.Clamp()
				dstPos := y*dst.Stride + x*4
				dst.Pix[dstPos+0] = uint8(result.R * 255)
				dst.Pix[dstPos+1] = uint8(result.G * 255)
				dst.Pix[dstPos+2] = uint8(result.B * 255)
				dst.Pix[dstPos+3] = uint8(result.A * 255)
			}

		}
	})

	return dst
}