Diff
diff --git a/gg/gradient.go b/gg/gradient.go
deleted file mode 100644
index 9bbdbf3..0000000
--- a/gg/gradient.go
+++ /dev/null
@@ -1,248 +0,0 @@
-package gg
-
-import (
- "image/color"
- "math"
- "sort"
-)
-
-type stop struct {
- pos float64
- color color.Color
-}
-
-type stops []stop
-
-// Len satisfies the Sort interface.
-func (s stops) Len() int {
- return len(s)
-}
-
-// Less satisfies the Sort interface.
-func (s stops) Less(i, j int) bool {
- return s[i].pos < s[j].pos
-}
-
-// Swap satisfies the Sort interface.
-func (s stops) Swap(i, j int) {
- s[i], s[j] = s[j], s[i]
-}
-
-type Gradient interface {
- Pattern
- AddColorStop(offset float64, color color.Color)
-}
-
-// Linear Gradient
-type linearGradient struct {
- x0, y0, x1, y1 float64
- stops stops
-}
-
-func (g *linearGradient) ColorAt(x, y int) color.Color {
- if len(g.stops) == 0 {
- return color.Transparent
- }
-
- fx, fy := float64(x), float64(y)
- x0, y0, x1, y1 := g.x0, g.y0, g.x1, g.y1
- dx, dy := x1-x0, y1-y0
-
- // Horizontal
- if dy == 0 && dx != 0 {
- return getColor((fx-x0)/dx, g.stops)
- }
-
- // Vertical
- if dx == 0 && dy != 0 {
- return getColor((fy-y0)/dy, g.stops)
- }
-
- // Dot product
- s0 := dx*(fx-x0) + dy*(fy-y0)
- if s0 < 0 {
- return g.stops[0].color
- }
- // Calculate distance to (x0,y0) alone (x0,y0)->(x1,y1)
- mag := math.Hypot(dx, dy)
- u := ((fx-x0)*-dy + (fy-y0)*dx) / (mag * mag)
- x2, y2 := x0+u*-dy, y0+u*dx
- d := math.Hypot(fx-x2, fy-y2) / mag
- return getColor(d, g.stops)
-}
-
-func (g *linearGradient) AddColorStop(offset float64, color color.Color) {
- g.stops = append(g.stops, stop{pos: offset, color: color})
- sort.Sort(g.stops)
-}
-
-func NewLinearGradient(x0, y0, x1, y1 float64) Gradient {
- g := &linearGradient{
- x0: x0, y0: y0,
- x1: x1, y1: y1,
- }
- return g
-}
-
-// Radial Gradient
-type circle struct {
- x, y, r float64
-}
-
-type radialGradient struct {
- c0, c1, cd circle
- a, inva float64
- mindr float64
- stops stops
-}
-
-func dot3(x0, y0, z0, x1, y1, z1 float64) float64 {
- return x0*x1 + y0*y1 + z0*z1
-}
-
-func (g *radialGradient) ColorAt(x, y int) color.Color {
- if len(g.stops) == 0 {
- return color.Transparent
- }
-
- // copy from pixman's pixman-radial-gradient.c
-
- dx, dy := float64(x)+0.5-g.c0.x, float64(y)+0.5-g.c0.y
- b := dot3(dx, dy, g.c0.r, g.cd.x, g.cd.y, g.cd.r)
- c := dot3(dx, dy, -g.c0.r, dx, dy, g.c0.r)
-
- if g.a == 0 {
- if b == 0 {
- return color.Transparent
- }
- t := 0.5 * c / b
- if t*g.cd.r >= g.mindr {
- return getColor(t, g.stops)
- }
- return color.Transparent
- }
-
- discr := dot3(b, g.a, 0, b, -c, 0)
- if discr >= 0 {
- sqrtdiscr := math.Sqrt(discr)
- t0 := (b + sqrtdiscr) * g.inva
- t1 := (b - sqrtdiscr) * g.inva
-
- if t0*g.cd.r >= g.mindr {
- return getColor(t0, g.stops)
- } else if t1*g.cd.r >= g.mindr {
- return getColor(t1, g.stops)
- }
- }
-
- return color.Transparent
-}
-
-func (g *radialGradient) AddColorStop(offset float64, color color.Color) {
- g.stops = append(g.stops, stop{pos: offset, color: color})
- sort.Sort(g.stops)
-}
-
-func NewRadialGradient(x0, y0, r0, x1, y1, r1 float64) Gradient {
- c0 := circle{x0, y0, r0}
- c1 := circle{x1, y1, r1}
- cd := circle{x1 - x0, y1 - y0, r1 - r0}
- a := dot3(cd.x, cd.y, -cd.r, cd.x, cd.y, cd.r)
- var inva float64
- if a != 0 {
- inva = 1.0 / a
- }
- mindr := -c0.r
- g := &radialGradient{
- c0: c0,
- c1: c1,
- cd: cd,
- a: a,
- inva: inva,
- mindr: mindr,
- }
- return g
-}
-
-// Conic Gradient
-type conicGradient struct {
- cx, cy float64
- rotation float64
- stops stops
-}
-
-func (g *conicGradient) ColorAt(x, y int) color.Color {
- if len(g.stops) == 0 {
- return color.Transparent
- }
- a := math.Atan2(float64(y)-g.cy, float64(x)-g.cx)
- t := norm(a, -math.Pi, math.Pi) - g.rotation
- if t < 0 {
- t += 1
- }
- return getColor(t, g.stops)
-}
-
-func (g *conicGradient) AddColorStop(offset float64, color color.Color) {
- g.stops = append(g.stops, stop{pos: offset, color: color})
- sort.Sort(g.stops)
-}
-
-func NewConicGradient(cx, cy, deg float64) Gradient {
- g := &conicGradient{
- cx: cx,
- cy: cy,
- rotation: normalizeAngle(deg) / 360,
- }
- return g
-}
-
-func normalizeAngle(t float64) float64 {
- t = math.Mod(t, 360)
- if t < 0 {
- t += 360
- }
- return t
-}
-
-// Map value which is in range [a..b] to range [0..1]
-func norm(value, a, b float64) float64 {
- return (value - a) * (1.0 / (b - a))
-}
-
-func getColor(pos float64, stops stops) color.Color {
- if pos <= 0.0 || len(stops) == 1 {
- return stops[0].color
- }
-
- last := stops[len(stops)-1]
-
- if pos >= last.pos {
- return last.color
- }
-
- for i, stop := range stops[1:] {
- if pos < stop.pos {
- pos = (pos - stops[i].pos) / (stop.pos - stops[i].pos)
- return colorLerp(stops[i].color, stop.color, pos)
- }
- }
-
- return last.color
-}
-
-func colorLerp(c0, c1 color.Color, t float64) color.Color {
- r0, g0, b0, a0 := c0.RGBA()
- r1, g1, b1, a1 := c1.RGBA()
-
- return color.RGBA{
- lerp(r0, r1, t),
- lerp(g0, g1, t),
- lerp(b0, b1, t),
- lerp(a0, a1, t),
- }
-}
-
-func lerp(a, b uint32, t float64) uint8 {
- return uint8(int32(float64(a)*(1.0-t)+float64(b)*t) >> 8)
-}