-
Notifications
You must be signed in to change notification settings - Fork 0
/
convert.go
129 lines (106 loc) · 2.65 KB
/
convert.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
package tigrfont
import (
"fmt"
"image"
"image/png"
"os"
"strings"
)
type Codepage int
const (
ASCII Codepage = 0
CP1252 Codepage = 1252
UNICODE Codepage = 12001
)
func (cp Codepage) String() string {
switch cp {
case ASCII:
return "ascii"
case CP1252:
return "windows 1252"
case UNICODE:
return "unicode"
default:
return "invalid"
}
}
func Convert(options Options, font, target string) (int, error) {
var runeSet []rune
var err error
if len(options.Encoding) > 0 && len(options.SampleFile) > 0 {
return 0, fmt.Errorf("cannot specify both encoding and sample file")
}
replaceMode := replaceMissing
watermark := false
if len(options.Encoding) > 0 {
runeSet, err = runesFromEncoding(options.Encoding)
if err != nil {
return 0, fmt.Errorf("failed to extract characters from encoding %q: %w", options.Encoding, err)
}
replaceMode = removeMissing
watermark = true
options.Codepage = UNICODE
}
if len(options.SampleFile) > 0 {
runeSet, err = runesFromFile(options.SampleFile)
if err != nil {
return 0, fmt.Errorf("failed to extract characters from sample %q: %w", options.SampleFile, err)
}
replaceMode = removeMissing
watermark = true
options.Codepage = UNICODE
}
if len(runeSet) == 0 {
const lowChar = 32
var highChar = 127
switch options.Codepage {
case ASCII:
highChar = 127
case CP1252:
highChar = 255
case UNICODE:
return 0, fmt.Errorf("use encoding or sample file to create unicode sheet")
default:
return 0, fmt.Errorf("invalid TIGR codepage: %v", options.Codepage)
}
runeSet = runesFromRange(lowChar, highChar)
}
fontBytes, err := os.ReadFile(font)
if err != nil {
return 0, fmt.Errorf("failed to load font file: %w", err)
}
var img image.Image
var rendered int
// Try TTF first
img, rendered, err = tigrFromTTF(options, fontBytes, runeSet, replaceMode, watermark)
if err != nil {
font = strings.ToLower(font)
if strings.HasSuffix(font, "ttf") || strings.HasSuffix(font, "otf") {
return 0, err
}
// Assume BDF file
img, rendered, err = tigrFromBDF(fontBytes, runeSet, replaceMode, watermark)
if err != nil {
return 0, fmt.Errorf("failed to render font: %v", err)
}
}
if watermark {
img, err = palettize(img.(*image.NRGBA))
if err != nil {
return 0, err
}
}
pngFile, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0664)
if err != nil {
return 0, fmt.Errorf("failed to open target %q: %v", target, err)
}
defer pngFile.Close()
encoder := png.Encoder{
CompressionLevel: png.BestCompression,
}
err = encoder.Encode(pngFile, img)
if err != nil {
return 0, fmt.Errorf("failed to encode PNG: %v", err)
}
return rendered, nil
}