From e7498352b8b696887290bb74b7423b8c472eadde Mon Sep 17 00:00:00 2001 From: ekzyis Date: Sat, 19 Oct 2024 18:59:41 +0200 Subject: [PATCH] Use lightningvolt.ttf for coordinates --- chess/board.go | 38 +++++++++++++++++++++++++++++++++++--- go.mod | 1 + go.sum | 2 ++ lightningvolt.ttf | Bin 0 -> 22284 bytes 4 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 lightningvolt.ttf diff --git a/chess/board.go b/chess/board.go index 10ae061..80acd25 100644 --- a/chess/board.go +++ b/chess/board.go @@ -12,6 +12,7 @@ import ( "golang.org/x/image/font" "golang.org/x/image/font/basicfont" + "golang.org/x/image/font/opentype" "golang.org/x/image/math/fixed" ) @@ -197,11 +198,17 @@ func drawCoordinate(img *image.RGBA, x, y int, flipped bool) { } else if !flipped { color = Light } - // TODO: use SN font and make it bold + + face, err := loadFontFace("lightningvolt.ttf") + if err != nil { + log.Printf("error loading font: %v\n", err) + face = basicfont.Face7x13 + } + d := &font.Drawer{ Dst: img, Src: image.NewUniform(color), - Face: basicfont.Face7x13, + Face: face, Dot: origin, } d.DrawString(s) @@ -214,11 +221,36 @@ func drawCoordinate(img *image.RGBA, x, y int, flipped bool) { } if row != "" { - origin = fixed.P((x+1)*128-12, y*128+15) + origin = fixed.P((x+1)*128-20, y*128+23) drawString(row, origin) } } +func loadFontFace(path string) (font.Face, error) { + fontBytes, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + ttfFont, err := opentype.Parse(fontBytes) + if err != nil { + return nil, err + } + + faceOptions := &opentype.FaceOptions{ + Size: 32, + DPI: 72, + Hinting: font.HintingNone, + } + + fontFace, err := opentype.NewFace(ttfFont, faceOptions) + if err != nil { + return nil, err + } + + return fontFace, nil +} + func (b *Board) SetPiece(name PieceName, color Color, position string) error { var ( piece *Piece diff --git a/go.mod b/go.mod index 26c32c8..6391a77 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/text v0.18.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 7870f31..3691bec 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw= golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= diff --git a/lightningvolt.ttf b/lightningvolt.ttf new file mode 100644 index 0000000000000000000000000000000000000000..242a25fb6314e4ab1621583ef42c23aa85ba11ef GIT binary patch literal 22284 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