-
Notifications
You must be signed in to change notification settings - Fork 184
Expand file tree
/
Copy pathencoder.go
More file actions
139 lines (124 loc) · 4.87 KB
/
encoder.go
File metadata and controls
139 lines (124 loc) · 4.87 KB
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
// Package code93 can create Code93 barcodes
package code93
import (
"errors"
"strings"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type encodeInfo struct {
value int
data int
}
const (
// Special Function 1 ($)
FNC1 = '\u00f1'
// Special Function 2 (%)
FNC2 = '\u00f2'
// Special Function 3 (/)
FNC3 = '\u00f3'
// Special Function 4 (+)
FNC4 = '\u00f4'
)
var encodeTable = map[rune]encodeInfo{
'0': encodeInfo{0, 0x114}, '1': encodeInfo{1, 0x148}, '2': encodeInfo{2, 0x144},
'3': encodeInfo{3, 0x142}, '4': encodeInfo{4, 0x128}, '5': encodeInfo{5, 0x124},
'6': encodeInfo{6, 0x122}, '7': encodeInfo{7, 0x150}, '8': encodeInfo{8, 0x112},
'9': encodeInfo{9, 0x10A}, 'A': encodeInfo{10, 0x1A8}, 'B': encodeInfo{11, 0x1A4},
'C': encodeInfo{12, 0x1A2}, 'D': encodeInfo{13, 0x194}, 'E': encodeInfo{14, 0x192},
'F': encodeInfo{15, 0x18A}, 'G': encodeInfo{16, 0x168}, 'H': encodeInfo{17, 0x164},
'I': encodeInfo{18, 0x162}, 'J': encodeInfo{19, 0x134}, 'K': encodeInfo{20, 0x11A},
'L': encodeInfo{21, 0x158}, 'M': encodeInfo{22, 0x14C}, 'N': encodeInfo{23, 0x146},
'O': encodeInfo{24, 0x12C}, 'P': encodeInfo{25, 0x116}, 'Q': encodeInfo{26, 0x1B4},
'R': encodeInfo{27, 0x1B2}, 'S': encodeInfo{28, 0x1AC}, 'T': encodeInfo{29, 0x1A6},
'U': encodeInfo{30, 0x196}, 'V': encodeInfo{31, 0x19A}, 'W': encodeInfo{32, 0x16C},
'X': encodeInfo{33, 0x166}, 'Y': encodeInfo{34, 0x136}, 'Z': encodeInfo{35, 0x13A},
'-': encodeInfo{36, 0x12E}, '.': encodeInfo{37, 0x1D4}, ' ': encodeInfo{38, 0x1D2},
'$': encodeInfo{39, 0x1CA}, '/': encodeInfo{40, 0x16E}, '+': encodeInfo{41, 0x176},
'%': encodeInfo{42, 0x1AE}, FNC1: encodeInfo{43, 0x126}, FNC2: encodeInfo{44, 0x1DA},
FNC3: encodeInfo{45, 0x1D6}, FNC4: encodeInfo{46, 0x132}, '*': encodeInfo{47, 0x15E},
}
var extendedTable = []string{
"\u00f2U", "\u00f1A", "\u00f1B", "\u00f1C", "\u00f1D", "\u00f1E", "\u00f1F", "\u00f1G",
"\u00f1H", "\u00f1I", "\u00f1J", "\u00f1K", "\u00f1L", "\u00f1M", "\u00f1N", "\u00f1O",
"\u00f1P", "\u00f1Q", "\u00f1R", "\u00f1S", "\u00f1T", "\u00f1U", "\u00f1V", "\u00f1W",
"\u00f1X", "\u00f1Y", "\u00f1Z", "\u00f2A", "\u00f2B", "\u00f2C", "\u00f2D", "\u00f2E",
" ", "\u00f3A", "\u00f3B", "\u00f3C", "\u00f3D", "\u00f3E", "\u00f3F", "\u00f3G",
"\u00f3H", "\u00f3I", "\u00f3J", "\u00f3K", "\u00f3L", "-", ".", "\u00f3O",
"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "\u00f3Z", "\u00f2F", "\u00f2G", "\u00f2H", "\u00f2I", "\u00f2J",
"\u00f2V", "A", "B", "C", "D", "E", "F", "G",
"H", "I", "J", "K", "L", "M", "N", "O",
"P", "Q", "R", "S", "T", "U", "V", "W",
"X", "Y", "Z", "\u00f2K", "\u00f2L", "\u00f2M", "\u00f2N", "\u00f2O",
"\u00f2W", "\u00f4A", "\u00f4B", "\u00f4C", "\u00f4D", "\u00f4E", "\u00f4F", "\u00f4G",
"\u00f4H", "\u00f4I", "\u00f4J", "\u00f4K", "\u00f4L", "\u00f4M", "\u00f4N", "\u00f4O",
"\u00f4P", "\u00f4Q", "\u00f4R", "\u00f4S", "\u00f4T", "\u00f4U", "\u00f4V", "\u00f4W",
"\u00f4X", "\u00f4Y", "\u00f4Z", "\u00f2P", "\u00f2Q", "\u00f2R", "\u00f2S", "\u00f2T",
}
func prepare(content string) (string, error) {
result := ""
for _, r := range content {
if r > 127 {
return "", errors.New("only ASCII strings can be encoded")
}
result += extendedTable[int(r)]
}
return result, nil
}
// Encode returns a code93 barcode for the given content and color scheme
// if includeChecksum is set to true, two checksum characters are calculated and added to the content
func EncodeWithColor(content string, includeChecksum bool, fullASCIIMode bool, color barcode.ColorScheme) (barcode.Barcode, error) {
if fullASCIIMode {
var err error
content, err = prepare(content)
if err != nil {
return nil, err
}
} else if strings.ContainsRune(content, '*') {
return nil, errors.New("invalid data! content may not contain '*'")
}
data := content + string(getChecksum(content, 20))
if includeChecksum {
data += string(getChecksum(data, 15))
}
data = "*" + data + "*"
result := new(utils.BitList)
for _, r := range data {
info, ok := encodeTable[r]
if !ok {
return nil, errors.New("invalid data")
}
result.AddBits(info.data, 9)
}
result.AddBit(true)
return utils.New1DCodeWithColor(barcode.TypeCode93, content, result, color), nil
}
// Encode returns a code93 barcode for the given content
// if includeChecksum is set to true, two checksum characters are calculated and added to the content
func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.Barcode, error) {
return EncodeWithColor(content, includeChecksum, fullASCIIMode, barcode.ColorScheme16)
}
func getChecksum(content string, maxWeight int) rune {
weight := 1
total := 0
data := []rune(content)
for i := len(data) - 1; i >= 0; i-- {
r := data[i]
info, ok := encodeTable[r]
if !ok {
return ' '
}
total += info.value * weight
if weight++; weight > maxWeight {
weight = 1
}
}
total = total % 47
for r, info := range encodeTable {
if info.value == total {
return r
}
}
return ' '
}