Files
motdGO/fontmanager.go

177 lines
3.9 KiB
Go

package motdGO
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
// Default font if no other valid given
const defaultFont string = "standard"
// Extension of a font file
const extension string = "flf"
// Builtin fonts to load
var defaultFonts []string = []string{
"standard",
"larry3d",
}
// Holds the available fonts
type fontManager struct {
// The already read fonts
fontLib map[string]*font
// The in given pathes found fonts
fontList map[string]string
}
// Create a new fontmanager
// Initializes the fontManager,
// loads the builtin fonts and returns it
func newFontManager() *fontManager {
fm := &fontManager{
fontLib: make(map[string]*font),
fontList: make(map[string]string),
}
fm.loadBuildInFont()
return fm
}
// Get a font by name
// Default font if no other font could be loaded
func (fm *fontManager) getFont(fontName string) *font {
// Get the font from the fontLib
_, ok := fm.fontLib[fontName]
// Font not found
if !ok {
// Try to load it from loaded fontList
err := fm.loadDiskFont(fontName)
// Font also not found here, use the default font
if err != nil {
fontName = defaultFont
}
}
return fm.fontLib[fontName]
}
// Loads all .flf files recursively in the fontPath path
// Saves the found font files in a map with the name as the key
// and the path as the value. Doesn't load them at this point
// for performance. Called in the AsciiRenderer
func (fm *fontManager) loadFontList(fontPath string) error {
// Walk through the path
return filepath.Walk(fontPath, func(path string, info os.FileInfo, err error) error {
// Return an error if occurred
if err != nil {
return err
}
// If the current item is a directory or has not the correct suffix
if info.IsDir() || !strings.HasSuffix(info.Name(), "."+extension) {
return nil
}
// Extract the font name
fontName := strings.TrimSuffix(info.Name(), "."+extension)
// Save the font to the list
fm.fontList[fontName] = path
return nil
})
}
// Load a font from disk
// The font must be registered in the fontList
func (fm *fontManager) loadDiskFont(fontName string) error {
// Get the fontpath
path, ok := fm.fontList[fontName]
// Font is not registered
if !ok {
return errors.New("Font Not Found: " + fontName)
}
// Read file contents
fontStr, err := ioutil.ReadFile(path)
if err != nil {
return err
}
// Parse the file contents
font, err := parseFontContent(string(fontStr))
if err != nil {
return err
}
// Register the font object in the fontLib
fm.fontLib[fontName] = font
return nil
}
// Load the builtin fonts from the bindata.go file
// Load all fonts specified on top (defaultFonts)
func (fm *fontManager) loadBuildInFont() error {
// Load each default font
for _, name := range defaultFonts {
// Get Contents
fontStr, err := Asset(name + "." + extension)
if err != nil {
return err
}
// Load the font
err = fm.loadBindataFont(fontStr, name)
if err != nil {
return err
}
}
return nil
}
// Load a bindata font
func (fm *fontManager) loadBindataFont(fontBinary []byte, fontName string) error {
// Get the font
font, err := parseFontContent(string(fontBinary))
if err != nil {
return err
}
// Register the font object in the fontLib
fm.fontLib[fontName] = font
return nil
}
// Parse a font from a content string
// Used to load fonts from disk and the builtin fonts
func parseFontContent(cont string) (*font, error) {
// Get all lines
lines := strings.Split(cont, "\n")
if len(lines) < 1 {
return nil, errors.New("Font content error")
}
// Get the header metadata
header := strings.Split(lines[0], " ")
// Line end of the comment
commentEndLine, _ := strconv.Atoi(header[5])
// Char height
height, _ := strconv.Atoi(header[1])
// Initialize the font
font := &font{
hardblank: header[0][len(header[0])-1:],
height: height,
fontSlice: lines[commentEndLine+1:],
}
return font, nil
}