cleaning and improving

This commit is contained in:
probandula
2016-10-27 16:21:03 +02:00
parent 3b00a8f4a2
commit 69ecfa2f6f
3 changed files with 194 additions and 148 deletions

166
font.go
View File

@@ -1,151 +1,35 @@
// Explanation of the .flf file header
// THE HEADER LINE
//
// The header line gives information about the FIGfont. Here is an example
// showing the names of all parameters:
//
// flf2a$ 6 5 20 15 3 0 143 229 NOTE: The first five characters in
// | | | | | | | | | | the entire file must be "flf2a".
// / / | | | | | | | \
// Signature / / | | | | | \ Codetag_Count
// Hardblank / / | | | \ Full_Layout*
// Height / | | \ Print_Direction
// Baseline / \ Comment_Lines
// Max_Length Old_Layout*
//
// * The two layout parameters are closely related and fairly complex.
// (See "INTERPRETATION OF LAYOUT PARAMETERS".)
//
package figlet4go
import (
"errors"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
)
const defaultFontName string = "standard"
// Represents a single font
type font struct {
// Hardblank symbol
hardblank string
// Height of one char
height int
//
fontSlice []string
}
// Holds the fonts
type fontManager struct {
// Font libraries
fontLib map[string]*font
// Font name to path
fontList map[string]string
}
// Create new fontmanager
func newFontManager() *fontManager {
this := &fontManager{}
this.fontLib = make(map[string]*font)
this.fontList = make(map[string]string)
this.loadBuildInFont()
return this
}
// Load all font *.flf files in the fontPath recursivly
func (this *fontManager) loadFont(fontPath string) error {
return filepath.Walk(fontPath, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() || !strings.HasSuffix(info.Name(), ".flf") {
return nil
}
fontName := strings.TrimSuffix(info.Name(), ".flf")
this.fontList[fontName] = path
return nil
})
}
// Load the default font
func (this *fontManager) loadBuildInFont() error {
// Default fonts to load
defaultFonts := []string{
"standard",
"larry3d",
}
// Load each default font
for _, name := range defaultFonts {
fontStr, err := Asset(name + ".flf")
if err != nil {
return err
}
font, err := this.parseFontContent(string(fontStr))
if err != nil {
return err
}
this.fontLib[name] = font
}
return nil
}
// Load a font from disk
func (this *fontManager) loadDiskFont(fontName string) error {
fontFilePath, ok := this.fontList[fontName]
if !ok {
return errors.New("FontName Not Found.")
}
// read full file content
fileBuf, err := ioutil.ReadFile(fontFilePath)
if err != nil {
return err
}
font, err := this.parseFontContent(string(fileBuf))
if err != nil {
return err
}
this.fontLib[fontName] = font
return nil
}
// Parse a font from a content string
func (this *fontManager) parseFontContent(cont string) (*font, error) {
lines := strings.Split(cont, "\n")
if len(lines) < 1 {
return nil, errors.New("font content error")
}
// flf2a$ 7 5 16 -1 12
// Fender by Scooter 8/94 (jkratten@law.georgetown.edu)
//
// Explanation of first line:
// flf2 - "magic number" for file identification
// a - should always be `a', for now
// $ - the "hardblank" -- prints as a blank, but can't be smushed
// 7 - height of a character
// 5 - height of a character, not including descenders
// 10 - max line length (excluding comment lines) + a fudge factor
// -1 - default smushmode for this font (like "-m 15" on command line)
// 12 - number of comment lines
header := strings.Split(lines[0], " ")
font := &font{}
font.hardblank = header[0][len(header[0])-1:]
font.height, _ = strconv.Atoi(header[1])
commentEndLine, _ := strconv.Atoi(header[5])
font.fontSlice = lines[commentEndLine+1:]
return font, nil
}
// Get a font by name
// Better error handling. Why is there one in the return if not used?
func (this *fontManager) getFont(fontName string) (*font, error) {
font, ok := this.fontLib[fontName]
if !ok {
err := this.loadDiskFont(fontName)
if err != nil {
font, _ := this.fontLib[defaultFontName]
return font, nil
}
}
font, _ = this.fontLib[fontName]
return font, nil
}
func (f *font) getCharSlice() []string {
// TODO here will be the logic of NewAsciiChar
return []string{}
}

165
fontmanager.go Normal file
View File

@@ -0,0 +1,165 @@
package figlet4go
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 fontmanagerM
func newFontManager() *fontManager {
fm := &fontManager{}
fm.fontLib = make(map[string]*font)
fm.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 occured
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 (this *fontManager) loadDiskFont(fontName string) error {
// Get the fontpath
path, ok := this.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
this.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
}
// Get the font
font, err := parseFontContent(string(fontStr))
if err != nil {
return err
}
// Register the font object in the fontLib
fm.fontLib[name] = 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
}

View File

@@ -17,7 +17,7 @@ type RenderOptions struct {
// Sets the default font name
func NewRenderOptions() *RenderOptions {
return &RenderOptions{
FontName: defaultFontName,
FontName: defaultFont,
}
}
@@ -36,7 +36,7 @@ func NewAsciiRender() *AsciiRender {
// Loading all *.flf font files recursively in a path
func (ar *AsciiRender) LoadFont(fontPath string) error {
return ar.fontMgr.loadFont(fontPath)
return ar.fontMgr.loadFontList(fontPath)
}
// Render a string with the default options
@@ -53,11 +53,8 @@ func (ar *AsciiRender) RenderOpts(str string, opt *RenderOptions) (string, error
colored := len(opt.FontColor) > 0
// Load the font
font, err := ar.fontMgr.getFont(opt.FontName)
if err != nil {
return "", err
}
font := ar.fontMgr.getFont(opt.FontName)
// Slice holding the chars
chars := []*AsciiChar{}