-
Notifications
You must be signed in to change notification settings - Fork 17
/
fonts.go
137 lines (112 loc) · 2.6 KB
/
fonts.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
package lookup
import (
"fmt"
"image"
"io/ioutil"
"net/url"
"os"
"strings"
)
type fontSymbol struct {
symbol string
image *imageBinary
width int
height int
}
func newFontSymbol(symbol string, img image.Image) *fontSymbol {
imgBin := newImageBinary(img)
fs := &fontSymbol{
symbol: symbol,
image: imgBin,
width: imgBin.width,
height: imgBin.height,
}
return fs
}
func (f *fontSymbol) String() string { return f.symbol }
type fontSymbolLookup struct {
fs *fontSymbol
x, y int
g float64
size int
}
func newFontSymbolLookup(fs *fontSymbol, x, y int, g float64) *fontSymbolLookup {
return &fontSymbolLookup{fs, x, y, g, fs.image.size}
}
func (l *fontSymbolLookup) cross(f *fontSymbolLookup) bool {
r := image.Rect(l.x, l.y, l.x+l.fs.width, l.y+l.fs.height)
r2 := image.Rect(f.x, f.y, f.x+f.fs.width, f.y+f.fs.height)
return r.Intersect(r2) != image.Rectangle{}
}
func (l *fontSymbolLookup) yCross(f *fontSymbolLookup) bool {
ly2 := l.y + l.fs.height
fy2 := f.y + f.fs.height
return (f.y >= l.y && f.y <= ly2) || (fy2 >= l.y && fy2 <= ly2)
}
func (l *fontSymbolLookup) biggerThan(other *fontSymbolLookup, maxSize2 int) bool {
if abs(abs(l.size)-abs(other.size)) >= maxSize2 {
return other.size < l.size
}
// better quality goes first
diff := l.g - other.g
if diff != 0 {
return diff > 0
}
// bigger items goes first
return other.size < l.size
}
func (l *fontSymbolLookup) comesAfter(f *fontSymbolLookup) bool {
r := 0
if !l.yCross(f) {
r = l.y - f.y
}
if r == 0 {
r = l.x - f.x
}
if r == 0 {
r = l.y - f.y
}
return r < 0
}
func (l *fontSymbolLookup) String() string {
return fmt.Sprintf("'%s'(%d,%d,%d)[%f]", l.fs.symbol, l.x, l.y, l.size, l.g)
}
func loadFont(path string) ([]*fontSymbol, error) {
files, err := ioutil.ReadDir(path)
if err != nil {
return nil, err
}
fonts := make([]*fontSymbol, 0)
for _, f := range files {
if f.IsDir() || strings.HasPrefix(f.Name(), ".") {
continue
}
fs, err := loadSymbol(path, f.Name())
if err != nil {
return nil, err
}
fonts = append(fonts,fs)
}
return fonts, nil
}
func loadSymbol(path string, fileName string) (*fontSymbol, error) {
imageFile, err := os.Open(path + "/" + fileName)
if err != nil {
return nil, err
}
defer imageFile.Close()
img, _, err := image.Decode(imageFile)
if err != nil {
return nil, err
}
symbolName, err := url.QueryUnescape(fileName)
if err != nil {
return nil, err
}
symbolName = strings.Replace(symbolName, "\u200b", "", -1) // Remove zero width spaces
fs := newFontSymbol(
strings.TrimSuffix(symbolName, ".png"),
ensureGrayScale(img),
)
return fs, nil
}