diff --git a/cmd/tins2021/background.go b/cmd/tins2021/background.go new file mode 100644 index 0000000..441ae72 --- /dev/null +++ b/cmd/tins2021/background.go @@ -0,0 +1,64 @@ +package main + +import ( + "image" + "image/color" + "image/png" + "math/rand" + "os" + + "github.com/llgcode/draw2d/draw2dimg" + "github.com/nfnt/resize" + "golang.org/x/image/draw" + "opslag.de/schobers/geom" + "opslag.de/schobers/tins2021" + "opslag.de/schobers/zntg/ui" +) + +func GenerateBackground(resources ui.Resources, path string) error { + const cubeTextureWidth = 100 + cube := resize.Resize(cubeTextureWidth, 0, tins2021.GenerateCube(tins2021.Blue), resize.Bilinear) + inverted := resize.Resize(cubeTextureWidth, 0, tins2021.GenerateHole(tins2021.Blue), resize.Bilinear) + + const twelfth = (1. / 6) * geom.Pi + centerTopSquare := geom.PtF(.5, .5*geom.Sin(twelfth)) + delta := geom.PtF(geom.Cos(twelfth), .5+centerTopSquare.Y).Mul(cubeTextureWidth).Mul(.5).ToInt().Mul(2) + + bounds := image.Rect(2560, 1440, 0, 0) + im := image.NewRGBA(bounds) + var odd bool + for y := -cubeTextureWidth; y < bounds.Max.Y; y += delta.Y { + left := -cubeTextureWidth + if odd { + left += delta.X / 2 + } + for x := left; x < bounds.Max.X; x += delta.X { + currentCube := cube + n := rand.Intn(2) + if n == 0 { + currentCube = inverted + } + draw.Copy(im, image.Pt(x, y), currentCube, image.Rect(0, 0, cubeTextureWidth, cubeTextureWidth), draw.Over, nil) + } + odd = !odd + } + + ctx := draw2dimg.NewGraphicContext(im) + font, err := parseTitleFont(resources) + if err != nil { + return err + } + + setDraw2DFont(ctx, font) + ctx.SetFontSize(224) + const text = "QBITTER" + center := draw2DCenterString(ctx, text) + ctx.SetFillColor(color.White) + ctx.FillStringAt(text, .5*float64(bounds.Dx())+center.X, .5*float64(bounds.Dy())+center.Y) + + out, err := os.Create(path) + if err != nil { + return err + } + return png.Encode(out, im) +} diff --git a/cmd/tins2021/draw2dfont.go b/cmd/tins2021/draw2dfont.go new file mode 100644 index 0000000..f50b008 --- /dev/null +++ b/cmd/tins2021/draw2dfont.go @@ -0,0 +1,47 @@ +package main + +import ( + "io/ioutil" + + "github.com/golang/freetype/truetype" + "github.com/llgcode/draw2d" + "github.com/llgcode/draw2d/draw2dimg" + "opslag.de/schobers/geom" + "opslag.de/schobers/zntg/ui" +) + +func draw2DCenterString(ctx *draw2dimg.GraphicContext, s string) geom.PointF { + left, top, right, bottom := ctx.GetStringBounds(s) + return geom.PtF(-.5*(right-left), .5*(bottom-top)) +} + +type draw2DFontCache struct{ *truetype.Font } + +func (f draw2DFontCache) Load(draw2d.FontData) (*truetype.Font, error) { return f.Font, nil } +func (draw2DFontCache) Store(draw2d.FontData, *truetype.Font) {} + +func parseTrueTypeFont(resources ui.Resources, name string) (*truetype.Font, error) { + ttf, err := resources.OpenResource(name) + if err != nil { + return nil, err + } + defer ttf.Close() + data, err := ioutil.ReadAll(ttf) + if err != nil { + return nil, err + } + return truetype.Parse(data) +} + +func parseScoreFont(resources ui.Resources) (*truetype.Font, error) { + return parseTrueTypeFont(resources, "resources/fonts/FiraMono-Regular.ttf") +} + +func parseTitleFont(resources ui.Resources) (*truetype.Font, error) { + return parseTrueTypeFont(resources, "resources/fonts/escher.ttf") +} + +func setDraw2DFont(ctx *draw2dimg.GraphicContext, font *truetype.Font) { + ctx.FontCache = draw2DFontCache{font} + // ctx.SetFont(font) // is ignored anyway +} diff --git a/cmd/tins2021/settings.go b/cmd/tins2021/settings.go index 3f077d4..f363a74 100644 --- a/cmd/tins2021/settings.go +++ b/cmd/tins2021/settings.go @@ -4,10 +4,8 @@ import ( "fmt" "image" "image/color" - "io/ioutil" "github.com/golang/freetype/truetype" - "github.com/llgcode/draw2d" "github.com/llgcode/draw2d/draw2dimg" "opslag.de/schobers/geom" "opslag.de/schobers/tins2021" @@ -53,21 +51,15 @@ func drawKey(ctx *draw2dimg.GraphicContext, font *truetype.Font, center geom.Poi ctx.Close() ctx.Stroke() - ctx.FontCache = fontCache{font} - ctx.SetFont(font) + setDraw2DFont(ctx, font) ctx.SetFontSize(keyHeight_5) text := fmt.Sprintf("%c", key) - textLeft, textTop, textRight, textBottom := ctx.GetStringBounds(text) - textX, textY := skewed(-.5*(textRight-textLeft), .5*(textBottom-textTop)) + textCenter := draw2DCenterString(ctx, text) + textX, textY := skewed(textCenter.X, textCenter.Y) ctx.FillStringAt(text, textX, textY) } -type fontCache struct{ *truetype.Font } - -func (f fontCache) Load(draw2d.FontData) (*truetype.Font, error) { return f.Font, nil } -func (fontCache) Store(draw2d.FontData, *truetype.Font) {} - func generateArrowKeys(resources ui.Resources) image.Image { return generateKeys(resources, keyboardLayoutKey{Position: geom.PtF(.53, .25), Key: '↑'}, @@ -106,7 +98,7 @@ func generateKeys(resources ui.Resources, keys ...keyboardLayoutKey) image.Image im := image.NewRGBA(image.Rect(0, 0, keyboardLayoutTextureWidth, keyboardLayoutTextureHeight)) ctx := draw2dimg.NewGraphicContext(im) - font, err := parseFont(resources) + font, err := parseScoreFont(resources) if err != nil { panic(err) } @@ -138,19 +130,6 @@ type keyboardLayoutKey struct { Highlight bool } -func parseFont(resources ui.Resources) (*truetype.Font, error) { - ttf, err := resources.OpenResource("resources/fonts/FiraMono-Regular.ttf") - if err != nil { - return nil, err - } - defer ttf.Close() - data, err := ioutil.ReadAll(ttf) - if err != nil { - return nil, err - } - return truetype.Parse(data) -} - type settings struct { ui.StackPanel diff --git a/cmd/tins2021/tins2021.go b/cmd/tins2021/tins2021.go index 681996c..915a4ae 100644 --- a/cmd/tins2021/tins2021.go +++ b/cmd/tins2021/tins2021.go @@ -29,14 +29,20 @@ func openResources() ui.Resources { } func run() error { + var background string var extract bool + flag.StringVar(&background, "background", "", "generates a background") flag.BoolVar(&extract, "extract", false, "extracts all resources to the current working directory") flag.Parse() if extract { return copyBoxToDisk(resources) } + res := openResources() + if background != "" { + return GenerateBackground(res, background) + } ptPtr := func(x, y int) *geom.Point { p := geom.Pt(x, y)