github.com/Kintar/etxt@v0.0.0-20221224033739-2fc69f000137/examples/gtxt/outline_cheap/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 "golang.org/x/image/math/fixed"
    14  
    15  import "github.com/Kintar/etxt"
    16  
    17  // Must be compiled with '-tags gtxt'
    18  
    19  // This example draws text with a cheap and simple outline, made by
    20  // repeatedly drawing text slightly shifted to the left, right, up
    21  // and down. For higher quality outlines, see the OutlineRasterizer
    22  // instead and the gtxt/outline example.
    23  //
    24  // If you want a more advanced example on how to draw glyphs individually,
    25  // check gtxt/mirror instead. This example uses the renderer's DefaultDrawFunc,
    26  // so it doesn't get into the grittiest details.
    27  
    28  func main() {
    29  	// get font path
    30  	if len(os.Args) != 2 {
    31  		msg := "Usage: expects one argument with the path to the font to be used\n"
    32  		fmt.Fprint(os.Stderr, msg)
    33  		os.Exit(1)
    34  	}
    35  
    36  	// parse font
    37  	font, fontName, err := etxt.ParseFontFrom(os.Args[1])
    38  	if err != nil {
    39  		log.Fatal(err)
    40  	}
    41  	fmt.Printf("Font loaded: %s\n", fontName)
    42  
    43  	// create cache
    44  	cache := etxt.NewDefaultCache(1024 * 1024 * 1024) // 1GB cache
    45  
    46  	// create and configure renderer
    47  	renderer := etxt.NewStdRenderer()
    48  	renderer.SetCacheHandler(cache.NewHandler())
    49  	renderer.SetSizePx(36)
    50  	renderer.SetFont(font)
    51  	renderer.SetAlign(etxt.YCenter, etxt.XCenter)
    52  	renderer.SetColor(color.RGBA{0, 0, 0, 255}) // black
    53  
    54  	// create target image and fill it with white
    55  	outImage := image.NewRGBA(image.Rect(0, 0, 312, 64))
    56  	for i := 0; i < 312*64*4; i++ {
    57  		outImage.Pix[i] = 255
    58  	}
    59  
    60  	// set target and start drawing each character...
    61  	renderer.SetTarget(outImage)
    62  
    63  	// The key idea is to draw text repeatedly, slightly shifted
    64  	// to the left, right, up, down... and finally draw the middle.
    65  	// We could also do this with separate Draw() calls, but Traverse
    66  	// should be more efficient here.
    67  	//
    68  	// We will still draw the main text on a separate call afterwards
    69  	// in order to avoid the background of a letter being overlayed
    70  	// on top of a previously drawn letter (won't happen on most fonts
    71  	// or sizes or glyph sequences, but it's possible in some cases).
    72  	renderer.Traverse("Cheap Outline!", fixed.P(156, 32),
    73  		func(dot fixed.Point26_6, _ rune, glyphIndex etxt.GlyphIndex) {
    74  			const DotShift = 1 << 6 // we want to shift the letters 1 pixel
    75  			// to create an outline, but since we are
    76  			// using fixed precision numbers with 6
    77  			// bits for the decimal part, we need to
    78  			// apply this shift for the number to be
    79  			// correct in fixed.Int26_6 format.
    80  
    81  			mask := renderer.LoadGlyphMask(glyphIndex, dot)
    82  			dot.X -= DotShift // shift left
    83  			renderer.DefaultDrawFunc(dot, mask, glyphIndex)
    84  			dot.X += DotShift * 2 // shift right
    85  			renderer.DefaultDrawFunc(dot, mask, glyphIndex)
    86  			dot.X -= DotShift // restore X to center
    87  			dot.Y -= DotShift // shift up
    88  			renderer.DefaultDrawFunc(dot, mask, glyphIndex)
    89  			dot.Y += DotShift * 2 // shift down
    90  			renderer.DefaultDrawFunc(dot, mask, glyphIndex)
    91  		})
    92  
    93  	// finally draw the main text. you can try different colors, but
    94  	// white makes it look like there's only outline, so that's cool.
    95  	renderer.SetColor(color.RGBA{255, 255, 255, 255})
    96  	renderer.Draw("Cheap Outline!", 156, 32)
    97  
    98  	// store result as png
    99  	filename, err := filepath.Abs("gtxt_outline_cheap.png")
   100  	if err != nil {
   101  		log.Fatal(err)
   102  	}
   103  	fmt.Printf("Output image: %s\n", filename)
   104  	file, err := os.Create(filename)
   105  	if err != nil {
   106  		log.Fatal(err)
   107  	}
   108  	err = png.Encode(file, outImage)
   109  	if err != nil {
   110  		log.Fatal(err)
   111  	}
   112  	err = file.Close()
   113  	if err != nil {
   114  		log.Fatal(err)
   115  	}
   116  	fmt.Print("Program exited successfully.\n")
   117  }