1
2 package twooffive
3
4 import (
5 "errors"
6 "fmt"
7
8 "github.com/boombuler/barcode"
9 "github.com/boombuler/barcode/utils"
10 )
11
12 const patternWidth = 5
13
14 type pattern [patternWidth]bool
15 type encodeInfo struct {
16 start []bool
17 end []bool
18 widths map[bool]int
19 }
20
21 var (
22 encodingTable = map[rune]pattern{
23 '0': pattern{false, false, true, true, false},
24 '1': pattern{true, false, false, false, true},
25 '2': pattern{false, true, false, false, true},
26 '3': pattern{true, true, false, false, false},
27 '4': pattern{false, false, true, false, true},
28 '5': pattern{true, false, true, false, false},
29 '6': pattern{false, true, true, false, false},
30 '7': pattern{false, false, false, true, true},
31 '8': pattern{true, false, false, true, false},
32 '9': pattern{false, true, false, true, false},
33 }
34
35 modes = map[bool]encodeInfo{
36 false: encodeInfo{
37 start: []bool{true, true, false, true, true, false, true, false},
38 end: []bool{true, true, false, true, false, true, true},
39 widths: map[bool]int{
40 true: 3,
41 false: 1,
42 },
43 },
44 true: encodeInfo{
45 start: []bool{true, false, true, false},
46 end: []bool{true, true, false, true},
47 widths: map[bool]int{
48 true: 3,
49 false: 1,
50 },
51 },
52 }
53 nonInterleavedSpace = pattern{false, false, false, false, false}
54 )
55
56
57 func AddCheckSum(content string) (string, error) {
58 if content == "" {
59 return "", errors.New("content is empty")
60 }
61
62 even := len(content)%2 == 1
63 sum := 0
64 for _, r := range content {
65 if _, ok := encodingTable[r]; ok {
66 value := utils.RuneToInt(r)
67 if even {
68 sum += value * 3
69 } else {
70 sum += value
71 }
72 even = !even
73 } else {
74 return "", fmt.Errorf("can not encode \"%s\"", content)
75 }
76 }
77
78 return content + string(utils.IntToRune(sum%10)), nil
79 }
80
81
82 func Encode(content string, interleaved bool) (barcode.Barcode, error) {
83 if content == "" {
84 return nil, errors.New("content is empty")
85 }
86
87 if interleaved && len(content)%2 == 1 {
88 return nil, errors.New("can only encode even number of digits in interleaved mode")
89 }
90
91 mode := modes[interleaved]
92 resBits := new(utils.BitList)
93 resBits.AddBit(mode.start...)
94
95 var lastRune *rune
96 for _, r := range content {
97 var a, b pattern
98 if interleaved {
99 if lastRune == nil {
100 lastRune = new(rune)
101 *lastRune = r
102 continue
103 } else {
104 var o1, o2 bool
105 a, o1 = encodingTable[*lastRune]
106 b, o2 = encodingTable[r]
107 if !o1 || !o2 {
108 return nil, fmt.Errorf("can not encode \"%s\"", content)
109 }
110 lastRune = nil
111 }
112 } else {
113 var ok bool
114 a, ok = encodingTable[r]
115 if !ok {
116 return nil, fmt.Errorf("can not encode \"%s\"", content)
117 }
118 b = nonInterleavedSpace
119 }
120
121 for i := 0; i < patternWidth; i++ {
122 for x := 0; x < mode.widths[a[i]]; x++ {
123 resBits.AddBit(true)
124 }
125 for x := 0; x < mode.widths[b[i]]; x++ {
126 resBits.AddBit(false)
127 }
128 }
129 }
130
131 resBits.AddBit(mode.end...)
132
133 if interleaved {
134 return utils.New1DCode(barcode.Type2of5Interleaved, content, resBits), nil
135 } else {
136 return utils.New1DCode(barcode.Type2of5, content, resBits), nil
137 }
138 }
139
View as plain text