-
Notifications
You must be signed in to change notification settings - Fork 9
/
fontmanager.go
176 lines (148 loc) · 3.86 KB
/
fontmanager.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
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 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
}