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
|
// Package twooffive can create interleaved and standard "2 of 5" barcodes.
package twooffive
import (
"errors"
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
const patternWidth = 5
type pattern [patternWidth]bool
type encodeInfo struct {
start []bool
end []bool
widths map[bool]int
}
var (
encodingTable = map[rune]pattern{
'0': pattern{false, false, true, true, false},
'1': pattern{true, false, false, false, true},
'2': pattern{false, true, false, false, true},
'3': pattern{true, true, false, false, false},
'4': pattern{false, false, true, false, true},
'5': pattern{true, false, true, false, false},
'6': pattern{false, true, true, false, false},
'7': pattern{false, false, false, true, true},
'8': pattern{true, false, false, true, false},
'9': pattern{false, true, false, true, false},
}
modes = map[bool]encodeInfo{
false: encodeInfo{ // non-interleaved
start: []bool{true, true, false, true, true, false, true, false},
end: []bool{true, true, false, true, false, true, true},
widths: map[bool]int{
true: 3,
false: 1,
},
},
true: encodeInfo{ // interleaved
start: []bool{true, false, true, false},
end: []bool{true, true, false, true},
widths: map[bool]int{
true: 3,
false: 1,
},
},
}
nonInterleavedSpace = pattern{false, false, false, false, false}
)
// AddCheckSum calculates the correct check-digit and appends it to the given content.
func AddCheckSum(content string) (string, error) {
if content == "" {
return "", errors.New("content is empty")
}
even := len(content)%2 == 1
sum := 0
for _, r := range content {
if _, ok := encodingTable[r]; ok {
value := utils.RuneToInt(r)
if even {
sum += value * 3
} else {
sum += value
}
even = !even
} else {
return "", fmt.Errorf("can not encode \"%s\"", content)
}
}
return content + string(utils.IntToRune(sum%10)), nil
}
// Encode creates a codabar barcode for the given content
func Encode(content string, interleaved bool) (barcode.Barcode, error) {
if content == "" {
return nil, errors.New("content is empty")
}
if interleaved && len(content)%2 == 1 {
return nil, errors.New("can only encode even number of digits in interleaved mode")
}
mode := modes[interleaved]
resBits := new(utils.BitList)
resBits.AddBit(mode.start...)
var lastRune *rune
for _, r := range content {
var a, b pattern
if interleaved {
if lastRune == nil {
lastRune = new(rune)
*lastRune = r
continue
} else {
var o1, o2 bool
a, o1 = encodingTable[*lastRune]
b, o2 = encodingTable[r]
if !o1 || !o2 {
return nil, fmt.Errorf("can not encode \"%s\"", content)
}
lastRune = nil
}
} else {
var ok bool
a, ok = encodingTable[r]
if !ok {
return nil, fmt.Errorf("can not encode \"%s\"", content)
}
b = nonInterleavedSpace
}
for i := 0; i < patternWidth; i++ {
for x := 0; x < mode.widths[a[i]]; x++ {
resBits.AddBit(true)
}
for x := 0; x < mode.widths[b[i]]; x++ {
resBits.AddBit(false)
}
}
}
resBits.AddBit(mode.end...)
if interleaved {
return utils.New1DCode(barcode.Type2of5Interleaved, content, resBits), nil
} else {
return utils.New1DCode(barcode.Type2of5, content, resBits), nil
}
}
|