103 lines
2.3 KiB
Go
103 lines
2.3 KiB
Go
//go:build ignore
|
|
|
|
// gen_icon generates a 1024x1024 source icon for the Quintodrome app.
|
|
// Run: go run desktop/scripts/gen_icon.go
|
|
package main
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
"image/png"
|
|
"os"
|
|
)
|
|
|
|
const size = 1024
|
|
const ss = 4 // supersampling factor per axis
|
|
|
|
func lerp(a, b, t float64) float64 { return a + (b-a)*t }
|
|
|
|
type rgb struct{ r, g, b float64 }
|
|
|
|
func mix(a, b rgb, t float64) rgb {
|
|
return rgb{lerp(a.r, b.r, t), lerp(a.g, b.g, t), lerp(a.b, b.b, t)}
|
|
}
|
|
|
|
var (
|
|
bgTop = rgb{58, 42, 94}
|
|
bgBottom = rgb{23, 21, 28}
|
|
circleTop = rgb{168, 85, 247}
|
|
circleBottom = rgb{124, 58, 237}
|
|
white = rgb{255, 255, 255}
|
|
)
|
|
|
|
func inTriangle(px, py, ax, ay, bx, by, cx, cy float64) bool {
|
|
sign := func(x1, y1, x2, y2, x3, y3 float64) float64 {
|
|
return (x1-x3)*(y2-y3) - (x2-x3)*(y1-y3)
|
|
}
|
|
d1 := sign(px, py, ax, ay, bx, by)
|
|
d2 := sign(px, py, bx, by, cx, cy)
|
|
d3 := sign(px, py, cx, cy, ax, ay)
|
|
neg := d1 < 0 || d2 < 0 || d3 < 0
|
|
pos := d1 > 0 || d2 > 0 || d3 > 0
|
|
return !(neg && pos)
|
|
}
|
|
|
|
func sample(x, y float64) rgb {
|
|
// background vertical gradient
|
|
c := mix(bgTop, bgBottom, y/size)
|
|
|
|
// centered circle
|
|
cx, cy, cr := float64(size)/2, float64(size)/2, float64(size)*0.31
|
|
dx, dy := x-cx, y-cy
|
|
if d := dx*dx + dy*dy; d <= cr*cr {
|
|
t := (y - (cy - cr)) / (2 * cr)
|
|
circle := mix(circleTop, circleBottom, t)
|
|
c = circle
|
|
}
|
|
|
|
// play triangle
|
|
tx := float64(size) * 0.512
|
|
ax, ay := tx-float64(size)*0.145, float64(size)*0.342
|
|
bx, by := tx-float64(size)*0.145, float64(size)*0.658
|
|
cxv, cyv := tx+float64(size)*0.165, float64(size)*0.5
|
|
if inTriangle(x, y, ax, ay, bx, by, cxv, cyv) {
|
|
c = white
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func main() {
|
|
img := image.NewRGBA(image.Rect(0, 0, size, size))
|
|
for y := 0; y < size; y++ {
|
|
for x := 0; x < size; x++ {
|
|
var acc rgb
|
|
for sy := 0; sy < ss; sy++ {
|
|
for sx := 0; sx < ss; sx++ {
|
|
fx := float64(x) + (float64(sx)+0.5)/ss
|
|
fy := float64(y) + (float64(sy)+0.5)/ss
|
|
s := sample(fx, fy)
|
|
acc.r += s.r
|
|
acc.g += s.g
|
|
acc.b += s.b
|
|
}
|
|
}
|
|
n := float64(ss * ss)
|
|
img.SetRGBA(x, y, color.RGBA{
|
|
R: uint8(acc.r / n),
|
|
G: uint8(acc.g / n),
|
|
B: uint8(acc.b / n),
|
|
A: 255,
|
|
})
|
|
}
|
|
}
|
|
|
|
f, err := os.Create(os.Args[len(os.Args)-1])
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer f.Close()
|
|
if err := png.Encode(f, img); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|