github.com/Kintar/etxt@v0.0.0-20221224033739-2fc69f000137/examples/gtxt/aligns/main.go (about) 1 //go:build gtxt 2 3 package main 4 5 import "os" 6 import "image" 7 import "image/color" 8 import "image/png" 9 import "path/filepath" 10 import "log" 11 import "fmt" 12 13 import "github.com/Kintar/etxt" 14 15 // Must be compiled with '-tags gtxt' 16 17 func main() { 18 // get font path 19 if len(os.Args) != 2 { 20 msg := "Usage: expects one argument with the path to the font to be used\n" 21 fmt.Fprint(os.Stderr, msg) 22 os.Exit(1) 23 } 24 25 // parse font 26 font, fontName, err := etxt.ParseFontFrom(os.Args[1]) 27 if err != nil { 28 log.Fatal(err) 29 } 30 fmt.Printf("Font loaded: %s\n", fontName) 31 32 // create cache 33 cache := etxt.NewDefaultCache(1024 * 1024 * 1024) // 1GB cache 34 35 // create and configure renderer 36 renderer := etxt.NewStdRenderer() 37 renderer.SetCacheHandler(cache.NewHandler()) 38 renderer.SetSizePx(18) 39 renderer.SetFont(font) 40 renderer.SetColor(color.RGBA{40, 0, 0, 255}) 41 42 // create target image and fill it with a dark background color, 43 // four rectangles to draw text with different aligns within each 44 // one, including guide lines and a central mark for each rectangle 45 // (this has nothing to do with etxt, it's only to make it look nice) 46 outImage, targets := makeFancyOutImage() 47 48 // set renderer's target and draw on each target point 49 // with different aligns 50 renderer.SetTarget(outImage) 51 52 // default (Baseline, Left) align 53 // renderer.SetAlign(etxt.Baseline, etxt.Left) 54 renderer.Draw("(Baseline, Left)", targets[0].X, targets[0].Y) 55 56 // (YCenter, XCenter) align 57 renderer.SetAlign(etxt.YCenter, etxt.XCenter) 58 renderer.Draw("(YCenter, XCenter)", targets[1].X, targets[1].Y) 59 60 // (Top, Right) align 61 renderer.SetAlign(etxt.Top, etxt.Right) 62 renderer.Draw("(Top, Right)", targets[2].X, targets[2].Y) 63 64 // (Bottom, XCenter) align 65 renderer.SetAlign(etxt.Bottom, etxt.XCenter) 66 renderer.Draw("(Bottom, XCenter)", targets[3].X, targets[3].Y) 67 68 // store image as png 69 filename, err := filepath.Abs("gtxt_aligns.png") 70 if err != nil { 71 log.Fatal(err) 72 } 73 fmt.Printf("Output image: %s\n", filename) 74 file, err := os.Create(filename) 75 if err != nil { 76 log.Fatal(err) 77 } 78 err = png.Encode(file, outImage) 79 if err != nil { 80 log.Fatal(err) 81 } 82 err = file.Close() 83 if err != nil { 84 log.Fatal(err) 85 } 86 fmt.Print("Program exited successfully.\n") 87 } 88 89 // Creates an image with four subrectangles in it, each with guide lines 90 // and a mark at their center, so we can use it to draw with different 91 // aligns on top and see how they relate to the given marks. 92 // 93 // This has nothing to do with etxt itself, so you don't need to understand 94 // it, and if you are doing game dev this is trivial for you anyway. 95 func makeFancyOutImage() (*image.RGBA, [4]image.Point) { 96 // out image properties 97 rectWidth := 301 98 rectHeight := 101 99 padding := 4 100 backColor := color.RGBA{R: 236, G: 236, B: 230, A: 255} 101 rectColor := color.RGBA{R: 200, G: 196, B: 206, A: 255} 102 guideColor := color.RGBA{R: 220, G: 220, B: 220, A: 255} 103 markColor := color.RGBA{R: 0, G: 80, B: 120, A: 255} 104 markColor2 := color.RGBA{R: 0, G: 190, B: 80, A: 255} 105 totalWidth := rectWidth*2 + padding*3 106 totalHeight := rectHeight*2 + padding*3 107 outImage := image.NewRGBA(image.Rect(0, 0, totalWidth, totalHeight)) 108 109 // paint background 110 for y := 0; y < totalHeight; y++ { 111 for x := 0; x < totalWidth; x++ { 112 outImage.Set(x, y, backColor) 113 } 114 } 115 116 // paint rects 117 for y := 0; y < rectHeight; y++ { 118 for x := 0; x < rectWidth; x++ { 119 // we draw the four rects at once (not ideal for memory accesses) 120 outImage.Set(x+padding, y+padding, rectColor) 121 outImage.Set(x+padding*2+rectWidth, y+padding, rectColor) 122 lowerY := y + rectHeight + padding*2 123 outImage.Set(x+padding, lowerY, rectColor) 124 outImage.Set(x+padding*2+rectWidth, lowerY, rectColor) 125 } 126 } 127 128 // paint guide lines 129 for x := 0; x < rectWidth; x++ { // horizontal guide lines 130 y := padding + rectHeight/2 131 outImage.Set(x+padding, y, guideColor) 132 outImage.Set(x+padding*2+rectWidth, y, guideColor) 133 yBottom := y + padding + rectHeight 134 outImage.Set(x+padding, yBottom, guideColor) 135 outImage.Set(x+padding*2+rectWidth, yBottom, guideColor) 136 } 137 for y := 0; y < rectHeight; y++ { // vertical guide lines 138 outImage.Set(padding+rectWidth/2, y+padding, guideColor) 139 outImage.Set(padding+rectWidth/2, y+padding*2+rectHeight, guideColor) 140 xRight := rectWidth/2 + padding*2 + rectWidth 141 outImage.Set(xRight, y+padding, guideColor) 142 outImage.Set(xRight, y+padding*2+rectHeight, guideColor) 143 } 144 145 // create target points for reference marks 146 ta := image.Pt(rectWidth/2+padding, rectHeight/2+padding) 147 tb := image.Pt(rectWidth/2+padding*2+rectWidth, rectHeight/2+padding) 148 tc := image.Pt(rectWidth/2+padding, rectHeight/2+padding*2+rectHeight) 149 td := image.Pt(rectWidth/2+padding*2+rectWidth, rectHeight/2+padding*2+rectHeight) 150 151 // paint reference marks 152 drawMarkAt := func(x, y int) { 153 outImage.Set(x, y, markColor) 154 for i := 1; i < 3; i++ { 155 outImage.Set(x+i, y, markColor) 156 outImage.Set(x-i, y, markColor) 157 outImage.Set(x, y-i, markColor) 158 outImage.Set(x, y+i, markColor) 159 } 160 outImage.Set(x+1, y+1, markColor2) 161 outImage.Set(x+1, y-1, markColor2) 162 outImage.Set(x-1, y+1, markColor2) 163 outImage.Set(x-1, y-1, markColor2) 164 } 165 drawMarkAt(ta.X, ta.Y) 166 drawMarkAt(tb.X, tb.Y) 167 drawMarkAt(tc.X, tc.Y) 168 drawMarkAt(td.X, td.Y) 169 170 return outImage, [4]image.Point{ta, tb, tc, td} 171 }