replace zxq.co/ripple/hanayo

This commit is contained in:
Alicia
2019-02-23 13:29:15 +00:00
commit c3d206c173
5871 changed files with 1353715 additions and 0 deletions

1
vendor/github.com/boombuler/barcode/.gitignore generated vendored Normal file
View File

@@ -0,0 +1 @@
.vscode/

21
vendor/github.com/boombuler/barcode/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Florian Sundermann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

53
vendor/github.com/boombuler/barcode/README.md generated vendored Normal file
View File

@@ -0,0 +1,53 @@
[![Join the chat at https://gitter.im/golang-barcode/Lobby](https://badges.gitter.im/golang-barcode/Lobby.svg)](https://gitter.im/golang-barcode/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
## Introduction ##
This is a package for GO which can be used to create different types of barcodes.
## Supported Barcode Types ##
* 2 of 5
* Aztec Code
* Codabar
* Code 128
* Code 39
* Code 93
* Datamatrix
* EAN 13
* EAN 8
* PDF 417
* QR Code
## Example ##
This is a simple example on how to create a QR-Code and write it to a png-file
```go
package main
import (
"image/png"
"os"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
)
func main() {
// Create the barcode
qrCode, _ := qr.Encode("Hello World", qr.M, qr.Auto)
// Scale the barcode to 200x200 pixels
qrCode, _ = barcode.Scale(qrCode, 200, 200)
// create the output file
file, _ := os.Create("qrcode.png")
defer file.Close()
// encode the barcode as png
png.Encode(file, qrCode)
}
```
## Documentation ##
See [GoDoc](https://godoc.org/github.com/boombuler/barcode)
To create a barcode use the Encode function from one of the subpackages.

View File

@@ -0,0 +1,94 @@
package aztec
import (
"testing"
)
func encodeTest(t *testing.T, data, wanted string) {
result, err := Encode([]byte(data), DEFAULT_EC_PERCENT, DEFAULT_LAYERS)
if err != nil {
t.Error(err)
} else {
ac, ok := result.(*aztecCode)
if !ok {
t.Error("returned barcode is no aztec code...")
} else if draw := ac.string(); draw != wanted {
t.Errorf("Invalid Barcode returned:\n%s", draw)
}
}
}
func Test_Encode1(t *testing.T) {
encodeTest(t, "This is an example Aztec symbol for Wikipedia.",
"X X X X X X X X \n"+
"X X X X X X X X X X \n"+
"X X X X X X X X X X X \n"+
"X X X X X X X X X X X \n"+
" X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X \n"+
"X X X X X X X X X X \n"+
" X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X \n"+
" X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X \n"+
" X X X \n"+
" X X X X X X X X X X \n"+
" X X X X X X X X X X \n")
}
func Test_Encode2(t *testing.T) {
encodeTest(t, "Aztec Code is a public domain 2D matrix barcode symbology"+
" of nominally square symbols built on a square grid with a "+
"distinctive square bullseye pattern at their center.",
" X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X X X X X X X X X \n"+
" X X X X X X X X X X X X X X X X \n"+
"X X X X X X X X X X X X X \n")
}

62
vendor/github.com/boombuler/barcode/aztec/azteccode.go generated vendored Normal file
View File

@@ -0,0 +1,62 @@
package aztec
import (
"bytes"
"image"
"image/color"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type aztecCode struct {
*utils.BitList
size int
content []byte
}
func newAztecCode(size int) *aztecCode {
return &aztecCode{utils.NewBitList(size * size), size, nil}
}
func (c *aztecCode) Content() string {
return string(c.content)
}
func (c *aztecCode) Metadata() barcode.Metadata {
return barcode.Metadata{barcode.TypeAztec, 2}
}
func (c *aztecCode) ColorModel() color.Model {
return color.Gray16Model
}
func (c *aztecCode) Bounds() image.Rectangle {
return image.Rect(0, 0, c.size, c.size)
}
func (c *aztecCode) At(x, y int) color.Color {
if c.GetBit(x*c.size + y) {
return color.Black
}
return color.White
}
func (c *aztecCode) set(x, y int) {
c.SetBit(x*c.size+y, true)
}
func (c *aztecCode) string() string {
buf := new(bytes.Buffer)
for y := 0; y < c.size; y++ {
for x := 0; x < c.size; x++ {
if c.GetBit(x*c.size + y) {
buf.WriteString("X ")
} else {
buf.WriteString(" ")
}
}
buf.WriteRune('\n')
}
return buf.String()
}

268
vendor/github.com/boombuler/barcode/aztec/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,268 @@
// Package aztec can create Aztec Code barcodes
package aztec
import (
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
const (
DEFAULT_EC_PERCENT = 33
DEFAULT_LAYERS = 0
max_nb_bits = 32
max_nb_bits_compact = 4
)
var (
word_size = []int{
4, 6, 6, 8, 8, 8, 8, 8, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
}
)
func totalBitsInLayer(layers int, compact bool) int {
tmp := 112
if compact {
tmp = 88
}
return (tmp + 16*layers) * layers
}
func stuffBits(bits *utils.BitList, wordSize int) *utils.BitList {
out := new(utils.BitList)
n := bits.Len()
mask := (1 << uint(wordSize)) - 2
for i := 0; i < n; i += wordSize {
word := 0
for j := 0; j < wordSize; j++ {
if i+j >= n || bits.GetBit(i+j) {
word |= 1 << uint(wordSize-1-j)
}
}
if (word & mask) == mask {
out.AddBits(word&mask, byte(wordSize))
i--
} else if (word & mask) == 0 {
out.AddBits(word|1, byte(wordSize))
i--
} else {
out.AddBits(word, byte(wordSize))
}
}
return out
}
func generateModeMessage(compact bool, layers, messageSizeInWords int) *utils.BitList {
modeMessage := new(utils.BitList)
if compact {
modeMessage.AddBits(layers-1, 2)
modeMessage.AddBits(messageSizeInWords-1, 6)
modeMessage = generateCheckWords(modeMessage, 28, 4)
} else {
modeMessage.AddBits(layers-1, 5)
modeMessage.AddBits(messageSizeInWords-1, 11)
modeMessage = generateCheckWords(modeMessage, 40, 4)
}
return modeMessage
}
func drawModeMessage(matrix *aztecCode, compact bool, matrixSize int, modeMessage *utils.BitList) {
center := matrixSize / 2
if compact {
for i := 0; i < 7; i++ {
offset := center - 3 + i
if modeMessage.GetBit(i) {
matrix.set(offset, center-5)
}
if modeMessage.GetBit(i + 7) {
matrix.set(center+5, offset)
}
if modeMessage.GetBit(20 - i) {
matrix.set(offset, center+5)
}
if modeMessage.GetBit(27 - i) {
matrix.set(center-5, offset)
}
}
} else {
for i := 0; i < 10; i++ {
offset := center - 5 + i + i/5
if modeMessage.GetBit(i) {
matrix.set(offset, center-7)
}
if modeMessage.GetBit(i + 10) {
matrix.set(center+7, offset)
}
if modeMessage.GetBit(29 - i) {
matrix.set(offset, center+7)
}
if modeMessage.GetBit(39 - i) {
matrix.set(center-7, offset)
}
}
}
}
func drawBullsEye(matrix *aztecCode, center, size int) {
for i := 0; i < size; i += 2 {
for j := center - i; j <= center+i; j++ {
matrix.set(j, center-i)
matrix.set(j, center+i)
matrix.set(center-i, j)
matrix.set(center+i, j)
}
}
matrix.set(center-size, center-size)
matrix.set(center-size+1, center-size)
matrix.set(center-size, center-size+1)
matrix.set(center+size, center-size)
matrix.set(center+size, center-size+1)
matrix.set(center+size, center+size-1)
}
// Encode returns an aztec barcode with the given content
func Encode(data []byte, minECCPercent int, userSpecifiedLayers int) (barcode.Barcode, error) {
bits := highlevelEncode(data)
eccBits := ((bits.Len() * minECCPercent) / 100) + 11
totalSizeBits := bits.Len() + eccBits
var layers, TotalBitsInLayer, wordSize int
var compact bool
var stuffedBits *utils.BitList
if userSpecifiedLayers != DEFAULT_LAYERS {
compact = userSpecifiedLayers < 0
if compact {
layers = -userSpecifiedLayers
} else {
layers = userSpecifiedLayers
}
if (compact && layers > max_nb_bits_compact) || (!compact && layers > max_nb_bits) {
return nil, fmt.Errorf("Illegal value %d for layers", userSpecifiedLayers)
}
TotalBitsInLayer = totalBitsInLayer(layers, compact)
wordSize = word_size[layers]
usableBitsInLayers := TotalBitsInLayer - (TotalBitsInLayer % wordSize)
stuffedBits = stuffBits(bits, wordSize)
if stuffedBits.Len()+eccBits > usableBitsInLayers {
return nil, fmt.Errorf("Data to large for user specified layer")
}
if compact && stuffedBits.Len() > wordSize*64 {
return nil, fmt.Errorf("Data to large for user specified layer")
}
} else {
wordSize = 0
stuffedBits = nil
// We look at the possible table sizes in the order Compact1, Compact2, Compact3,
// Compact4, Normal4,... Normal(i) for i < 4 isn't typically used since Compact(i+1)
// is the same size, but has more data.
for i := 0; ; i++ {
if i > max_nb_bits {
return nil, fmt.Errorf("Data too large for an aztec code")
}
compact = i <= 3
layers = i
if compact {
layers = i + 1
}
TotalBitsInLayer = totalBitsInLayer(layers, compact)
if totalSizeBits > TotalBitsInLayer {
continue
}
// [Re]stuff the bits if this is the first opportunity, or if the
// wordSize has changed
if wordSize != word_size[layers] {
wordSize = word_size[layers]
stuffedBits = stuffBits(bits, wordSize)
}
usableBitsInLayers := TotalBitsInLayer - (TotalBitsInLayer % wordSize)
if compact && stuffedBits.Len() > wordSize*64 {
// Compact format only allows 64 data words, though C4 can hold more words than that
continue
}
if stuffedBits.Len()+eccBits <= usableBitsInLayers {
break
}
}
}
messageBits := generateCheckWords(stuffedBits, TotalBitsInLayer, wordSize)
messageSizeInWords := stuffedBits.Len() / wordSize
modeMessage := generateModeMessage(compact, layers, messageSizeInWords)
// allocate symbol
var baseMatrixSize int
if compact {
baseMatrixSize = 11 + layers*4
} else {
baseMatrixSize = 14 + layers*4
}
alignmentMap := make([]int, baseMatrixSize)
var matrixSize int
if compact {
// no alignment marks in compact mode, alignmentMap is a no-op
matrixSize = baseMatrixSize
for i := 0; i < len(alignmentMap); i++ {
alignmentMap[i] = i
}
} else {
matrixSize = baseMatrixSize + 1 + 2*((baseMatrixSize/2-1)/15)
origCenter := baseMatrixSize / 2
center := matrixSize / 2
for i := 0; i < origCenter; i++ {
newOffset := i + i/15
alignmentMap[origCenter-i-1] = center - newOffset - 1
alignmentMap[origCenter+i] = center + newOffset + 1
}
}
code := newAztecCode(matrixSize)
code.content = data
// draw data bits
for i, rowOffset := 0, 0; i < layers; i++ {
rowSize := (layers - i) * 4
if compact {
rowSize += 9
} else {
rowSize += 12
}
for j := 0; j < rowSize; j++ {
columnOffset := j * 2
for k := 0; k < 2; k++ {
if messageBits.GetBit(rowOffset + columnOffset + k) {
code.set(alignmentMap[i*2+k], alignmentMap[i*2+j])
}
if messageBits.GetBit(rowOffset + rowSize*2 + columnOffset + k) {
code.set(alignmentMap[i*2+j], alignmentMap[baseMatrixSize-1-i*2-k])
}
if messageBits.GetBit(rowOffset + rowSize*4 + columnOffset + k) {
code.set(alignmentMap[baseMatrixSize-1-i*2-k], alignmentMap[baseMatrixSize-1-i*2-j])
}
if messageBits.GetBit(rowOffset + rowSize*6 + columnOffset + k) {
code.set(alignmentMap[baseMatrixSize-1-i*2-j], alignmentMap[i*2+k])
}
}
}
rowOffset += rowSize * 8
}
// draw mode message
drawModeMessage(code, compact, matrixSize, modeMessage)
// draw alignment marks
if compact {
drawBullsEye(code, matrixSize/2, 5)
} else {
drawBullsEye(code, matrixSize/2, 7)
for i, j := 0, 0; i < baseMatrixSize/2-1; i, j = i+15, j+16 {
for k := (matrixSize / 2) & 1; k < matrixSize; k += 2 {
code.set(matrixSize/2-j, k)
code.set(matrixSize/2+j, k)
code.set(k, matrixSize/2-j)
code.set(k, matrixSize/2+j)
}
}
}
return code, nil
}

View File

@@ -0,0 +1,58 @@
package aztec
import (
"strings"
"testing"
"github.com/boombuler/barcode/utils"
)
func Test_StuffBits(t *testing.T) {
testStuffBits := func(wordSize int, bits string, expected string) {
bl := new(utils.BitList)
for _, r := range bits {
if r == 'X' {
bl.AddBit(true)
} else if r == '.' {
bl.AddBit(false)
}
}
stuffed := stuffBits(bl, wordSize)
expectedBits := strings.Replace(expected, " ", "", -1)
result := bitStr(stuffed)
if result != expectedBits {
t.Errorf("stuffBits failed for %q\nGot: %q", bits, result)
}
}
testStuffBits(5, ".X.X. X.X.X .X.X.",
".X.X. X.X.X .X.X.")
testStuffBits(5, ".X.X. ..... .X.X",
".X.X. ....X ..X.X")
testStuffBits(3, "XX. ... ... ..X XXX .X. ..",
"XX. ..X ..X ..X ..X .XX XX. .X. ..X")
testStuffBits(6, ".X.X.. ...... ..X.XX",
".X.X.. .....X. ..X.XX XXXX.")
testStuffBits(6, ".X.X.. ...... ...... ..X.X.",
".X.X.. .....X .....X ....X. X.XXXX")
testStuffBits(6, ".X.X.. XXXXXX ...... ..X.XX",
".X.X.. XXXXX. X..... ...X.X XXXXX.")
testStuffBits(6,
"...... ..XXXX X..XX. .X.... .X.X.X .....X .X.... ...X.X .....X ....XX ..X... ....X. X..XXX X.XX.X",
".....X ...XXX XX..XX ..X... ..X.X. X..... X.X... ....X. X..... X....X X..X.. .....X X.X..X XXX.XX .XXXXX")
}
func Test_ModeMessage(t *testing.T) {
testModeMessage := func(compact bool, layers, words int, expected string) {
result := bitStr(generateModeMessage(compact, layers, words))
expectedBits := strings.Replace(expected, " ", "", -1)
if result != expectedBits {
t.Errorf("generateModeMessage(%v, %d, %d) failed.\nGot:%s", compact, layers, words, result)
}
}
testModeMessage(true, 2, 29, ".X .XXX.. ...X XX.. ..X .XX. .XX.X")
testModeMessage(true, 4, 64, "XX XXXXXX .X.. ...X ..XX .X.. XX..")
testModeMessage(false, 21, 660, "X.X.. .X.X..X..XX .XXX ..X.. .XXX. .X... ..XXX")
testModeMessage(false, 32, 4096, "XXXXX XXXXXXXXXXX X.X. ..... XXX.X ..X.. X.XXX")
}

View File

@@ -0,0 +1,61 @@
package aztec
import (
"github.com/boombuler/barcode/utils"
)
func bitsToWords(stuffedBits *utils.BitList, wordSize int, wordCount int) []int {
message := make([]int, wordCount)
for i := 0; i < wordCount; i++ {
value := 0
for j := 0; j < wordSize; j++ {
if stuffedBits.GetBit(i*wordSize + j) {
value |= (1 << uint(wordSize-j-1))
}
}
message[i] = value
}
return message
}
func generateCheckWords(bits *utils.BitList, totalBits, wordSize int) *utils.BitList {
rs := utils.NewReedSolomonEncoder(getGF(wordSize))
// bits is guaranteed to be a multiple of the wordSize, so no padding needed
messageWordCount := bits.Len() / wordSize
totalWordCount := totalBits / wordSize
eccWordCount := totalWordCount - messageWordCount
messageWords := bitsToWords(bits, wordSize, messageWordCount)
eccWords := rs.Encode(messageWords, eccWordCount)
startPad := totalBits % wordSize
messageBits := new(utils.BitList)
messageBits.AddBits(0, byte(startPad))
for _, messageWord := range messageWords {
messageBits.AddBits(messageWord, byte(wordSize))
}
for _, eccWord := range eccWords {
messageBits.AddBits(eccWord, byte(wordSize))
}
return messageBits
}
func getGF(wordSize int) *utils.GaloisField {
switch wordSize {
case 4:
return utils.NewGaloisField(0x13, 16, 1)
case 6:
return utils.NewGaloisField(0x43, 64, 1)
case 8:
return utils.NewGaloisField(0x012D, 256, 1)
case 10:
return utils.NewGaloisField(0x409, 1024, 1)
case 12:
return utils.NewGaloisField(0x1069, 4096, 1)
default:
return nil
}
}

171
vendor/github.com/boombuler/barcode/aztec/highlevel.go generated vendored Normal file
View File

@@ -0,0 +1,171 @@
package aztec
import (
"github.com/boombuler/barcode/utils"
)
func highlevelEncode(data []byte) *utils.BitList {
states := stateSlice{initialState}
for index := 0; index < len(data); index++ {
pairCode := 0
nextChar := byte(0)
if index+1 < len(data) {
nextChar = data[index+1]
}
switch cur := data[index]; {
case cur == '\r' && nextChar == '\n':
pairCode = 2
case cur == '.' && nextChar == ' ':
pairCode = 3
case cur == ',' && nextChar == ' ':
pairCode = 4
case cur == ':' && nextChar == ' ':
pairCode = 5
}
if pairCode > 0 {
// We have one of the four special PUNCT pairs. Treat them specially.
// Get a new set of states for the two new characters.
states = updateStateListForPair(states, data, index, pairCode)
index++
} else {
// Get a new set of states for the new character.
states = updateStateListForChar(states, data, index)
}
}
minBitCnt := int((^uint(0)) >> 1)
var result *state = nil
for _, s := range states {
if s.bitCount < minBitCnt {
minBitCnt = s.bitCount
result = s
}
}
if result != nil {
return result.toBitList(data)
} else {
return new(utils.BitList)
}
}
func simplifyStates(states stateSlice) stateSlice {
var result stateSlice = nil
for _, newState := range states {
add := true
var newResult stateSlice = nil
for _, oldState := range result {
if add && oldState.isBetterThanOrEqualTo(newState) {
add = false
}
if !(add && newState.isBetterThanOrEqualTo(oldState)) {
newResult = append(newResult, oldState)
}
}
if add {
result = append(newResult, newState)
} else {
result = newResult
}
}
return result
}
// We update a set of states for a new character by updating each state
// for the new character, merging the results, and then removing the
// non-optimal states.
func updateStateListForChar(states stateSlice, data []byte, index int) stateSlice {
var result stateSlice = nil
for _, s := range states {
if r := updateStateForChar(s, data, index); len(r) > 0 {
result = append(result, r...)
}
}
return simplifyStates(result)
}
// Return a set of states that represent the possible ways of updating this
// state for the next character. The resulting set of states are added to
// the "result" list.
func updateStateForChar(s *state, data []byte, index int) stateSlice {
var result stateSlice = nil
ch := data[index]
charInCurrentTable := charMap[s.mode][ch] > 0
var stateNoBinary *state = nil
for mode := mode_upper; mode <= mode_punct; mode++ {
charInMode := charMap[mode][ch]
if charInMode > 0 {
if stateNoBinary == nil {
// Only create stateNoBinary the first time it's required.
stateNoBinary = s.endBinaryShift(index)
}
// Try generating the character by latching to its mode
if !charInCurrentTable || mode == s.mode || mode == mode_digit {
// If the character is in the current table, we don't want to latch to
// any other mode except possibly digit (which uses only 4 bits). Any
// other latch would be equally successful *after* this character, and
// so wouldn't save any bits.
res := stateNoBinary.latchAndAppend(mode, charInMode)
result = append(result, res)
}
// Try generating the character by switching to its mode.
if _, ok := shiftTable[s.mode][mode]; !charInCurrentTable && ok {
// It never makes sense to temporarily shift to another mode if the
// character exists in the current mode. That can never save bits.
res := stateNoBinary.shiftAndAppend(mode, charInMode)
result = append(result, res)
}
}
}
if s.bShiftByteCount > 0 || charMap[s.mode][ch] == 0 {
// It's never worthwhile to go into binary shift mode if you're not already
// in binary shift mode, and the character exists in your current mode.
// That can never save bits over just outputting the char in the current mode.
res := s.addBinaryShiftChar(index)
result = append(result, res)
}
return result
}
// We update a set of states for a new character by updating each state
// for the new character, merging the results, and then removing the
// non-optimal states.
func updateStateListForPair(states stateSlice, data []byte, index int, pairCode int) stateSlice {
var result stateSlice = nil
for _, s := range states {
if r := updateStateForPair(s, data, index, pairCode); len(r) > 0 {
result = append(result, r...)
}
}
return simplifyStates(result)
}
func updateStateForPair(s *state, data []byte, index int, pairCode int) stateSlice {
var result stateSlice
stateNoBinary := s.endBinaryShift(index)
// Possibility 1. Latch to MODE_PUNCT, and then append this code
result = append(result, stateNoBinary.latchAndAppend(mode_punct, pairCode))
if s.mode != mode_punct {
// Possibility 2. Shift to MODE_PUNCT, and then append this code.
// Every state except MODE_PUNCT (handled above) can shift
result = append(result, stateNoBinary.shiftAndAppend(mode_punct, pairCode))
}
if pairCode == 3 || pairCode == 4 {
// both characters are in DIGITS. Sometimes better to just add two digits
digitState := stateNoBinary.
latchAndAppend(mode_digit, 16-pairCode). // period or comma in DIGIT
latchAndAppend(mode_digit, 1) // space in DIGIT
result = append(result, digitState)
}
if s.bShiftByteCount > 0 {
// It only makes sense to do the characters as binary if we're already
// in binary mode.
result = append(result, s.addBinaryShiftChar(index).addBinaryShiftChar(index+1))
}
return result
}

View File

@@ -0,0 +1,132 @@
package aztec
import (
"bytes"
"strings"
"testing"
"github.com/boombuler/barcode/utils"
)
func bitStr(bl *utils.BitList) string {
buf := new(bytes.Buffer)
for i := 0; i < bl.Len(); i++ {
if bl.GetBit(i) {
buf.WriteRune('X')
} else {
buf.WriteRune('.')
}
}
return buf.String()
}
func testHighLevelEncodeString(t *testing.T, s, expectedBits string) {
bits := highlevelEncode([]byte(s))
result := bitStr(bits)
expectedBits = strings.Replace(expectedBits, " ", "", -1)
if result != expectedBits {
t.Errorf("invalid result for highlevelEncode(%q). Got:\n%s", s, result)
}
}
func testHighLevelEncodeStringCnt(t *testing.T, s string, expectedBitCnt int) {
bits := highlevelEncode([]byte(s))
if bits.Len() != expectedBitCnt {
t.Errorf("invalid result for highlevelEncode(%q). Got %d, expected %d bits", s, bits.Len(), expectedBitCnt)
}
}
func Test_HighLevelEncode(t *testing.T) {
testHighLevelEncodeString(t, "A. b.",
// 'A' P/S '. ' L/L b D/L '.'
"...X. ..... ...XX XXX.. ...XX XXXX. XX.X")
testHighLevelEncodeString(t, "Lorem ipsum.",
// 'L' L/L 'o' 'r' 'e' 'm' ' ' 'i' 'p' 's' 'u' 'm' D/L '.'
".XX.X XXX.. X.... X..XX ..XX. .XXX. ....X .X.X. X...X X.X.. X.XX. .XXX. XXXX. XX.X")
testHighLevelEncodeString(t, "Lo. Test 123.",
// 'L' L/L 'o' P/S '. ' U/S 'T' 'e' 's' 't' D/L ' ' '1' '2' '3' '.'
".XX.X XXX.. X.... ..... ...XX XXX.. X.X.X ..XX. X.X.. X.X.X XXXX. ...X ..XX .X.. .X.X XX.X")
testHighLevelEncodeString(t, "Lo...x",
// 'L' L/L 'o' D/L '.' '.' '.' U/L L/L 'x'
".XX.X XXX.. X.... XXXX. XX.X XX.X XX.X XXX. XXX.. XX..X")
testHighLevelEncodeString(t, ". x://abc/.",
//P/S '. ' L/L 'x' P/S ':' P/S '/' P/S '/' 'a' 'b' 'c' P/S '/' D/L '.'
"..... ...XX XXX.. XX..X ..... X.X.X ..... X.X.. ..... X.X.. ...X. ...XX ..X.. ..... X.X.. XXXX. XX.X")
// Uses Binary/Shift rather than Lower/Shift to save two bits.
testHighLevelEncodeString(t, "ABCdEFG",
//'A' 'B' 'C' B/S =1 'd' 'E' 'F' 'G'
"...X. ...XX ..X.. XXXXX ....X .XX..X.. ..XX. ..XXX .X...")
testHighLevelEncodeStringCnt(t,
// Found on an airline boarding pass. Several stretches of Binary shift are
// necessary to keep the bitcount so low.
"09 UAG ^160MEUCIQC0sYS/HpKxnBELR1uB85R20OoqqwFGa0q2uEi"+
"Ygh6utAIgLl1aBVM4EOTQtMQQYH9M2Z3Dp4qnA/fwWuQ+M8L3V8U=",
823)
}
func Test_HighLevelEncodeBinary(t *testing.T) {
// binary short form single byte
testHighLevelEncodeString(t, "N\u0000N",
// 'N' B/S =1 '\0' N
".XXXX XXXXX ....X ........ .XXXX") // Encode "N" in UPPER
testHighLevelEncodeString(t, "N\u0000n",
// 'N' B/S =2 '\0' 'n'
".XXXX XXXXX ...X. ........ .XX.XXX.") // Encode "n" in BINARY
// binary short form consecutive bytes
testHighLevelEncodeString(t, "N\x00\x80 A",
// 'N' B/S =2 '\0' \u0080 ' ' 'A'
".XXXX XXXXX ...X. ........ X....... ....X ...X.")
// binary skipping over single character
testHighLevelEncodeString(t, "\x00a\xFF\x80 A",
// B/S =4 '\0' 'a' '\3ff' '\200' ' ' 'A'
"XXXXX ..X.. ........ .XX....X XXXXXXXX X....... ....X ...X.")
// getting into binary mode from digit mode
testHighLevelEncodeString(t, "1234\u0000",
//D/L '1' '2' '3' '4' U/L B/S =1 \0
"XXXX. ..XX .X.. .X.X .XX. XXX. XXXXX ....X ........")
// Create a string in which every character requires binary
sb := new(bytes.Buffer)
for i := 0; i <= 3000; i++ {
sb.WriteByte(byte(128 + (i % 30)))
}
// Test the output generated by Binary/Switch, particularly near the
// places where the encoding changes: 31, 62, and 2047+31=2078
for _, i := range []int{1, 2, 3, 10, 29, 30, 31, 32, 33, 60, 61, 62, 63, 64, 2076, 2077, 2078, 2079, 2080, 2100} {
// This is the expected length of a binary string of length "i"
expectedLength := (8 * i)
switch {
case i <= 31:
expectedLength += 10
case i <= 62:
expectedLength += 20
case i <= 2078:
expectedLength += 21
default:
expectedLength += 31
}
data := string(sb.Bytes()[:i])
// Verify that we are correct about the length.
testHighLevelEncodeStringCnt(t, data, expectedLength)
if i != 1 && i != 32 && i != 2079 {
// The addition of an 'a' at the beginning or end gets merged into the binary code
// in those cases where adding another binary character only adds 8 or 9 bits to the result.
// So we exclude the border cases i=1,32,2079
// A lower case letter at the beginning will be merged into binary mode
testHighLevelEncodeStringCnt(t, "a"+string(sb.Bytes()[:i-1]), expectedLength)
// A lower case letter at the end will also be merged into binary mode
testHighLevelEncodeStringCnt(t, string(sb.Bytes()[:i-1])+"a", expectedLength)
}
// A lower case letter at both ends will enough to latch us into LOWER.
testHighLevelEncodeStringCnt(t, "a"+data+"b", expectedLength+15)
}
}

264
vendor/github.com/boombuler/barcode/aztec/state.go generated vendored Normal file
View File

@@ -0,0 +1,264 @@
package aztec
import (
"fmt"
"github.com/boombuler/barcode/utils"
)
type encodingMode byte
const (
mode_upper encodingMode = iota // 5 bits
mode_lower // 5 bits
mode_digit // 4 bits
mode_mixed // 5 bits
mode_punct // 5 bits
)
var (
// The Latch Table shows, for each pair of Modes, the optimal method for
// getting from one mode to another. In the worst possible case, this can
// be up to 14 bits. In the best possible case, we are already there!
// The high half-word of each entry gives the number of bits.
// The low half-word of each entry are the actual bits necessary to change
latchTable = map[encodingMode]map[encodingMode]int{
mode_upper: {
mode_upper: 0,
mode_lower: (5 << 16) + 28,
mode_digit: (5 << 16) + 30,
mode_mixed: (5 << 16) + 29,
mode_punct: (10 << 16) + (29 << 5) + 30,
},
mode_lower: {
mode_upper: (9 << 16) + (30 << 4) + 14,
mode_lower: 0,
mode_digit: (5 << 16) + 30,
mode_mixed: (5 << 16) + 29,
mode_punct: (10 << 16) + (29 << 5) + 30,
},
mode_digit: {
mode_upper: (4 << 16) + 14,
mode_lower: (9 << 16) + (14 << 5) + 28,
mode_digit: 0,
mode_mixed: (9 << 16) + (14 << 5) + 29,
mode_punct: (14 << 16) + (14 << 10) + (29 << 5) + 30,
},
mode_mixed: {
mode_upper: (5 << 16) + 29,
mode_lower: (5 << 16) + 28,
mode_digit: (10 << 16) + (29 << 5) + 30,
mode_mixed: 0,
mode_punct: (5 << 16) + 30,
},
mode_punct: {
mode_upper: (5 << 16) + 31,
mode_lower: (10 << 16) + (31 << 5) + 28,
mode_digit: (10 << 16) + (31 << 5) + 30,
mode_mixed: (10 << 16) + (31 << 5) + 29,
mode_punct: 0,
},
}
// A map showing the available shift codes. (The shifts to BINARY are not shown)
shiftTable = map[encodingMode]map[encodingMode]int{
mode_upper: {
mode_punct: 0,
},
mode_lower: {
mode_punct: 0,
mode_upper: 28,
},
mode_mixed: {
mode_punct: 0,
},
mode_digit: {
mode_punct: 0,
mode_upper: 15,
},
}
charMap map[encodingMode][]int
)
type state struct {
mode encodingMode
tokens token
bShiftByteCount int
bitCount int
}
type stateSlice []*state
var initialState *state = &state{
mode: mode_upper,
tokens: nil,
bShiftByteCount: 0,
bitCount: 0,
}
func init() {
charMap = make(map[encodingMode][]int)
charMap[mode_upper] = make([]int, 256)
charMap[mode_lower] = make([]int, 256)
charMap[mode_digit] = make([]int, 256)
charMap[mode_mixed] = make([]int, 256)
charMap[mode_punct] = make([]int, 256)
charMap[mode_upper][' '] = 1
for c := 'A'; c <= 'Z'; c++ {
charMap[mode_upper][int(c)] = int(c - 'A' + 2)
}
charMap[mode_lower][' '] = 1
for c := 'a'; c <= 'z'; c++ {
charMap[mode_lower][c] = int(c - 'a' + 2)
}
charMap[mode_digit][' '] = 1
for c := '0'; c <= '9'; c++ {
charMap[mode_digit][c] = int(c - '0' + 2)
}
charMap[mode_digit][','] = 12
charMap[mode_digit]['.'] = 13
mixedTable := []int{
0, ' ', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 27, 28, 29, 30, 31, '@', '\\', '^',
'_', '`', '|', '~', 127,
}
for i, v := range mixedTable {
charMap[mode_mixed][v] = i
}
punctTable := []int{
0, '\r', 0, 0, 0, 0, '!', '\'', '#', '$', '%', '&', '\'',
'(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?',
'[', ']', '{', '}',
}
for i, v := range punctTable {
if v > 0 {
charMap[mode_punct][v] = i
}
}
}
func (em encodingMode) BitCount() byte {
if em == mode_digit {
return 4
}
return 5
}
// Create a new state representing this state with a latch to a (not
// necessary different) mode, and then a code.
func (s *state) latchAndAppend(mode encodingMode, value int) *state {
bitCount := s.bitCount
tokens := s.tokens
if mode != s.mode {
latch := latchTable[s.mode][mode]
tokens = newSimpleToken(tokens, latch&0xFFFF, byte(latch>>16))
bitCount += latch >> 16
}
tokens = newSimpleToken(tokens, value, mode.BitCount())
return &state{
mode: mode,
tokens: tokens,
bShiftByteCount: 0,
bitCount: bitCount + int(mode.BitCount()),
}
}
// Create a new state representing this state, with a temporary shift
// to a different mode to output a single value.
func (s *state) shiftAndAppend(mode encodingMode, value int) *state {
tokens := s.tokens
// Shifts exist only to UPPER and PUNCT, both with tokens size 5.
tokens = newSimpleToken(tokens, shiftTable[s.mode][mode], s.mode.BitCount())
tokens = newSimpleToken(tokens, value, 5)
return &state{
mode: s.mode,
tokens: tokens,
bShiftByteCount: 0,
bitCount: s.bitCount + int(s.mode.BitCount()) + 5,
}
}
// Create a new state representing this state, but an additional character
// output in Binary Shift mode.
func (s *state) addBinaryShiftChar(index int) *state {
tokens := s.tokens
mode := s.mode
bitCnt := s.bitCount
if s.mode == mode_punct || s.mode == mode_digit {
latch := latchTable[s.mode][mode_upper]
tokens = newSimpleToken(tokens, latch&0xFFFF, byte(latch>>16))
bitCnt += latch >> 16
mode = mode_upper
}
deltaBitCount := 8
if s.bShiftByteCount == 0 || s.bShiftByteCount == 31 {
deltaBitCount = 18
} else if s.bShiftByteCount == 62 {
deltaBitCount = 9
}
result := &state{
mode: mode,
tokens: tokens,
bShiftByteCount: s.bShiftByteCount + 1,
bitCount: bitCnt + deltaBitCount,
}
if result.bShiftByteCount == 2047+31 {
// The string is as long as it's allowed to be. We should end it.
result = result.endBinaryShift(index + 1)
}
return result
}
// Create the state identical to this one, but we are no longer in
// Binary Shift mode.
func (s *state) endBinaryShift(index int) *state {
if s.bShiftByteCount == 0 {
return s
}
tokens := newShiftToken(s.tokens, index-s.bShiftByteCount, s.bShiftByteCount)
return &state{
mode: s.mode,
tokens: tokens,
bShiftByteCount: 0,
bitCount: s.bitCount,
}
}
// Returns true if "this" state is better (or equal) to be in than "that"
// state under all possible circumstances.
func (this *state) isBetterThanOrEqualTo(other *state) bool {
mySize := this.bitCount + (latchTable[this.mode][other.mode] >> 16)
if other.bShiftByteCount > 0 && (this.bShiftByteCount == 0 || this.bShiftByteCount > other.bShiftByteCount) {
mySize += 10 // Cost of entering Binary Shift mode.
}
return mySize <= other.bitCount
}
func (s *state) toBitList(text []byte) *utils.BitList {
tokens := make([]token, 0)
se := s.endBinaryShift(len(text))
for t := se.tokens; t != nil; t = t.prev() {
tokens = append(tokens, t)
}
res := new(utils.BitList)
for i := len(tokens) - 1; i >= 0; i-- {
tokens[i].appendTo(res, text)
}
return res
}
func (s *state) String() string {
tokens := make([]token, 0)
for t := s.tokens; t != nil; t = t.prev() {
tokens = append([]token{t}, tokens...)
}
return fmt.Sprintf("M:%d bits=%d bytes=%d: %v", s.mode, s.bitCount, s.bShiftByteCount, tokens)
}

75
vendor/github.com/boombuler/barcode/aztec/token.go generated vendored Normal file
View File

@@ -0,0 +1,75 @@
package aztec
import (
"fmt"
"github.com/boombuler/barcode/utils"
)
type token interface {
fmt.Stringer
prev() token
appendTo(bits *utils.BitList, text []byte)
}
type simpleToken struct {
token
value int
bitCount byte
}
type binaryShiftToken struct {
token
bShiftStart int
bShiftByteCnt int
}
func newSimpleToken(prev token, value int, bitCount byte) token {
return &simpleToken{prev, value, bitCount}
}
func newShiftToken(prev token, bShiftStart int, bShiftCnt int) token {
return &binaryShiftToken{prev, bShiftStart, bShiftCnt}
}
func (st *simpleToken) prev() token {
return st.token
}
func (st *simpleToken) appendTo(bits *utils.BitList, text []byte) {
bits.AddBits(st.value, st.bitCount)
}
func (st *simpleToken) String() string {
value := st.value & ((1 << st.bitCount) - 1)
value |= 1 << st.bitCount
return "<" + fmt.Sprintf("%b", value)[1:] + ">"
}
func (bst *binaryShiftToken) prev() token {
return bst.token
}
func (bst *binaryShiftToken) appendTo(bits *utils.BitList, text []byte) {
for i := 0; i < bst.bShiftByteCnt; i++ {
if i == 0 || (i == 31 && bst.bShiftByteCnt <= 62) {
// We need a header before the first character, and before
// character 31 when the total byte code is <= 62
bits.AddBits(31, 5) // BINARY_SHIFT
if bst.bShiftByteCnt > 62 {
bits.AddBits(bst.bShiftByteCnt-31, 16)
} else if i == 0 {
// 1 <= binaryShiftByteCode <= 62
if bst.bShiftByteCnt < 31 {
bits.AddBits(bst.bShiftByteCnt, 5)
} else {
bits.AddBits(31, 5)
}
} else {
// 32 <= binaryShiftCount <= 62 and i == 31
bits.AddBits(bst.bShiftByteCnt-31, 5)
}
}
bits.AddByte(text[bst.bShiftStart+i])
}
}
func (bst *binaryShiftToken) String() string {
return fmt.Sprintf("<%d::%d>", bst.bShiftStart, (bst.bShiftStart + bst.bShiftByteCnt - 1))
}

42
vendor/github.com/boombuler/barcode/barcode.go generated vendored Normal file
View File

@@ -0,0 +1,42 @@
package barcode
import "image"
const (
TypeAztec = "Aztec"
TypeCodabar = "Codabar"
TypeCode128 = "Code 128"
TypeCode39 = "Code 39"
TypeCode93 = "Code 93"
TypeDataMatrix = "DataMatrix"
TypeEAN8 = "EAN 8"
TypeEAN13 = "EAN 13"
TypePDF = "PDF417"
TypeQR = "QR Code"
Type2of5 = "2 of 5"
Type2of5Interleaved = "2 of 5 (interleaved)"
)
// Contains some meta information about a barcode
type Metadata struct {
// the name of the barcode kind
CodeKind string
// contains 1 for 1D barcodes or 2 for 2D barcodes
Dimensions byte
}
// a rendered and encoded barcode
type Barcode interface {
image.Image
// returns some meta information about the barcode
Metadata() Metadata
// the data that was encoded in this barcode
Content() string
}
// Additional interface that some barcodes might implement to provide
// the value of its checksum.
type BarcodeIntCS interface {
Barcode
CheckSum() int
}

49
vendor/github.com/boombuler/barcode/codabar/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,49 @@
// Package codabar can create Codabar barcodes
package codabar
import (
"fmt"
"regexp"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
var encodingTable = map[rune][]bool{
'0': []bool{true, false, true, false, true, false, false, true, true},
'1': []bool{true, false, true, false, true, true, false, false, true},
'2': []bool{true, false, true, false, false, true, false, true, true},
'3': []bool{true, true, false, false, true, false, true, false, true},
'4': []bool{true, false, true, true, false, true, false, false, true},
'5': []bool{true, true, false, true, false, true, false, false, true},
'6': []bool{true, false, false, true, false, true, false, true, true},
'7': []bool{true, false, false, true, false, true, true, false, true},
'8': []bool{true, false, false, true, true, false, true, false, true},
'9': []bool{true, true, false, true, false, false, true, false, true},
'-': []bool{true, false, true, false, false, true, true, false, true},
'$': []bool{true, false, true, true, false, false, true, false, true},
':': []bool{true, true, false, true, false, true, true, false, true, true},
'/': []bool{true, true, false, true, true, false, true, false, true, true},
'.': []bool{true, true, false, true, true, false, true, true, false, true},
'+': []bool{true, false, true, true, false, false, true, true, false, false, true, true},
'A': []bool{true, false, true, true, false, false, true, false, false, true},
'B': []bool{true, false, true, false, false, true, false, false, true, true},
'C': []bool{true, false, false, true, false, false, true, false, true, true},
'D': []bool{true, false, true, false, false, true, true, false, false, true},
}
// Encode creates a codabar barcode for the given content
func Encode(content string) (barcode.Barcode, error) {
checkValid, _ := regexp.Compile(`[ABCD][0123456789\-\$\:/\.\+]*[ABCD]$`)
if content == "!" || checkValid.ReplaceAllString(content, "!") != "!" {
return nil, fmt.Errorf("can not encode \"%s\"", content)
}
resBits := new(utils.BitList)
for i, r := range content {
if i > 0 {
resBits.AddBit(false)
}
resBits.AddBit(encodingTable[r]...)
}
return utils.New1DCode(barcode.TypeCodabar, content, resBits), nil
}

View File

@@ -0,0 +1,32 @@
package codabar
import (
"image/color"
"testing"
)
func Test_Encode(t *testing.T) {
_, err := Encode("FOOBAR")
if err == nil {
t.Error("\"FOOBAR\" should not be encodable")
}
testEncode := func(txt, testResult string) {
code, err := Encode(txt)
if err != nil || code == nil {
t.Fail()
} else {
if code.Bounds().Max.X != len(testResult) {
t.Errorf("%v: length missmatch", txt)
} else {
for i, r := range testResult {
if (code.At(i, 0) == color.Black) != (r == '1') {
t.Errorf("%v: code missmatch on position %d", txt, i)
}
}
}
}
}
testEncode("A40156B", "10110010010101101001010101001101010110010110101001010010101101010010011")
}

203
vendor/github.com/boombuler/barcode/code128/encode.go generated vendored Normal file
View File

@@ -0,0 +1,203 @@
// Package code128 can create Code128 barcodes
package code128
import (
"fmt"
"strings"
"unicode/utf8"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
func strToRunes(str string) []rune {
result := make([]rune, utf8.RuneCountInString(str))
i := 0
for _, r := range str {
result[i] = r
i++
}
return result
}
func shouldUseCTable(nextRunes []rune, curEncoding byte) bool {
requiredDigits := 4
if curEncoding == startCSymbol {
requiredDigits = 2
}
if len(nextRunes) < requiredDigits {
return false
}
for i := 0; i < requiredDigits; i++ {
if i%2 == 0 && nextRunes[i] == FNC1 {
requiredDigits++
if len(nextRunes) < requiredDigits {
return false
}
continue
}
if nextRunes[i] < '0' || nextRunes[i] > '9' {
return false
}
}
return true
}
func tableContainsRune(table string, r rune) bool {
return strings.ContainsRune(table, r) || r == FNC1 || r == FNC2 || r == FNC3 || r == FNC4
}
func shouldUseATable(nextRunes []rune, curEncoding byte) bool {
nextRune := nextRunes[0]
if !tableContainsRune(bTable, nextRune) || curEncoding == startASymbol {
return tableContainsRune(aTable, nextRune)
}
if curEncoding == 0 {
for _, r := range nextRunes {
if tableContainsRune(abTable, r) {
continue
}
if strings.ContainsRune(aOnlyTable, r) {
return true
}
break
}
}
return false
}
func getCodeIndexList(content []rune) *utils.BitList {
result := new(utils.BitList)
curEncoding := byte(0)
for i := 0; i < len(content); i++ {
if shouldUseCTable(content[i:], curEncoding) {
if curEncoding != startCSymbol {
if curEncoding == byte(0) {
result.AddByte(startCSymbol)
} else {
result.AddByte(codeCSymbol)
}
curEncoding = startCSymbol
}
if content[i] == FNC1 {
result.AddByte(102)
} else {
idx := (content[i] - '0') * 10
i++
idx = idx + (content[i] - '0')
result.AddByte(byte(idx))
}
} else if shouldUseATable(content[i:], curEncoding) {
if curEncoding != startASymbol {
if curEncoding == byte(0) {
result.AddByte(startASymbol)
} else {
result.AddByte(codeASymbol)
}
curEncoding = startASymbol
}
var idx int
switch content[i] {
case FNC1:
idx = 102
break
case FNC2:
idx = 97
break
case FNC3:
idx = 96
break
case FNC4:
idx = 101
break
default:
idx = strings.IndexRune(aTable, content[i])
break
}
if idx < 0 {
return nil
}
result.AddByte(byte(idx))
} else {
if curEncoding != startBSymbol {
if curEncoding == byte(0) {
result.AddByte(startBSymbol)
} else {
result.AddByte(codeBSymbol)
}
curEncoding = startBSymbol
}
var idx int
switch content[i] {
case FNC1:
idx = 102
break
case FNC2:
idx = 97
break
case FNC3:
idx = 96
break
case FNC4:
idx = 100
break
default:
idx = strings.IndexRune(bTable, content[i])
break
}
if idx < 0 {
return nil
}
result.AddByte(byte(idx))
}
}
return result
}
// Encode creates a Code 128 barcode for the given content
func Encode(content string) (barcode.BarcodeIntCS, error) {
contentRunes := strToRunes(content)
if len(contentRunes) <= 0 || len(contentRunes) > 80 {
return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes))
}
idxList := getCodeIndexList(contentRunes)
if idxList == nil {
return nil, fmt.Errorf("\"%s\" could not be encoded", content)
}
result := new(utils.BitList)
sum := 0
for i, idx := range idxList.GetBytes() {
if i == 0 {
sum = int(idx)
} else {
sum += i * int(idx)
}
result.AddBit(encodingTable[idx]...)
}
sum = sum % 103
result.AddBit(encodingTable[sum]...)
result.AddBit(encodingTable[stopSymbol]...)
return utils.New1DCodeIntCheckSum(barcode.TypeCode128, content, result, sum), nil
}
func EncodeWithoutChecksum(content string) (barcode.Barcode, error) {
contentRunes := strToRunes(content)
if len(contentRunes) <= 0 || len(contentRunes) > 80 {
return nil, fmt.Errorf("content length should be between 1 and 80 runes but got %d", len(contentRunes))
}
idxList := getCodeIndexList(contentRunes)
if idxList == nil {
return nil, fmt.Errorf("\"%s\" could not be encoded", content)
}
result := new(utils.BitList)
for _, idx := range idxList.GetBytes() {
result.AddBit(encodingTable[idx]...)
}
result.AddBit(encodingTable[stopSymbol]...)
return utils.New1DCode(barcode.TypeCode128, content, result), nil
}

View File

@@ -0,0 +1,131 @@
package code128
import (
"image/color"
"testing"
)
func testEncode(t *testing.T, txt, testResult string) {
code, err := Encode(txt)
if err != nil || code == nil {
t.Error(err)
} else {
if code.Bounds().Max.X != len(testResult) {
t.Errorf("%v: length missmatch. Got %d expected %d", txt, code.Bounds().Max.X, len(testResult))
} else {
encoded := ""
failed := false
for i, r := range testResult {
if code.At(i, 0) == color.Black {
encoded += "1"
} else {
encoded += "0"
}
if (code.At(i, 0) == color.Black) != (r == '1') {
failed = true
t.Errorf("%v: code missmatch on position %d", txt, i)
}
}
if failed {
t.Log("Encoded: ", encoded)
}
}
}
}
func Test_EncodeFunctionChars(t *testing.T) {
encFNC1 := "11110101110"
encFNC2 := "11110101000"
encFNC3 := "10111100010"
encFNC4 := "10111101110"
encStartB := "11010010000"
encStop := "1100011101011"
// Special Case FC1 can also be encoded to C Table therefor using 123 as suffix might have unexpected results.
testEncode(t, string(FNC1)+"A23", encStartB+encFNC1+"10100011000"+"11001110010"+"11001011100"+"10100011110"+encStop)
testEncode(t, string(FNC2)+"123", encStartB+encFNC2+"10011100110"+"11001110010"+"11001011100"+"11100010110"+encStop)
testEncode(t, string(FNC3)+"123", encStartB+encFNC3+"10011100110"+"11001110010"+"11001011100"+"11101000110"+encStop)
testEncode(t, string(FNC4)+"123", encStartB+encFNC4+"10011100110"+"11001110010"+"11001011100"+"11100011010"+encStop)
}
func Test_Unencodable(t *testing.T) {
if _, err := Encode(""); err == nil {
t.Fail()
}
if _, err := Encode("ä"); err == nil {
t.Fail()
}
}
func Test_EncodeCTable(t *testing.T) {
testEncode(t, "HI345678H", "110100100001100010100011000100010101110111101000101100011100010110110000101001011110111011000101000111011000101100011101011")
testEncode(t, "334455", "11010011100101000110001000110111011101000110100100111101100011101011")
testEncode(t, string(FNC1)+"1234",
"11010011100"+ // Start C
"11110101110"+ // FNC1
"10110011100"+ // 12
"10001011000"+ // 34
"11101001100"+ // CheckSum == 24
"1100011101011") // Stop
}
func Test_shouldUseCTable(t *testing.T) {
if !shouldUseCTable([]rune{FNC1, '1', '2'}, startCSymbol) {
t.Error("[FNC1]12 failed")
}
if shouldUseCTable([]rune{FNC1, '1'}, startCSymbol) {
t.Error("[FNC1]1 failed")
}
if shouldUseCTable([]rune{'0', FNC1, '1'}, startCSymbol) {
t.Error("0[FNC1]1 failed")
}
if !shouldUseCTable([]rune{'0', '1', FNC1, '2', '3'}, startBSymbol) {
t.Error("01[FNC1]23 failed")
}
if shouldUseCTable([]rune{'0', '1', FNC1}, startBSymbol) {
t.Error("01[FNC1] failed")
}
}
func Test_Issue16(t *testing.T) {
if !shouldUseATable([]rune{'\r', 'A'}, 0) {
t.Error("Code should start with A-Table if the text start with \\r")
}
if !shouldUseATable([]rune{FNC1, '\r'}, 0) {
t.Error("Code should start with A-Table if the text start with <FNC1>\\r")
}
if shouldUseATable([]rune{FNC1, '1', '2', '3'}, 0) {
t.Error("Code should not start with A-Table if the text start with <FNC1>123")
}
testEncode(t, string(FNC3)+"$P\rI", "110100001001011110001010010001100111011101101111011101011000100010110001010001100011101011")
}
func Test_Datalogic(t *testing.T) {
// <Start A><FNC3>$P\r<checksum><STOP>
testEncode(t, string(FNC3)+"$P\r",
"11010000100"+ // <Start A>
"10111100010"+ // <FNC3>
"10010001100"+ // $
"11101110110"+ // P
"11110111010"+ // CR
"11000100010"+ // checksum = 'I'
"1100011101011") // STOP
// <Start B><FNC3>$P,Ae,P<CR><checksum><STOP>
testEncode(t, string(FNC3)+"$P,Ae,P\r",
"11010010000"+ // <Start B>
"10111100010"+ // <FNC3>
"10010001100"+ // $
"11101110110"+ // P
"10110011100"+ // ,
"10100011000"+ // A
"10110010000"+ // e
"10110011100"+ // ,
"11101110110"+ // P
"11101011110"+ // <Code A>
"11110111010"+ // <CR>
"10110001000"+ // checksum = 'D'
"1100011101011") // STOP
}

View File

@@ -0,0 +1,143 @@
package code128
var encodingTable = [107][]bool{
[]bool{true, true, false, true, true, false, false, true, true, false, false},
[]bool{true, true, false, false, true, true, false, true, true, false, false},
[]bool{true, true, false, false, true, true, false, false, true, true, false},
[]bool{true, false, false, true, false, false, true, true, false, false, false},
[]bool{true, false, false, true, false, false, false, true, true, false, false},
[]bool{true, false, false, false, true, false, false, true, true, false, false},
[]bool{true, false, false, true, true, false, false, true, false, false, false},
[]bool{true, false, false, true, true, false, false, false, true, false, false},
[]bool{true, false, false, false, true, true, false, false, true, false, false},
[]bool{true, true, false, false, true, false, false, true, false, false, false},
[]bool{true, true, false, false, true, false, false, false, true, false, false},
[]bool{true, true, false, false, false, true, false, false, true, false, false},
[]bool{true, false, true, true, false, false, true, true, true, false, false},
[]bool{true, false, false, true, true, false, true, true, true, false, false},
[]bool{true, false, false, true, true, false, false, true, true, true, false},
[]bool{true, false, true, true, true, false, false, true, true, false, false},
[]bool{true, false, false, true, true, true, false, true, true, false, false},
[]bool{true, false, false, true, true, true, false, false, true, true, false},
[]bool{true, true, false, false, true, true, true, false, false, true, false},
[]bool{true, true, false, false, true, false, true, true, true, false, false},
[]bool{true, true, false, false, true, false, false, true, true, true, false},
[]bool{true, true, false, true, true, true, false, false, true, false, false},
[]bool{true, true, false, false, true, true, true, false, true, false, false},
[]bool{true, true, true, false, true, true, false, true, true, true, false},
[]bool{true, true, true, false, true, false, false, true, true, false, false},
[]bool{true, true, true, false, false, true, false, true, true, false, false},
[]bool{true, true, true, false, false, true, false, false, true, true, false},
[]bool{true, true, true, false, true, true, false, false, true, false, false},
[]bool{true, true, true, false, false, true, true, false, true, false, false},
[]bool{true, true, true, false, false, true, true, false, false, true, false},
[]bool{true, true, false, true, true, false, true, true, false, false, false},
[]bool{true, true, false, true, true, false, false, false, true, true, false},
[]bool{true, true, false, false, false, true, true, false, true, true, false},
[]bool{true, false, true, false, false, false, true, true, false, false, false},
[]bool{true, false, false, false, true, false, true, true, false, false, false},
[]bool{true, false, false, false, true, false, false, false, true, true, false},
[]bool{true, false, true, true, false, false, false, true, false, false, false},
[]bool{true, false, false, false, true, true, false, true, false, false, false},
[]bool{true, false, false, false, true, true, false, false, false, true, false},
[]bool{true, true, false, true, false, false, false, true, false, false, false},
[]bool{true, true, false, false, false, true, false, true, false, false, false},
[]bool{true, true, false, false, false, true, false, false, false, true, false},
[]bool{true, false, true, true, false, true, true, true, false, false, false},
[]bool{true, false, true, true, false, false, false, true, true, true, false},
[]bool{true, false, false, false, true, true, false, true, true, true, false},
[]bool{true, false, true, true, true, false, true, true, false, false, false},
[]bool{true, false, true, true, true, false, false, false, true, true, false},
[]bool{true, false, false, false, true, true, true, false, true, true, false},
[]bool{true, true, true, false, true, true, true, false, true, true, false},
[]bool{true, true, false, true, false, false, false, true, true, true, false},
[]bool{true, true, false, false, false, true, false, true, true, true, false},
[]bool{true, true, false, true, true, true, false, true, false, false, false},
[]bool{true, true, false, true, true, true, false, false, false, true, false},
[]bool{true, true, false, true, true, true, false, true, true, true, false},
[]bool{true, true, true, false, true, false, true, true, false, false, false},
[]bool{true, true, true, false, true, false, false, false, true, true, false},
[]bool{true, true, true, false, false, false, true, false, true, true, false},
[]bool{true, true, true, false, true, true, false, true, false, false, false},
[]bool{true, true, true, false, true, true, false, false, false, true, false},
[]bool{true, true, true, false, false, false, true, true, false, true, false},
[]bool{true, true, true, false, true, true, true, true, false, true, false},
[]bool{true, true, false, false, true, false, false, false, false, true, false},
[]bool{true, true, true, true, false, false, false, true, false, true, false},
[]bool{true, false, true, false, false, true, true, false, false, false, false},
[]bool{true, false, true, false, false, false, false, true, true, false, false},
[]bool{true, false, false, true, false, true, true, false, false, false, false},
[]bool{true, false, false, true, false, false, false, false, true, true, false},
[]bool{true, false, false, false, false, true, false, true, true, false, false},
[]bool{true, false, false, false, false, true, false, false, true, true, false},
[]bool{true, false, true, true, false, false, true, false, false, false, false},
[]bool{true, false, true, true, false, false, false, false, true, false, false},
[]bool{true, false, false, true, true, false, true, false, false, false, false},
[]bool{true, false, false, true, true, false, false, false, false, true, false},
[]bool{true, false, false, false, false, true, true, false, true, false, false},
[]bool{true, false, false, false, false, true, true, false, false, true, false},
[]bool{true, true, false, false, false, false, true, false, false, true, false},
[]bool{true, true, false, false, true, false, true, false, false, false, false},
[]bool{true, true, true, true, false, true, true, true, false, true, false},
[]bool{true, true, false, false, false, false, true, false, true, false, false},
[]bool{true, false, false, false, true, true, true, true, false, true, false},
[]bool{true, false, true, false, false, true, true, true, true, false, false},
[]bool{true, false, false, true, false, true, true, true, true, false, false},
[]bool{true, false, false, true, false, false, true, true, true, true, false},
[]bool{true, false, true, true, true, true, false, false, true, false, false},
[]bool{true, false, false, true, true, true, true, false, true, false, false},
[]bool{true, false, false, true, true, true, true, false, false, true, false},
[]bool{true, true, true, true, false, true, false, false, true, false, false},
[]bool{true, true, true, true, false, false, true, false, true, false, false},
[]bool{true, true, true, true, false, false, true, false, false, true, false},
[]bool{true, true, false, true, true, false, true, true, true, true, false},
[]bool{true, true, false, true, true, true, true, false, true, true, false},
[]bool{true, true, true, true, false, true, true, false, true, true, false},
[]bool{true, false, true, false, true, true, true, true, false, false, false},
[]bool{true, false, true, false, false, false, true, true, true, true, false},
[]bool{true, false, false, false, true, false, true, true, true, true, false},
[]bool{true, false, true, true, true, true, false, true, false, false, false},
[]bool{true, false, true, true, true, true, false, false, false, true, false},
[]bool{true, true, true, true, false, true, false, true, false, false, false},
[]bool{true, true, true, true, false, true, false, false, false, true, false},
[]bool{true, false, true, true, true, false, true, true, true, true, false},
[]bool{true, false, true, true, true, true, false, true, true, true, false},
[]bool{true, true, true, false, true, false, true, true, true, true, false},
[]bool{true, true, true, true, false, true, false, true, true, true, false},
[]bool{true, true, false, true, false, false, false, false, true, false, false},
[]bool{true, true, false, true, false, false, true, false, false, false, false},
[]bool{true, true, false, true, false, false, true, true, true, false, false},
[]bool{true, true, false, false, false, true, true, true, false, true, false, true, true},
}
const startASymbol byte = 103
const startBSymbol byte = 104
const startCSymbol byte = 105
const codeASymbol byte = 101
const codeBSymbol byte = 100
const codeCSymbol byte = 99
const stopSymbol byte = 106
const (
// FNC1 - Special Function 1
FNC1 = '\u00f1'
// FNC2 - Special Function 2
FNC2 = '\u00f2'
// FNC3 - Special Function 3
FNC3 = '\u00f3'
// FNC4 - Special Function 4
FNC4 = '\u00f4'
)
const abTable = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
const bTable = abTable + "`abcdefghijklmnopqrstuvwxyz{|}~\u007F"
const aOnlyTable = "\u0000\u0001\u0002\u0003\u0004" + // NUL, SOH, STX, ETX, EOT
"\u0005\u0006\u0007\u0008\u0009" + // ENQ, ACK, BEL, BS, HT
"\u000A\u000B\u000C\u000D\u000E" + // LF, VT, FF, CR, SO
"\u000F\u0010\u0011\u0012\u0013" + // SI, DLE, DC1, DC2, DC3
"\u0014\u0015\u0016\u0017\u0018" + // DC4, NAK, SYN, ETB, CAN
"\u0019\u001A\u001B\u001C\u001D" + // EM, SUB, ESC, FS, GS
"\u001E\u001F" // RS, US
const aTable = abTable + aOnlyTable

152
vendor/github.com/boombuler/barcode/code39/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,152 @@
// Package code39 can create Code39 barcodes
package code39
import (
"errors"
"strconv"
"strings"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type encodeInfo struct {
value int
data []bool
}
var encodeTable = map[rune]encodeInfo{
'0': encodeInfo{0, []bool{true, false, true, false, false, true, true, false, true, true, false, true}},
'1': encodeInfo{1, []bool{true, true, false, true, false, false, true, false, true, false, true, true}},
'2': encodeInfo{2, []bool{true, false, true, true, false, false, true, false, true, false, true, true}},
'3': encodeInfo{3, []bool{true, true, false, true, true, false, false, true, false, true, false, true}},
'4': encodeInfo{4, []bool{true, false, true, false, false, true, true, false, true, false, true, true}},
'5': encodeInfo{5, []bool{true, true, false, true, false, false, true, true, false, true, false, true}},
'6': encodeInfo{6, []bool{true, false, true, true, false, false, true, true, false, true, false, true}},
'7': encodeInfo{7, []bool{true, false, true, false, false, true, false, true, true, false, true, true}},
'8': encodeInfo{8, []bool{true, true, false, true, false, false, true, false, true, true, false, true}},
'9': encodeInfo{9, []bool{true, false, true, true, false, false, true, false, true, true, false, true}},
'A': encodeInfo{10, []bool{true, true, false, true, false, true, false, false, true, false, true, true}},
'B': encodeInfo{11, []bool{true, false, true, true, false, true, false, false, true, false, true, true}},
'C': encodeInfo{12, []bool{true, true, false, true, true, false, true, false, false, true, false, true}},
'D': encodeInfo{13, []bool{true, false, true, false, true, true, false, false, true, false, true, true}},
'E': encodeInfo{14, []bool{true, true, false, true, false, true, true, false, false, true, false, true}},
'F': encodeInfo{15, []bool{true, false, true, true, false, true, true, false, false, true, false, true}},
'G': encodeInfo{16, []bool{true, false, true, false, true, false, false, true, true, false, true, true}},
'H': encodeInfo{17, []bool{true, true, false, true, false, true, false, false, true, true, false, true}},
'I': encodeInfo{18, []bool{true, false, true, true, false, true, false, false, true, true, false, true}},
'J': encodeInfo{19, []bool{true, false, true, false, true, true, false, false, true, true, false, true}},
'K': encodeInfo{20, []bool{true, true, false, true, false, true, false, true, false, false, true, true}},
'L': encodeInfo{21, []bool{true, false, true, true, false, true, false, true, false, false, true, true}},
'M': encodeInfo{22, []bool{true, true, false, true, true, false, true, false, true, false, false, true}},
'N': encodeInfo{23, []bool{true, false, true, false, true, true, false, true, false, false, true, true}},
'O': encodeInfo{24, []bool{true, true, false, true, false, true, true, false, true, false, false, true}},
'P': encodeInfo{25, []bool{true, false, true, true, false, true, true, false, true, false, false, true}},
'Q': encodeInfo{26, []bool{true, false, true, false, true, false, true, true, false, false, true, true}},
'R': encodeInfo{27, []bool{true, true, false, true, false, true, false, true, true, false, false, true}},
'S': encodeInfo{28, []bool{true, false, true, true, false, true, false, true, true, false, false, true}},
'T': encodeInfo{29, []bool{true, false, true, false, true, true, false, true, true, false, false, true}},
'U': encodeInfo{30, []bool{true, true, false, false, true, false, true, false, true, false, true, true}},
'V': encodeInfo{31, []bool{true, false, false, true, true, false, true, false, true, false, true, true}},
'W': encodeInfo{32, []bool{true, true, false, false, true, true, false, true, false, true, false, true}},
'X': encodeInfo{33, []bool{true, false, false, true, false, true, true, false, true, false, true, true}},
'Y': encodeInfo{34, []bool{true, true, false, false, true, false, true, true, false, true, false, true}},
'Z': encodeInfo{35, []bool{true, false, false, true, true, false, true, true, false, true, false, true}},
'-': encodeInfo{36, []bool{true, false, false, true, false, true, false, true, true, false, true, true}},
'.': encodeInfo{37, []bool{true, true, false, false, true, false, true, false, true, true, false, true}},
' ': encodeInfo{38, []bool{true, false, false, true, true, false, true, false, true, true, false, true}},
'$': encodeInfo{39, []bool{true, false, false, true, false, false, true, false, false, true, false, true}},
'/': encodeInfo{40, []bool{true, false, false, true, false, false, true, false, true, false, false, true}},
'+': encodeInfo{41, []bool{true, false, false, true, false, true, false, false, true, false, false, true}},
'%': encodeInfo{42, []bool{true, false, true, false, false, true, false, false, true, false, false, true}},
'*': encodeInfo{-1, []bool{true, false, false, true, false, true, true, false, true, true, false, true}},
}
var extendedTable = map[rune]string{
0: `%U`, 1: `$A`, 2: `$B`, 3: `$C`, 4: `$D`, 5: `$E`, 6: `$F`, 7: `$G`, 8: `$H`, 9: `$I`, 10: `$J`,
11: `$K`, 12: `$L`, 13: `$M`, 14: `$N`, 15: `$O`, 16: `$P`, 17: `$Q`, 18: `$R`, 19: `$S`, 20: `$T`,
21: `$U`, 22: `$V`, 23: `$W`, 24: `$X`, 25: `$Y`, 26: `$Z`, 27: `%A`, 28: `%B`, 29: `%C`, 30: `%D`,
31: `%E`, 33: `/A`, 34: `/B`, 35: `/C`, 36: `/D`, 37: `/E`, 38: `/F`, 39: `/G`, 40: `/H`, 41: `/I`,
42: `/J`, 43: `/K`, 44: `/L`, 47: `/O`, 58: `/Z`, 59: `%F`, 60: `%G`, 61: `%H`, 62: `%I`, 63: `%J`,
64: `%V`, 91: `%K`, 92: `%L`, 93: `%M`, 94: `%N`, 95: `%O`, 96: `%W`, 97: `+A`, 98: `+B`, 99: `+C`,
100: `+D`, 101: `+E`, 102: `+F`, 103: `+G`, 104: `+H`, 105: `+I`, 106: `+J`, 107: `+K`, 108: `+L`,
109: `+M`, 110: `+N`, 111: `+O`, 112: `+P`, 113: `+Q`, 114: `+R`, 115: `+S`, 116: `+T`, 117: `+U`,
118: `+V`, 119: `+W`, 120: `+X`, 121: `+Y`, 122: `+Z`, 123: `%P`, 124: `%Q`, 125: `%R`, 126: `%S`,
127: `%T`,
}
func getChecksum(content string) string {
sum := 0
for _, r := range content {
info, ok := encodeTable[r]
if !ok || info.value < 0 {
return "#"
}
sum += info.value
}
sum = sum % 43
for r, v := range encodeTable {
if v.value == sum {
return string(r)
}
}
return "#"
}
func prepare(content string) (string, error) {
result := ""
for _, r := range content {
if r > 127 {
return "", errors.New("Only ASCII strings can be encoded")
}
val, ok := extendedTable[r]
if ok {
result += val
} else {
result += string([]rune{r})
}
}
return result, nil
}
// Encode returns a code39 barcode for the given content
// if includeChecksum is set to true, a checksum character is calculated and added to the content
func Encode(content string, includeChecksum bool, fullASCIIMode bool) (barcode.BarcodeIntCS, 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! try full ascii mode")
}
data := "*" + content
if includeChecksum {
data += getChecksum(content)
}
data += "*"
result := new(utils.BitList)
for i, r := range data {
if i != 0 {
result.AddBit(false)
}
info, ok := encodeTable[r]
if !ok {
return nil, errors.New("invalid data! try full ascii mode")
}
result.AddBit(info.data...)
}
checkSum, err := strconv.ParseInt(getChecksum(content), 10, 64)
if err != nil {
checkSum = 0
}
return utils.New1DCodeIntCheckSum(barcode.TypeCode39, content, result, int(checkSum)), nil
}

View File

@@ -0,0 +1,31 @@
package code39
import (
"image/color"
"testing"
)
func doTest(t *testing.T, addCS, fullASCII bool, data, testResult string) {
code, err := Encode(data, addCS, fullASCII)
if err != nil {
t.Error(err)
}
if len(testResult) != code.Bounds().Max.X {
t.Errorf("Invalid code size. Expected %d got %d", len(testResult), code.Bounds().Max.X)
}
for i, r := range testResult {
if (code.At(i, 0) == color.Black) != (r == '1') {
t.Errorf("Failed at position %d", i)
}
}
}
func Test_Encode(t *testing.T) {
doTest(t, false, false, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
"1001011011010110101001011010110100101101101101001010101011001011011010110010101"+
"011011001010101010011011011010100110101011010011010101011001101011010101001101011010"+
"100110110110101001010101101001101101011010010101101101001010101011001101101010110010"+
"101101011001010101101100101100101010110100110101011011001101010101001011010110110010"+
"110101010011011010101010011011010110100101011010110010101101101100101010101001101011"+
"011010011010101011001101010101001011011011010010110101011001011010100101101101")
}

131
vendor/github.com/boombuler/barcode/code93/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,131 @@
// 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
// 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) {
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))
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.New1DCode(barcode.TypeCode93, content, result), nil
}
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 ' '
}

View File

@@ -0,0 +1,39 @@
package code93
import (
"image/color"
"testing"
)
func doTest(t *testing.T, data, testResult string) {
code, err := Encode(data, true, false)
if err != nil {
t.Error(err)
}
if len(testResult) != code.Bounds().Max.X {
t.Errorf("Invalid code size. Expected %d got %d", len(testResult), code.Bounds().Max.X)
}
for i, r := range testResult {
if (code.At(i, 0) == color.Black) != (r == '1') {
t.Errorf("Failed at position %d", i)
}
}
}
func Test_CheckSum(t *testing.T) {
if r := getChecksum("TEST93", 20); r != '+' {
t.Errorf("Checksum C-Failed. Got %s", string(r))
}
if r := getChecksum("TEST93+", 15); r != '6' {
t.Errorf("Checksum K-Failed. Got %s", string(r))
}
}
func Test_Encode(t *testing.T) {
doTest(t, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
"1010111101101010001101001001101000101100101001100100101100010101011010001011001"+
"001011000101001101001000110101010110001010011001010001101001011001000101101101101001"+
"101100101101011001101001101100101101100110101011011001011001101001101101001110101000"+
"101001010010001010001001010000101001010001001001001001000101010100001000100101000010"+
"101001110101010000101010111101")
}

View File

@@ -0,0 +1,213 @@
package datamatrix
import (
"github.com/boombuler/barcode/utils"
"strconv"
)
type setValFunc func(byte)
type codeLayout struct {
matrix *utils.BitList
occupy *utils.BitList
size *dmCodeSize
}
func newCodeLayout(size *dmCodeSize) *codeLayout {
result := new(codeLayout)
result.matrix = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
result.occupy = utils.NewBitList(size.MatrixColumns() * size.MatrixRows())
result.size = size
return result
}
func (l *codeLayout) Occupied(row, col int) bool {
return l.occupy.GetBit(col + row*l.size.MatrixColumns())
}
func (l *codeLayout) Set(row, col int, value, bitNum byte) {
val := ((value >> (7 - bitNum)) & 1) == 1
if row < 0 {
row += l.size.MatrixRows()
col += 4 - ((l.size.MatrixRows() + 4) % 8)
}
if col < 0 {
col += l.size.MatrixColumns()
row += 4 - ((l.size.MatrixColumns() + 4) % 8)
}
if l.Occupied(row, col) {
panic("Field already occupied row: " + strconv.Itoa(row) + " col: " + strconv.Itoa(col))
}
l.occupy.SetBit(col+row*l.size.MatrixColumns(), true)
l.matrix.SetBit(col+row*l.size.MatrixColumns(), val)
}
func (l *codeLayout) SetSimple(row, col int, value byte) {
l.Set(row-2, col-2, value, 0)
l.Set(row-2, col-1, value, 1)
l.Set(row-1, col-2, value, 2)
l.Set(row-1, col-1, value, 3)
l.Set(row-1, col-0, value, 4)
l.Set(row-0, col-2, value, 5)
l.Set(row-0, col-1, value, 6)
l.Set(row-0, col-0, value, 7)
}
func (l *codeLayout) Corner1(value byte) {
l.Set(l.size.MatrixRows()-1, 0, value, 0)
l.Set(l.size.MatrixRows()-1, 1, value, 1)
l.Set(l.size.MatrixRows()-1, 2, value, 2)
l.Set(0, l.size.MatrixColumns()-2, value, 3)
l.Set(0, l.size.MatrixColumns()-1, value, 4)
l.Set(1, l.size.MatrixColumns()-1, value, 5)
l.Set(2, l.size.MatrixColumns()-1, value, 6)
l.Set(3, l.size.MatrixColumns()-1, value, 7)
}
func (l *codeLayout) Corner2(value byte) {
l.Set(l.size.MatrixRows()-3, 0, value, 0)
l.Set(l.size.MatrixRows()-2, 0, value, 1)
l.Set(l.size.MatrixRows()-1, 0, value, 2)
l.Set(0, l.size.MatrixColumns()-4, value, 3)
l.Set(0, l.size.MatrixColumns()-3, value, 4)
l.Set(0, l.size.MatrixColumns()-2, value, 5)
l.Set(0, l.size.MatrixColumns()-1, value, 6)
l.Set(1, l.size.MatrixColumns()-1, value, 7)
}
func (l *codeLayout) Corner3(value byte) {
l.Set(l.size.MatrixRows()-3, 0, value, 0)
l.Set(l.size.MatrixRows()-2, 0, value, 1)
l.Set(l.size.MatrixRows()-1, 0, value, 2)
l.Set(0, l.size.MatrixColumns()-2, value, 3)
l.Set(0, l.size.MatrixColumns()-1, value, 4)
l.Set(1, l.size.MatrixColumns()-1, value, 5)
l.Set(2, l.size.MatrixColumns()-1, value, 6)
l.Set(3, l.size.MatrixColumns()-1, value, 7)
}
func (l *codeLayout) Corner4(value byte) {
l.Set(l.size.MatrixRows()-1, 0, value, 0)
l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, value, 1)
l.Set(0, l.size.MatrixColumns()-3, value, 2)
l.Set(0, l.size.MatrixColumns()-2, value, 3)
l.Set(0, l.size.MatrixColumns()-1, value, 4)
l.Set(1, l.size.MatrixColumns()-3, value, 5)
l.Set(1, l.size.MatrixColumns()-2, value, 6)
l.Set(1, l.size.MatrixColumns()-1, value, 7)
}
func (l *codeLayout) SetValues(data []byte) {
idx := 0
row := 4
col := 0
for (row < l.size.MatrixRows()) || (col < l.size.MatrixColumns()) {
if (row == l.size.MatrixRows()) && (col == 0) {
l.Corner1(data[idx])
idx++
}
if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%4 != 0) {
l.Corner2(data[idx])
idx++
}
if (row == l.size.MatrixRows()-2) && (col == 0) && (l.size.MatrixColumns()%8 == 4) {
l.Corner3(data[idx])
idx++
}
if (row == l.size.MatrixRows()+4) && (col == 2) && (l.size.MatrixColumns()%8 == 0) {
l.Corner4(data[idx])
idx++
}
for true {
if (row < l.size.MatrixRows()) && (col >= 0) && !l.Occupied(row, col) {
l.SetSimple(row, col, data[idx])
idx++
}
row -= 2
col += 2
if (row < 0) || (col >= l.size.MatrixColumns()) {
break
}
}
row += 1
col += 3
for true {
if (row >= 0) && (col < l.size.MatrixColumns()) && !l.Occupied(row, col) {
l.SetSimple(row, col, data[idx])
idx++
}
row += 2
col -= 2
if (row >= l.size.MatrixRows()) || (col < 0) {
break
}
}
row += 3
col += 1
}
if !l.Occupied(l.size.MatrixRows()-1, l.size.MatrixColumns()-1) {
l.Set(l.size.MatrixRows()-1, l.size.MatrixColumns()-1, 255, 0)
l.Set(l.size.MatrixRows()-2, l.size.MatrixColumns()-2, 255, 0)
}
}
func (l *codeLayout) Merge() *datamatrixCode {
result := newDataMatrixCode(l.size)
//dotted horizontal lines
for r := 0; r < l.size.Rows; r += (l.size.RegionRows() + 2) {
for c := 0; c < l.size.Columns; c += 2 {
result.set(c, r, true)
}
}
//solid horizontal line
for r := l.size.RegionRows() + 1; r < l.size.Rows; r += (l.size.RegionRows() + 2) {
for c := 0; c < l.size.Columns; c++ {
result.set(c, r, true)
}
}
//dotted vertical lines
for c := l.size.RegionColumns() + 1; c < l.size.Columns; c += (l.size.RegionColumns() + 2) {
for r := 1; r < l.size.Rows; r += 2 {
result.set(c, r, true)
}
}
//solid vertical line
for c := 0; c < l.size.Columns; c += (l.size.RegionColumns() + 2) {
for r := 0; r < l.size.Rows; r++ {
result.set(c, r, true)
}
}
count := 0
for hRegion := 0; hRegion < l.size.RegionCountHorizontal; hRegion++ {
for vRegion := 0; vRegion < l.size.RegionCountVertical; vRegion++ {
for x := 0; x < l.size.RegionColumns(); x++ {
colMatrix := (l.size.RegionColumns() * hRegion) + x
colResult := ((2 + l.size.RegionColumns()) * hRegion) + x + 1
for y := 0; y < l.size.RegionRows(); y++ {
rowMatrix := (l.size.RegionRows() * vRegion) + y
rowResult := ((2 + l.size.RegionRows()) * vRegion) + y + 1
val := l.matrix.GetBit(colMatrix + rowMatrix*l.size.MatrixColumns())
if val {
count++
}
result.set(colResult, rowResult, val)
}
}
}
}
return result
}

View File

@@ -0,0 +1,73 @@
package datamatrix
type dmCodeSize struct {
Rows int
Columns int
RegionCountHorizontal int
RegionCountVertical int
ECCCount int
BlockCount int
}
func (s *dmCodeSize) RegionRows() int {
return (s.Rows - (s.RegionCountHorizontal * 2)) / s.RegionCountHorizontal
}
func (s *dmCodeSize) RegionColumns() int {
return (s.Columns - (s.RegionCountVertical * 2)) / s.RegionCountVertical
}
func (s *dmCodeSize) MatrixRows() int {
return s.RegionRows() * s.RegionCountHorizontal
}
func (s *dmCodeSize) MatrixColumns() int {
return s.RegionColumns() * s.RegionCountVertical
}
func (s *dmCodeSize) DataCodewords() int {
return ((s.MatrixColumns() * s.MatrixRows()) / 8) - s.ECCCount
}
func (s *dmCodeSize) DataCodewordsForBlock(idx int) int {
if s.Rows == 144 && s.Columns == 144 {
// Special Case...
if idx < 8 {
return 156
} else {
return 155
}
}
return s.DataCodewords() / s.BlockCount
}
func (s *dmCodeSize) ErrorCorrectionCodewordsPerBlock() int {
return s.ECCCount / s.BlockCount
}
var codeSizes []*dmCodeSize = []*dmCodeSize{
&dmCodeSize{10, 10, 1, 1, 5, 1},
&dmCodeSize{12, 12, 1, 1, 7, 1},
&dmCodeSize{14, 14, 1, 1, 10, 1},
&dmCodeSize{16, 16, 1, 1, 12, 1},
&dmCodeSize{18, 18, 1, 1, 14, 1},
&dmCodeSize{20, 20, 1, 1, 18, 1},
&dmCodeSize{22, 22, 1, 1, 20, 1},
&dmCodeSize{24, 24, 1, 1, 24, 1},
&dmCodeSize{26, 26, 1, 1, 28, 1},
&dmCodeSize{32, 32, 2, 2, 36, 1},
&dmCodeSize{36, 36, 2, 2, 42, 1},
&dmCodeSize{40, 40, 2, 2, 48, 1},
&dmCodeSize{44, 44, 2, 2, 56, 1},
&dmCodeSize{48, 48, 2, 2, 68, 1},
&dmCodeSize{52, 52, 2, 2, 84, 2},
&dmCodeSize{64, 64, 4, 4, 112, 2},
&dmCodeSize{72, 72, 4, 4, 144, 4},
&dmCodeSize{80, 80, 4, 4, 192, 4},
&dmCodeSize{88, 88, 4, 4, 224, 4},
&dmCodeSize{96, 96, 4, 4, 272, 4},
&dmCodeSize{104, 104, 4, 4, 336, 6},
&dmCodeSize{120, 120, 6, 6, 408, 6},
&dmCodeSize{132, 132, 6, 6, 496, 8},
&dmCodeSize{144, 144, 6, 6, 620, 10},
}

View File

@@ -0,0 +1,102 @@
package datamatrix
import (
"bytes"
"testing"
)
func codeFromStr(str string, size *dmCodeSize) *datamatrixCode {
code := newDataMatrixCode(size)
idx := 0
for _, r := range str {
x := idx % size.Columns
y := idx / size.Columns
switch r {
case '#':
code.set(x, y, true)
case '.':
code.set(x, y, false)
default:
continue
}
idx++
}
return code
}
func Test_Issue12(t *testing.T) {
data := `{"po":12,"batchAction":"start_end"}`
realData := addPadding(encodeText(data), 36)
wantedData := []byte{124, 35, 113, 112, 35, 59, 142, 45, 35, 99, 98, 117, 100, 105, 66, 100, 117, 106, 112, 111, 35, 59, 35, 116, 117, 98, 115, 117, 96, 102, 111, 101, 35, 126, 129, 181}
if bytes.Compare(realData, wantedData) != 0 {
t.Error("Data Encoding failed")
return
}
var codeSize *dmCodeSize
for _, s := range codeSizes {
if s.DataCodewords() >= len(wantedData) {
codeSize = s
break
}
}
realECC := ec.calcECC(realData, codeSize)[len(realData):]
wantedECC := []byte{196, 53, 147, 192, 151, 213, 107, 61, 98, 251, 50, 71, 186, 15, 43, 111, 165, 243, 209, 79, 128, 109, 251, 4}
if bytes.Compare(realECC, wantedECC) != 0 {
t.Errorf("Error correction calculation failed\nGot: %v", realECC)
return
}
barcode := `
#.#.#.#.#.#.#.#.#.#.#.#.
#....###..#..#....#...##
##.......#...#.#.#....#.
#.###...##..#...##.##..#
##...####..##..#.#.#.##.
#.###.##.###..#######.##
#..###...##.##..#.##.##.
#.#.#.#.#.#.###....#.#.#
##.#...#.#.#..#...#####.
#...####..#...##..#.#..#
##...#...##.###.#.....#.
#.###.#.##.#.....###..##
##..#####...#..##...###.
###...#.####.##.#.#.#..#
#..###..#.#.####.#.###..
###.#.#..#..#.###.#.##.#
#####.##.###..#.####.#..
#.##.#......#.#..#.#.###
###.#....######.#...##..
##...#..##.###..#...####
#.######.###.##..#...##.
#..#..#.##.#..####...#.#
###.###..#..##.#.##...#.
########################`
bc, err := Encode(data)
if err != nil {
t.Error(err)
return
}
realResult := bc.(*datamatrixCode)
if realResult.Columns != 24 || realResult.Rows != 24 {
t.Errorf("Got wrong barcode size %dx%d", realResult.Columns, realResult.Rows)
return
}
wantedResult := codeFromStr(barcode, realResult.dmCodeSize)
for x := 0; x < wantedResult.Columns; x++ {
for y := 0; y < wantedResult.Rows; y++ {
r := realResult.get(x, y)
w := wantedResult.get(x, y)
if w != r {
t.Errorf("Failed at: c%d/r%d", x, y)
}
}
}
}

View File

@@ -0,0 +1,50 @@
package datamatrix
import (
"image"
"image/color"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type datamatrixCode struct {
*utils.BitList
*dmCodeSize
content string
}
func newDataMatrixCode(size *dmCodeSize) *datamatrixCode {
return &datamatrixCode{utils.NewBitList(size.Rows * size.Columns), size, ""}
}
func (c *datamatrixCode) Content() string {
return c.content
}
func (c *datamatrixCode) Metadata() barcode.Metadata {
return barcode.Metadata{barcode.TypeDataMatrix, 2}
}
func (c *datamatrixCode) ColorModel() color.Model {
return color.Gray16Model
}
func (c *datamatrixCode) Bounds() image.Rectangle {
return image.Rect(0, 0, c.Columns, c.Rows)
}
func (c *datamatrixCode) At(x, y int) color.Color {
if c.get(x, y) {
return color.Black
}
return color.White
}
func (c *datamatrixCode) get(x, y int) bool {
return c.GetBit(x*c.Rows + y)
}
func (c *datamatrixCode) set(x, y int, value bool) {
c.SetBit(x*c.Rows+y, value)
}

View File

@@ -0,0 +1,75 @@
// Package datamatrix can create Datamatrix barcodes
package datamatrix
import (
"errors"
"github.com/boombuler/barcode"
)
// Encode returns a Datamatrix barcode for the given content
func Encode(content string) (barcode.Barcode, error) {
data := encodeText(content)
var size *dmCodeSize
for _, s := range codeSizes {
if s.DataCodewords() >= len(data) {
size = s
break
}
}
if size == nil {
return nil, errors.New("to much data to encode")
}
data = addPadding(data, size.DataCodewords())
data = ec.calcECC(data, size)
code := render(data, size)
if code != nil {
code.content = content
return code, nil
}
return nil, errors.New("unable to render barcode")
}
func render(data []byte, size *dmCodeSize) *datamatrixCode {
cl := newCodeLayout(size)
cl.SetValues(data)
return cl.Merge()
}
func encodeText(content string) []byte {
var result []byte
input := []byte(content)
for i := 0; i < len(input); {
c := input[i]
i++
if c >= '0' && c <= '9' && i < len(input) && input[i] >= '0' && input[i] <= '9' {
// two numbers...
c2 := input[i]
i++
cw := byte(((c-'0')*10 + (c2 - '0')) + 130)
result = append(result, cw)
} else if c > 127 {
// not correct... needs to be redone later...
result = append(result, 235, c-127)
} else {
result = append(result, c+1)
}
}
return result
}
func addPadding(data []byte, toCount int) []byte {
if len(data) < toCount {
data = append(data, 129)
}
for len(data) < toCount {
R := ((149 * (len(data) + 1)) % 253) + 1
data = append(data, byte((129+R)%254))
}
return data
}

View File

@@ -0,0 +1,45 @@
package datamatrix
import (
"github.com/boombuler/barcode/utils"
)
type errorCorrection struct {
rs *utils.ReedSolomonEncoder
}
var ec *errorCorrection = newErrorCorrection()
func newErrorCorrection() *errorCorrection {
gf := utils.NewGaloisField(301, 256, 1)
return &errorCorrection{utils.NewReedSolomonEncoder(gf)}
}
func (ec *errorCorrection) calcECC(data []byte, size *dmCodeSize) []byte {
dataSize := len(data)
// make some space for error correction codes
data = append(data, make([]byte, size.ECCCount)...)
for block := 0; block < size.BlockCount; block++ {
dataCnt := size.DataCodewordsForBlock(block)
buff := make([]int, dataCnt)
// copy the data for the current block to buff
j := 0
for i := block; i < dataSize; i += size.BlockCount {
buff[j] = int(data[i])
j++
}
// calc the error correction codes
ecc := ec.rs.Encode(buff, size.ErrorCorrectionCodewordsPerBlock())
// and append them to the result
j = 0
for i := block; i < size.ErrorCorrectionCodewordsPerBlock()*size.BlockCount; i += size.BlockCount {
data[dataSize+i] = byte(ecc[j])
j++
}
}
return data
}

View File

@@ -0,0 +1,28 @@
package datamatrix
import (
"bytes"
"testing"
)
func Test_CalcECC(t *testing.T) {
data := []byte{142, 164, 186}
var size *dmCodeSize = nil
for _, s := range codeSizes {
if s.DataCodewords() >= len(data) {
size = s
break
}
}
if size == nil {
t.Error("size not found")
}
if bytes.Compare(ec.calcECC(data, size), []byte{142, 164, 186, 114, 25, 5, 88, 102}) != 0 {
t.Error("ECC Test 1 failed")
}
data = []byte{66, 129, 70}
if bytes.Compare(ec.calcECC(data, size), []byte{66, 129, 70, 138, 234, 82, 82, 95}) != 0 {
t.Error("ECC Test 2 failed")
}
}

187
vendor/github.com/boombuler/barcode/ean/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,187 @@
// Package ean can create EAN 8 and EAN 13 barcodes.
package ean
import (
"errors"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type encodedNumber struct {
LeftOdd []bool
LeftEven []bool
Right []bool
CheckSum []bool
}
var encoderTable = map[rune]encodedNumber{
'0': encodedNumber{
[]bool{false, false, false, true, true, false, true},
[]bool{false, true, false, false, true, true, true},
[]bool{true, true, true, false, false, true, false},
[]bool{false, false, false, false, false, false},
},
'1': encodedNumber{
[]bool{false, false, true, true, false, false, true},
[]bool{false, true, true, false, false, true, true},
[]bool{true, true, false, false, true, true, false},
[]bool{false, false, true, false, true, true},
},
'2': encodedNumber{
[]bool{false, false, true, false, false, true, true},
[]bool{false, false, true, true, false, true, true},
[]bool{true, true, false, true, true, false, false},
[]bool{false, false, true, true, false, true},
},
'3': encodedNumber{
[]bool{false, true, true, true, true, false, true},
[]bool{false, true, false, false, false, false, true},
[]bool{true, false, false, false, false, true, false},
[]bool{false, false, true, true, true, false},
},
'4': encodedNumber{
[]bool{false, true, false, false, false, true, true},
[]bool{false, false, true, true, true, false, true},
[]bool{true, false, true, true, true, false, false},
[]bool{false, true, false, false, true, true},
},
'5': encodedNumber{
[]bool{false, true, true, false, false, false, true},
[]bool{false, true, true, true, false, false, true},
[]bool{true, false, false, true, true, true, false},
[]bool{false, true, true, false, false, true},
},
'6': encodedNumber{
[]bool{false, true, false, true, true, true, true},
[]bool{false, false, false, false, true, false, true},
[]bool{true, false, true, false, false, false, false},
[]bool{false, true, true, true, false, false},
},
'7': encodedNumber{
[]bool{false, true, true, true, false, true, true},
[]bool{false, false, true, false, false, false, true},
[]bool{true, false, false, false, true, false, false},
[]bool{false, true, false, true, false, true},
},
'8': encodedNumber{
[]bool{false, true, true, false, true, true, true},
[]bool{false, false, false, true, false, false, true},
[]bool{true, false, false, true, false, false, false},
[]bool{false, true, false, true, true, false},
},
'9': encodedNumber{
[]bool{false, false, false, true, false, true, true},
[]bool{false, false, true, false, true, true, true},
[]bool{true, true, true, false, true, false, false},
[]bool{false, true, true, false, true, false},
},
}
func calcCheckNum(code string) rune {
x3 := len(code) == 7
sum := 0
for _, r := range code {
curNum := utils.RuneToInt(r)
if curNum < 0 || curNum > 9 {
return 'B'
}
if x3 {
curNum = curNum * 3
}
x3 = !x3
sum += curNum
}
return utils.IntToRune((10 - (sum % 10)) % 10)
}
func encodeEAN8(code string) *utils.BitList {
result := new(utils.BitList)
result.AddBit(true, false, true)
for cpos, r := range code {
num, ok := encoderTable[r]
if !ok {
return nil
}
var data []bool
if cpos < 4 {
data = num.LeftOdd
} else {
data = num.Right
}
if cpos == 4 {
result.AddBit(false, true, false, true, false)
}
result.AddBit(data...)
}
result.AddBit(true, false, true)
return result
}
func encodeEAN13(code string) *utils.BitList {
result := new(utils.BitList)
result.AddBit(true, false, true)
var firstNum []bool
for cpos, r := range code {
num, ok := encoderTable[r]
if !ok {
return nil
}
if cpos == 0 {
firstNum = num.CheckSum
continue
}
var data []bool
if cpos < 7 { // Left
if firstNum[cpos-1] {
data = num.LeftEven
} else {
data = num.LeftOdd
}
} else {
data = num.Right
}
if cpos == 7 {
result.AddBit(false, true, false, true, false)
}
result.AddBit(data...)
}
result.AddBit(true, false, true)
return result
}
// Encode returns a EAN 8 or EAN 13 barcode for the given code
func Encode(code string) (barcode.BarcodeIntCS, error) {
var checkSum int
if len(code) == 7 || len(code) == 12 {
code += string(calcCheckNum(code))
checkSum = utils.RuneToInt(calcCheckNum(code))
} else if len(code) == 8 || len(code) == 13 {
check := code[0 : len(code)-1]
check += string(calcCheckNum(check))
if check != code {
return nil, errors.New("checksum missmatch")
}
checkSum = utils.RuneToInt(rune(code[len(code)-1]))
}
if len(code) == 8 {
result := encodeEAN8(code)
if result != nil {
return utils.New1DCodeIntCheckSum(barcode.TypeEAN8, code, result, checkSum), nil
}
} else if len(code) == 13 {
result := encodeEAN13(code)
if result != nil {
return utils.New1DCodeIntCheckSum(barcode.TypeEAN13, code, result, checkSum), nil
}
}
return nil, errors.New("invalid ean code data")
}

View File

@@ -0,0 +1,46 @@
package ean
import (
"image/color"
"testing"
)
func testHelper(t *testing.T, testCode, testResult, kind string, checkMetadata bool) {
code, err := Encode(testCode)
if err != nil {
t.Error(err)
}
if checkMetadata && (code.Metadata().Dimensions != 1 || code.Content() != testCode || code.Metadata().CodeKind != kind) {
t.Error("Metadata missmatch")
}
if len(testResult) != code.Bounds().Max.X {
t.Fail()
}
for i, r := range testResult {
if (code.At(i, 0) == color.Black) != (r == '1') {
t.Fail()
}
}
}
func Test_EncodeEAN(t *testing.T) {
testHelper(t, "5901234123457", "10100010110100111011001100100110111101001110101010110011011011001000010101110010011101000100101", "EAN 13", true)
testHelper(t, "55123457", "1010110001011000100110010010011010101000010101110010011101000100101", "EAN 8", true)
testHelper(t, "5512345", "1010110001011000100110010010011010101000010101110010011101000100101", "EAN 8", false)
_, err := Encode("55123458") //<-- Invalid checksum
if err == nil {
t.Error("Invalid checksum not detected")
}
_, err = Encode("invalid")
if err == nil {
t.Error("\"invalid\" should not be encodable")
}
_, err = Encode("invalid")
if err == nil {
t.Error("\"invalid\" should not be encodable")
}
bits := encodeEAN13("invalid error")
if bits != nil {
t.Error("\"invalid error\" should not be encodable")
}
}

416
vendor/github.com/boombuler/barcode/pdf417/codewords.go generated vendored Normal file
View File

@@ -0,0 +1,416 @@
package pdf417
const start_word = 0x1fea8
const stop_word = 0x3fa29
var codewords = [][]int{
[]int{
0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0,
0x1d470, 0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0,
0x1eb7c, 0x1ace0, 0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860,
0x15dc0, 0x1aef0, 0x1d77c, 0x15ce0, 0x1ae78, 0x1d73e, 0x15c70,
0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78, 0x1af3e, 0x15f7c, 0x1f5fa,
0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270, 0x1e93c, 0x1a460,
0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418, 0x14810,
0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60,
0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be,
0x14e70, 0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c,
0x14f1e, 0x1a2c0, 0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e,
0x14440, 0x1a230, 0x1d11c, 0x14420, 0x1a218, 0x14410, 0x14408,
0x146c0, 0x1a370, 0x1d1bc, 0x14660, 0x1a338, 0x1d19e, 0x14630,
0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc, 0x14738, 0x1a39e,
0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240, 0x1a130,
0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208,
0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318,
0x1a18e, 0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0,
0x1d05c, 0x14120, 0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108,
0x1a086, 0x14104, 0x141b0, 0x14198, 0x1418c, 0x140a0, 0x1d02e,
0x1a04c, 0x1a046, 0x14082, 0x1cae0, 0x1e578, 0x1f2be, 0x194c0,
0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e, 0x12840, 0x19430,
0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670, 0x1cb3c,
0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe,
0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c,
0x12fbe, 0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e,
0x1b440, 0x1da30, 0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410,
0x1da0c, 0x192c0, 0x1c970, 0x1e4bc, 0x1b6c0, 0x19260, 0x1c938,
0x1e49e, 0x1b660, 0x1db38, 0x1ed9e, 0x16c40, 0x12420, 0x19218,
0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0, 0x19370, 0x1c9bc,
0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738, 0x1db9e,
0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738,
0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e,
0x16f9e, 0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c,
0x1b220, 0x1d918, 0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204,
0x19160, 0x1c8b8, 0x1e45e, 0x1b360, 0x19130, 0x1c89c, 0x16640,
0x12220, 0x1d99c, 0x1c88e, 0x16620, 0x12210, 0x1910c, 0x16610,
0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8, 0x1c8de, 0x16760,
0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718, 0x1230c,
0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e,
0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898,
0x1ec4e, 0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102,
0x12140, 0x190b0, 0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e,
0x16320, 0x1b198, 0x1d8ce, 0x16310, 0x12108, 0x19086, 0x16308,
0x1b186, 0x16304, 0x121b0, 0x190dc, 0x163b0, 0x12198, 0x190ce,
0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386, 0x163dc, 0x163ce,
0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088, 0x1d846,
0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090,
0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184,
0x12082, 0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826,
0x1b042, 0x1902c, 0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0,
0x1c570, 0x1e2bc, 0x18a60, 0x1c538, 0x11440, 0x18a30, 0x1c51c,
0x11420, 0x18a18, 0x11410, 0x11408, 0x116c0, 0x18b70, 0x1c5bc,
0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c, 0x11618, 0x1160c,
0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc, 0x1179e,
0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20,
0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960,
0x1c4b8, 0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220,
0x1cd9c, 0x1c48e, 0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208,
0x13608, 0x11360, 0x189b8, 0x1c4de, 0x13760, 0x11330, 0x1cdde,
0x13730, 0x19b9c, 0x1898e, 0x13718, 0x1130c, 0x1370c, 0x113b8,
0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e, 0x113de, 0x137de,
0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e, 0x1dd10,
0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c,
0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece,
0x1bb10, 0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140,
0x188b0, 0x1c45c, 0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740,
0x13320, 0x19998, 0x1ccce, 0x17720, 0x1bb98, 0x1ddce, 0x18886,
0x17710, 0x13308, 0x19986, 0x17708, 0x11102, 0x111b0, 0x188dc,
0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398, 0x199ce, 0x17798,
0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce, 0x177dc,
0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88,
0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0,
0x19890, 0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884,
0x1b984, 0x19882, 0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0,
0x11090, 0x1884c, 0x173a0, 0x13190, 0x198cc, 0x18846, 0x17390,
0x1b9cc, 0x11084, 0x17388, 0x13184, 0x11082, 0x13182, 0x110d8,
0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc, 0x110c6, 0x173cc,
0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48, 0x1ee26,
0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26,
0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c,
0x130d0, 0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8,
0x1b8e6, 0x11042, 0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec,
0x171e6, 0x1ee16, 0x1dc22, 0x1cc16, 0x19824, 0x19822, 0x11028,
0x13068, 0x170e8, 0x11022, 0x13062, 0x18560, 0x10a40, 0x18530,
0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c, 0x10a08, 0x18506,
0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18, 0x1858e,
0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde,
0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c,
0x18d08, 0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40,
0x10920, 0x1c6dc, 0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10,
0x10908, 0x18486, 0x11b08, 0x18d86, 0x10902, 0x109b0, 0x184dc,
0x11bb0, 0x10998, 0x184ce, 0x11b98, 0x18dce, 0x11b8c, 0x10986,
0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0, 0x1e758, 0x1f3ae,
0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82, 0x18ca0,
0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646,
0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458,
0x119a0, 0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446,
0x13b90, 0x19dcc, 0x10884, 0x13b88, 0x11984, 0x10882, 0x11982,
0x108d8, 0x1846e, 0x119d8, 0x108cc, 0x13bd8, 0x119cc, 0x108c6,
0x13bcc, 0x119c6, 0x108ee, 0x119ee, 0x13bee, 0x1ef50, 0x1f7ac,
0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50, 0x1e72c, 0x1ded0,
0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42, 0x1dec2,
0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8,
0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2,
0x10850, 0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8,
0x18c66, 0x17bd0, 0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6,
0x118c2, 0x17bc4, 0x1086c, 0x118ec, 0x10866, 0x139ec, 0x118e6,
0x17bec, 0x139e6, 0x17be6, 0x1ef28, 0x1f796, 0x1ef24, 0x1ef22,
0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64, 0x1ce22, 0x1de62,
0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64, 0x18c22,
0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36,
0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4,
0x138e2, 0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32,
0x19c34, 0x1bc74, 0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2,
0x10540, 0x10520, 0x18298, 0x10510, 0x10508, 0x10504, 0x105b0,
0x10598, 0x1058c, 0x10586, 0x105dc, 0x105ce, 0x186a0, 0x18690,
0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682, 0x104a0, 0x18258,
0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88, 0x186c6,
0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee,
0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748,
0x1c744, 0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8,
0x1c766, 0x18ec4, 0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448,
0x18226, 0x11dd0, 0x10cc8, 0x10444, 0x11dc8, 0x10cc4, 0x10442,
0x11dc4, 0x10cc2, 0x1046c, 0x10cec, 0x10466, 0x11dec, 0x10ce6,
0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728, 0x1cf68, 0x1e7b6,
0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68, 0x1c736,
0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428,
0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8,
0x11ce4, 0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6,
0x13df6, 0x1f7d4, 0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2,
0x1c714, 0x1cf34, 0x1c712, 0x1df74, 0x1cf32, 0x1df72, 0x18614,
0x18e34, 0x18612, 0x19e74, 0x18e32, 0x1bef4,
},
[]int{
0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518,
0x1fa8e, 0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60,
0x1f5b8, 0x1fade, 0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18,
0x1f58e, 0x1d610, 0x1eb0c, 0x1d608, 0x1eb06, 0x1d604, 0x1d760,
0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730, 0x1eb9c, 0x1ae20, 0x1d718,
0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706, 0x1ae04, 0x1af60,
0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20, 0x1af18,
0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8,
0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8,
0x1afde, 0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920,
0x1f498, 0x1fa4e, 0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904,
0x1e902, 0x1d340, 0x1e9b0, 0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce,
0x1d310, 0x1e98c, 0x1d308, 0x1e986, 0x1d304, 0x1d302, 0x1a740,
0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce, 0x1a710, 0x1d38c,
0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0, 0x1d3dc,
0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786,
0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86,
0x14fdc, 0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c,
0x1e888, 0x1f446, 0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e,
0x1d190, 0x1e8cc, 0x1d188, 0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0,
0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc, 0x1a388, 0x1d1c6, 0x1a384,
0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790, 0x1a3cc, 0x14788,
0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc, 0x147c6,
0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842,
0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0,
0x1d0ec, 0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec,
0x143c8, 0x1a1e6, 0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828,
0x1f416, 0x1e824, 0x1e822, 0x1d068, 0x1e836, 0x1d064, 0x1d062,
0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2, 0x141e8, 0x1a0f6, 0x141e4,
0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032, 0x1a074, 0x1a072,
0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e, 0x1e510,
0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0,
0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08,
0x1e586, 0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720,
0x1cb98, 0x1e5ce, 0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704,
0x19702, 0x12f40, 0x197b0, 0x1cbdc, 0x12f20, 0x19798, 0x1cbce,
0x12f10, 0x1978c, 0x12f08, 0x19786, 0x12f04, 0x12fb0, 0x197dc,
0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc, 0x12fce, 0x1f6a0,
0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688, 0x1fb46,
0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0,
0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484,
0x1ed84, 0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0,
0x1c990, 0x1e4cc, 0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984,
0x1db84, 0x1c982, 0x1db82, 0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0,
0x19390, 0x1c9cc, 0x1b790, 0x1dbcc, 0x1c9c6, 0x1b788, 0x19384,
0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8, 0x1c9ee, 0x16fa0,
0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88, 0x12784,
0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc,
0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648,
0x1fb26, 0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c,
0x1ecd0, 0x1e448, 0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442,
0x1ecc2, 0x1c8d0, 0x1e46c, 0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8,
0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2, 0x191d0, 0x1c8ec, 0x1b3d0,
0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4, 0x191c2, 0x1b3c2,
0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8, 0x1b3e6,
0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6,
0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428,
0x1f216, 0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868,
0x1e436, 0x1d8e8, 0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8,
0x1c876, 0x1b1e8, 0x1d8f6, 0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8,
0x190f6, 0x163e8, 0x121e4, 0x163e4, 0x121e2, 0x163e2, 0x121f6,
0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414, 0x1ec34, 0x1e412,
0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074, 0x1b0f4,
0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a,
0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0,
0x1f158, 0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284,
0x1e282, 0x1c5a0, 0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588,
0x1e2c6, 0x1c584, 0x1c582, 0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90,
0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84, 0x18b82, 0x117a0, 0x18bd8,
0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6, 0x11784, 0x11782,
0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350, 0x1f9ac,
0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342,
0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366,
0x1e6c4, 0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8,
0x1e266, 0x1cdc8, 0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0,
0x1c4ec, 0x19bd0, 0x189c8, 0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4,
0x189c2, 0x19bc2, 0x113d0, 0x189ec, 0x137d0, 0x113c8, 0x189e6,
0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2, 0x113ec, 0x137ec,
0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4, 0x174f8,
0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc,
0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e,
0x1f762, 0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776,
0x1e222, 0x1eee4, 0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8,
0x1c464, 0x1dde8, 0x1cce4, 0x1c462, 0x1dde4, 0x1cce2, 0x1dde2,
0x188e8, 0x1c476, 0x199e8, 0x188e4, 0x1bbe8, 0x199e4, 0x188e2,
0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6, 0x133e8, 0x111e4,
0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2, 0x111f6,
0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e,
0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214,
0x1e634, 0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74,
0x1c432, 0x1dcf4, 0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872,
0x1b9f4, 0x198f2, 0x1b9f2, 0x110f4, 0x131f4, 0x110f2, 0x173f4,
0x131f2, 0x173f2, 0x1fb8a, 0x1717c, 0x1713e, 0x1f30a, 0x1f71a,
0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a, 0x1dc7a, 0x1883a,
0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be, 0x1e150,
0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c,
0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8,
0x1c2e6, 0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6,
0x10bc4, 0x10bc2, 0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc,
0x1f1a4, 0x11a7e, 0x1f1a2, 0x1e128, 0x1f096, 0x1e368, 0x1e124,
0x1e364, 0x1e122, 0x1e362, 0x1c268, 0x1e136, 0x1c6e8, 0x1c264,
0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276, 0x18de8, 0x184e4,
0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8, 0x109e4,
0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8,
0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4,
0x1f192, 0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774,
0x1e332, 0x1e772, 0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672,
0x1cef2, 0x18474, 0x18cf4, 0x18472, 0x19df4, 0x18cf2, 0x19df2,
0x108f4, 0x119f4, 0x108f2, 0x13bf4, 0x119f2, 0x13bf2, 0x17af0,
0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e, 0x1f9ca, 0x1397c,
0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a, 0x1f7ba,
0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a,
0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa,
0x139fa, 0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be,
0x178bc, 0x1789e, 0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168,
0x1e0b6, 0x1c164, 0x1c162, 0x182e8, 0x1c176, 0x182e4, 0x182e2,
0x105e8, 0x182f6, 0x105e4, 0x105e2, 0x105f6, 0x1f0d4, 0x10d7e,
0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2, 0x1c134, 0x1c374,
0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2, 0x104f4,
0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca,
0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a,
0x1823a, 0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78,
0x19ebe, 0x13d3c, 0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc,
0x17d38, 0x1be9e, 0x17d1c, 0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e,
0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c, 0x17c8e, 0x13c5e, 0x17cde,
0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2, 0x18174, 0x18172,
0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a, 0x1837a,
0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e,
0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98,
0x1bf4e, 0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece,
0x17e58, 0x1bf2e, 0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c,
0x17e26, 0x10f5e, 0x11f5c, 0x11f4e, 0x13f58, 0x19fae, 0x13f4c,
0x13f46, 0x11f2e, 0x13f6e, 0x13f2c, 0x13f26,
},
[]int{
0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8,
0x1d47e, 0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8,
0x1fac8, 0x159f0, 0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2,
0x1587c, 0x1f5d0, 0x1faec, 0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc,
0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0, 0x1f5ec, 0x1ebc8, 0x1f5e6,
0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8, 0x1ebe6, 0x1d7c4,
0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4, 0x14bc0,
0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c,
0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64,
0x14cf8, 0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76,
0x14efc, 0x1f4e4, 0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4,
0x1e9e2, 0x1d3e8, 0x1e9f6, 0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6,
0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8, 0x1d17e, 0x144f0, 0x1a27c,
0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34, 0x146f8, 0x1a37e,
0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472, 0x1e8f4,
0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c,
0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e,
0x1f43a, 0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e,
0x141be, 0x140bc, 0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0,
0x194f8, 0x1ca7e, 0x128f0, 0x1947c, 0x12878, 0x1943e, 0x1283c,
0x1f968, 0x12df0, 0x196fc, 0x1f964, 0x12cf8, 0x1967e, 0x1f962,
0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc, 0x1f2e4, 0x12e7e,
0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8, 0x1e5f6,
0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0,
0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478,
0x1da3e, 0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0,
0x192f8, 0x1c97e, 0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c,
0x1923e, 0x16c78, 0x1243c, 0x16c3c, 0x1241e, 0x16c1e, 0x1f934,
0x126f8, 0x1937e, 0x1fb74, 0x1f932, 0x16ef8, 0x1267c, 0x1fb72,
0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e, 0x1f6f4, 0x1f272,
0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2, 0x1c9f4,
0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0,
0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438,
0x1b21e, 0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278,
0x1913e, 0x16678, 0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a,
0x1237c, 0x1fb3a, 0x1677c, 0x1233e, 0x1673e, 0x1f23a, 0x1f67a,
0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa, 0x191fa, 0x162e0, 0x1b178,
0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e, 0x1621c, 0x1620e,
0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e, 0x1631e,
0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c,
0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e,
0x1609c, 0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0,
0x18af8, 0x1c57e, 0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c,
0x1141e, 0x1f8b4, 0x116f8, 0x18b7e, 0x1f8b2, 0x1167c, 0x1163e,
0x1f174, 0x1177e, 0x1f172, 0x1e2f4, 0x1e2f2, 0x1c5f4, 0x1c5f2,
0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c, 0x134e0, 0x19a78,
0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c, 0x1340e,
0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e,
0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c,
0x1133e, 0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa,
0x1cdfa, 0x189fa, 0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70,
0x1dd3c, 0x17460, 0x1ba38, 0x1dd1e, 0x17430, 0x1ba1c, 0x17418,
0x1ba0e, 0x1740c, 0x132e0, 0x19978, 0x1ccbe, 0x176e0, 0x13270,
0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638, 0x1321c, 0x1761c,
0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c, 0x17778,
0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be,
0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e,
0x17230, 0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170,
0x198bc, 0x17370, 0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c,
0x1310e, 0x1730e, 0x110bc, 0x131bc, 0x1109e, 0x173bc, 0x1319e,
0x1739e, 0x17160, 0x1b8b8, 0x1dc5e, 0x17130, 0x1b89c, 0x17118,
0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e, 0x171b8, 0x1309c,
0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de, 0x170b0,
0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc,
0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e,
0x1706e, 0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e,
0x10a3c, 0x10a1e, 0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa,
0x185fa, 0x11ae0, 0x18d78, 0x1c6be, 0x11a70, 0x18d3c, 0x11a38,
0x18d1e, 0x11a1c, 0x11a0e, 0x10978, 0x184be, 0x11b78, 0x1093c,
0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe, 0x13ac0, 0x19d70,
0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c, 0x13a18,
0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938,
0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc,
0x119bc, 0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8,
0x1ef5e, 0x17a40, 0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e,
0x17a10, 0x1bd0c, 0x17a08, 0x1bd06, 0x17a04, 0x13960, 0x19cb8,
0x1ce5e, 0x17b60, 0x13930, 0x19c9c, 0x17b30, 0x1bd9c, 0x19c8e,
0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06, 0x118b8, 0x18c5e,
0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c, 0x1398e,
0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0,
0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908,
0x1bc86, 0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898,
0x19c4e, 0x17998, 0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c,
0x138dc, 0x1184e, 0x179dc, 0x138ce, 0x179ce, 0x178a0, 0x1bc58,
0x1de2e, 0x17890, 0x1bc4c, 0x17888, 0x1bc46, 0x17884, 0x17882,
0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc, 0x13846, 0x178c6,
0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848, 0x1bc26,
0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828,
0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be,
0x1053c, 0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e,
0x10d1c, 0x10d0e, 0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60,
0x18eb8, 0x1c75e, 0x11d30, 0x18e9c, 0x11d18, 0x18e8e, 0x11d0c,
0x11d06, 0x10cb8, 0x1865e, 0x11db8, 0x10c9c, 0x11d9c, 0x10c8e,
0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40, 0x19eb0, 0x1cf5c,
0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08, 0x19e86,
0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e,
0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc,
0x10c4e, 0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae,
0x1be90, 0x1df4c, 0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0,
0x19e58, 0x1cf2e, 0x17da0, 0x13c90, 0x19e4c, 0x17d90, 0x1becc,
0x19e46, 0x17d88, 0x13c84, 0x17d84, 0x13c82, 0x17d82, 0x11c58,
0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc, 0x11c46, 0x17dcc,
0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee, 0x1be50,
0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c,
0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42,
0x17cc2, 0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6,
0x1be28, 0x1df16, 0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68,
0x13c24, 0x17c64, 0x13c22, 0x17c62, 0x11c16, 0x13c36, 0x17c76,
0x1be14, 0x1be12, 0x13c14, 0x17c34, 0x13c12, 0x17c32, 0x102bc,
0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e, 0x1025e, 0x106de,
0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86, 0x1065c,
0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90,
0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e,
0x11ed8, 0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e,
0x11eee, 0x19f50, 0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42,
0x11e50, 0x18f2c, 0x13ed0, 0x19f6c, 0x18f26, 0x13ec8, 0x11e44,
0x13ec4, 0x11e42, 0x13ec2, 0x10e2c, 0x11e6c, 0x10e26, 0x13eec,
0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4, 0x1dfa2, 0x19f28,
0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62, 0x11e28,
0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4,
0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94,
0x1df92, 0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34,
0x11e12, 0x17e74, 0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a,
0x11e0a, 0x13e1a, 0x17e3a, 0x1035c, 0x1034e, 0x10758, 0x183ae,
0x1074c, 0x10746, 0x1032e, 0x1076e, 0x10f50, 0x187ac, 0x10f48,
0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c, 0x10726, 0x10f66,
0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796, 0x11f68,
0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76,
0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14,
0x11f34, 0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a,
0x19f9a, 0x10f0a, 0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8,
0x183d6, 0x107a4, 0x107a2, 0x10396, 0x107b6, 0x187d4, 0x187d2,
0x10794, 0x10fb4, 0x10792, 0x10fb2, 0x1c7ea,
},
}
func getCodeword(tableId int, word int) int {
return codewords[tableId][word]
}

View File

@@ -0,0 +1,57 @@
package pdf417
import "math"
const (
minCols = 2
maxCols = 30
maxRows = 30
minRows = 2
moduleHeight = 2
preferred_ratio = 3.0
)
func calculateNumberOfRows(m, k, c int) int {
r := ((m + 1 + k) / c) + 1
if c*r >= (m + 1 + k + c) {
r--
}
return r
}
func calcDimensions(dataWords, eccWords int) (cols, rows int) {
ratio := 0.0
cols = 0
rows = 0
for c := minCols; c <= maxCols; c++ {
r := calculateNumberOfRows(dataWords, eccWords, c)
if r < minRows {
break
}
if r > maxRows {
continue
}
newRatio := float64(17*cols+69) / float64(rows*moduleHeight)
if rows != 0 && math.Abs(newRatio-preferred_ratio) > math.Abs(ratio-preferred_ratio) {
continue
}
ratio = newRatio
cols = c
rows = r
}
if rows == 0 {
r := calculateNumberOfRows(dataWords, eccWords, minCols)
if r < minRows {
rows = minRows
cols = minCols
}
}
return
}

162
vendor/github.com/boombuler/barcode/pdf417/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,162 @@
// Package pdf417 can create PDF-417 barcodes
package pdf417
import (
"fmt"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
const (
padding_codeword = 900
)
// Encodes the given data as PDF417 barcode.
// securityLevel should be between 0 and 8. The higher the number, the more
// additional error-correction codes are added.
func Encode(data string, securityLevel byte) (barcode.Barcode, error) {
if securityLevel >= 9 {
return nil, fmt.Errorf("Invalid security level %d", securityLevel)
}
sl := securitylevel(securityLevel)
dataWords, err := highlevelEncode(data)
if err != nil {
return nil, err
}
columns, rows := calcDimensions(len(dataWords), sl.ErrorCorrectionWordCount())
if columns < minCols || columns > maxCols || rows < minRows || rows > maxRows {
return nil, fmt.Errorf("Unable to fit data in barcode")
}
barcode := new(pdfBarcode)
barcode.data = data
codeWords, err := encodeData(dataWords, columns, sl)
if err != nil {
return nil, err
}
grid := [][]int{}
for i := 0; i < len(codeWords); i += columns {
grid = append(grid, codeWords[i:min(i+columns, len(codeWords))])
}
codes := [][]int{}
for rowNum, row := range grid {
table := rowNum % 3
rowCodes := make([]int, 0, columns+4)
rowCodes = append(rowCodes, start_word)
rowCodes = append(rowCodes, getCodeword(table, getLeftCodeWord(rowNum, rows, columns, securityLevel)))
for _, word := range row {
rowCodes = append(rowCodes, getCodeword(table, word))
}
rowCodes = append(rowCodes, getCodeword(table, getRightCodeWord(rowNum, rows, columns, securityLevel)))
rowCodes = append(rowCodes, stop_word)
codes = append(codes, rowCodes)
}
barcode.code = renderBarcode(codes)
barcode.width = (columns+4)*17 + 1
return barcode, nil
}
func encodeData(dataWords []int, columns int, sl securitylevel) ([]int, error) {
dataCount := len(dataWords)
ecCount := sl.ErrorCorrectionWordCount()
padWords := getPadding(dataCount, ecCount, columns)
dataWords = append(dataWords, padWords...)
length := len(dataWords) + 1
dataWords = append([]int{length}, dataWords...)
ecWords := sl.Compute(dataWords)
return append(dataWords, ecWords...), nil
}
func getLeftCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
tableId := rowNum % 3
var x int
switch tableId {
case 0:
x = (rows - 3) / 3
case 1:
x = int(securityLevel) * 3
x += (rows - 1) % 3
case 2:
x = columns - 1
}
return 30*(rowNum/3) + x
}
func getRightCodeWord(rowNum int, rows int, columns int, securityLevel byte) int {
tableId := rowNum % 3
var x int
switch tableId {
case 0:
x = columns - 1
case 1:
x = (rows - 1) / 3
case 2:
x = int(securityLevel) * 3
x += (rows - 1) % 3
}
return 30*(rowNum/3) + x
}
func min(a, b int) int {
if a <= b {
return a
}
return b
}
func getPadding(dataCount int, ecCount int, columns int) []int {
totalCount := dataCount + ecCount + 1
mod := totalCount % columns
padding := []int{}
if mod > 0 {
padCount := columns - mod
padding = make([]int, padCount)
for i := 0; i < padCount; i++ {
padding[i] = padding_codeword
}
}
return padding
}
func renderBarcode(codes [][]int) *utils.BitList {
bl := new(utils.BitList)
for _, row := range codes {
lastIdx := len(row) - 1
for i, col := range row {
if i == lastIdx {
bl.AddBits(col, 18)
} else {
bl.AddBits(col, 17)
}
}
}
return bl
}

View File

@@ -0,0 +1,151 @@
package pdf417
type securitylevel byte
func (level securitylevel) ErrorCorrectionWordCount() int {
return 1 << (uint(level) + 1)
}
var correctionFactors = [][]int{
// Level 0
[]int{27, 917},
// Level 1
[]int{522, 568, 723, 809},
// Level 2
[]int{237, 308, 436, 284, 646, 653, 428, 379},
// Level 3
[]int{
274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42,
176, 65,
},
// Level 4
[]int{
361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687,
284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133,
231, 390, 685, 330, 63, 410,
},
// Level 5
[]int{
539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877,
381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511,
400, 672, 762, 283, 184, 440, 35, 519, 31, 460, 594, 225, 535, 517,
352, 605, 158, 651, 201, 488, 502, 648, 733, 717, 83, 404, 97, 280,
771, 840, 629, 4, 381, 843, 623, 264, 543,
},
// Level 6
[]int{
521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925,
749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631,
292, 908, 490, 704, 516, 258, 457, 907, 594, 723, 674, 292, 272, 96,
684, 432, 686, 606, 860, 569, 193, 219, 129, 186, 236, 287, 192,
775, 278, 173, 40, 379, 712, 463, 646, 776, 171, 491, 297, 763, 156,
732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, 784, 663, 627,
378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157,
374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587,
804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86,
801, 4, 108, 539,
},
// Level 7
[]int{
524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786,
138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194,
280, 201, 280, 828, 757, 710, 814, 919, 89, 68, 569, 11, 204, 796,
605, 540, 913, 801, 700, 799, 137, 439, 418, 592, 668, 353, 859,
370, 694, 325, 240, 216, 257, 284, 549, 209, 884, 315, 70, 329, 793,
490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, 307,
291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289,
470, 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136,
538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355,
588, 188, 462, 10, 134, 628, 320, 479, 130, 739, 71, 263, 318, 374,
601, 192, 605, 142, 673, 687, 234, 722, 384, 177, 752, 607, 640,
455, 193, 689, 707, 805, 641, 48, 60, 732, 621, 895, 544, 261, 852,
655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, 503, 118,
49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550,
73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791,
893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299,
922, 191, 910, 532, 609, 829, 189, 20, 167, 29, 872, 449, 83, 402,
41, 656, 505, 579, 481, 173, 404, 251, 688, 95, 497, 555, 642, 543,
307, 159, 924, 558, 648, 55, 497, 10,
},
// Level 8
[]int{
352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380,
350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88,
87, 193, 352, 781, 846, 75, 327, 520, 435, 543, 203, 666, 249, 346,
781, 621, 640, 268, 794, 534, 539, 781, 408, 390, 644, 102, 476,
499, 290, 632, 545, 37, 858, 916, 552, 41, 542, 289, 122, 272, 383,
800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, 290, 204, 681,
407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808,
684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516,
258, 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328,
596, 786, 303, 570, 381, 415, 641, 156, 237, 151, 429, 531, 207,
676, 710, 89, 168, 304, 402, 40, 708, 575, 162, 864, 229, 65, 861,
841, 512, 164, 477, 221, 92, 358, 785, 288, 357, 850, 836, 827, 736,
707, 94, 8, 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248,
361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, 45, 902,
452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, 37,
124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578,
911, 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777,
699, 688, 43, 408, 842, 383, 721, 521, 560, 644, 714, 559, 62, 145,
873, 663, 713, 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564,
343, 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708,
410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, 586, 424,
833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, 787,
680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644,
905, 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662,
513, 56, 252, 341, 242, 797, 838, 837, 720, 224, 307, 631, 61, 87,
560, 310, 756, 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915,
459, 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673,
782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, 162, 498,
308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, 375,
273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687,
842, 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321,
54, 669, 316, 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316,
486, 721, 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762,
752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, 284, 736,
138, 646, 411, 877, 669, 141, 919, 45, 780, 407, 164, 332, 899, 165,
726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, 63, 310, 863,
251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263,
},
}
func (level securitylevel) Compute(data []int) []int {
// Correction factors for the given level
factors := correctionFactors[int(level)]
// Number of correction code words
count := level.ErrorCorrectionWordCount()
// Correction code words array, prepopulated with zeros
ecWords := make([]int, count)
for _, value := range data {
temp := (value + ecWords[0]) % 929
for i := count - 1; i >= 0; i-- {
add := 0
if i > 0 {
add = ecWords[count-i]
}
ecWords[count-1-i] = (add + 929 - (temp*factors[i])%929) % 929
}
}
for key, word := range ecWords {
if word > 0 {
ecWords[key] = 929 - word
}
}
return ecWords
}

View File

@@ -0,0 +1,61 @@
package pdf417
import (
"testing"
)
var inputData = []int{16, 902, 1, 278, 827, 900, 295, 902, 2, 326, 823, 544, 900, 149, 900, 900}
func TestReedSolomonComputeLevel0(t *testing.T) {
var level securitylevel = 0
expected := []int{156, 765}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 0")
}
func TestReedSolomonComputeLevel1(t *testing.T) {
var level securitylevel = 1
expected := []int{168, 875, 63, 355}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 1")
}
func TestReedSolomonComputeLevel2(t *testing.T) {
var level securitylevel = 2
expected := []int{628, 715, 393, 299, 863, 601, 169, 708}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 2")
}
func TestReedSolomonComputeLevel3(t *testing.T) {
var level securitylevel = 3
expected := []int{232, 176, 793, 616, 476, 406, 855, 445, 84, 518, 522, 721, 607, 2, 42, 578}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 3")
}
func TestReedSolomonComputeLevel4(t *testing.T) {
var level securitylevel = 4
expected := []int{281, 156, 276, 668, 44, 252, 877, 30, 549, 856, 773, 639, 420, 330, 693, 329, 283, 723, 480, 482, 102, 925, 535, 892, 374, 472, 837, 331, 343, 608, 390, 364}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 4")
}
func TestReedSolomonComputeLevel5(t *testing.T) {
var level securitylevel = 5
expected := []int{31, 850, 18, 870, 53, 477, 837, 130, 533, 186, 266, 450, 39, 492, 542, 653, 499, 887, 618, 103, 364, 313, 906, 396, 270, 735, 593, 81, 557, 712, 810, 48, 167, 533, 205, 577, 503, 126, 449, 189, 859, 471, 493, 849, 554, 76, 878, 893, 168, 497, 251, 704, 311, 650, 283, 268, 462, 223, 659, 763, 176, 34, 544, 304}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 5")
}
func TestReedSolomonComputeLevel6(t *testing.T) {
var level securitylevel = 6
expected := []int{345, 775, 909, 489, 650, 568, 869, 577, 574, 349, 885, 317, 492, 222, 783, 451, 647, 385, 168, 366, 118, 655, 643, 551, 179, 880, 880, 752, 132, 206, 765, 862, 727, 240, 32, 266, 911, 287, 813, 437, 868, 201, 681, 867, 567, 398, 508, 564, 504, 676, 785, 554, 831, 566, 424, 93, 515, 275, 61, 544, 272, 621, 374, 922, 779, 663, 789, 295, 631, 536, 755, 465, 485, 416, 76, 412, 76, 431, 28, 614, 767, 419, 600, 779, 94, 584, 647, 846, 121, 97, 790, 205, 424, 793, 263, 271, 694, 522, 437, 817, 382, 164, 113, 849, 178, 602, 554, 261, 415, 737, 401, 675, 203, 271, 649, 120, 765, 209, 522, 687, 420, 32, 60, 266, 270, 228, 304, 270}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 6")
}
func TestReedSolomonComputeLevel7(t *testing.T) {
var level securitylevel = 7
expected := []int{142, 203, 799, 4, 105, 137, 793, 914, 225, 636, 60, 171, 490, 180, 414, 141, 399, 599, 829, 288, 108, 268, 444, 481, 795, 146, 655, 778, 189, 32, 597, 206, 208, 711, 845, 608, 642, 636, 540, 795, 845, 466, 492, 659, 138, 800, 912, 171, 92, 438, 225, 301, 777, 449, 230, 448, 326, 182, 892, 681, 543, 582, 732, 758, 162, 587, 685, 378, 646, 356, 354, 25, 839, 839, 556, 253, 501, 771, 745, 616, 473, 293, 669, 822, 613, 684, 229, 265, 110, 438, 144, 727, 317, 605, 414, 497, 82, 278, 267, 323, 43, 894, 624, 282, 790, 579, 430, 255, 802, 553, 922, 604, 68, 692, 809, 909, 663, 589, 735, 670, 298, 158, 201, 68, 124, 64, 67, 338, 694, 373, 225, 579, 309, 699, 920, 432, 717, 72, 126, 819, 142, 755, 473, 630, 331, 758, 730, 65, 359, 451, 236, 16, 56, 31, 87, 587, 125, 385, 384, 197, 352, 383, 173, 271, 38, 558, 810, 260, 521, 680, 7, 319, 650, 334, 695, 708, 0, 562, 365, 204, 114, 185, 560, 746, 767, 449, 797, 688, 63, 135, 818, 805, 3, 536, 908, 532, 400, 698, 49, 212, 630, 93, 157, 275, 3, 20, 611, 179, 302, 282, 876, 665, 241, 206, 474, 80, 217, 460, 462, 751, 719, 571, 536, 794, 522, 385, 598, 756, 162, 212, 758, 662, 361, 223, 587, 857, 503, 382, 615, 86, 283, 541, 847, 518, 406, 736, 486, 408, 226, 342, 784, 772, 211, 888, 234, 335}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 7")
}
func TestReedSolomonComputeLevel8(t *testing.T) {
var level securitylevel = 8
expected := []int{538, 446, 840, 510, 163, 708, 177, 666, 423, 600, 707, 913, 770, 571, 156, 683, 676, 697, 898, 776, 128, 851, 163, 854, 135, 661, 880, 279, 92, 324, 397, 207, 379, 223, 574, 9, 70, 858, 878, 579, 61, 551, 261, 388, 315, 856, 266, 865, 923, 38, 313, 62, 381, 198, 265, 256, 385, 878, 347, 532, 821, 53, 855, 225, 697, 826, 263, 334, 207, 565, 460, 496, 705, 599, 383, 289, 178, 168, 401, 268, 555, 190, 922, 284, 180, 810, 891, 832, 636, 813, 894, 495, 701, 484, 204, 793, 129, 164, 444, 228, 636, 98, 809, 57, 736, 697, 727, 534, 889, 480, 898, 773, 234, 851, 880, 843, 714, 443, 412, 489, 578, 468, 367, 663, 11, 686, 319, 352, 345, 670, 106, 106, 219, 466, 439, 350, 538, 66, 852, 175, 465, 731, 332, 110, 926, 491, 18, 422, 736, 797, 624, 376, 728, 526, 735, 200, 502, 923, 789, 529, 923, 706, 384, 869, 172, 548, 520, 463, 813, 384, 793, 231, 190, 653, 864, 351, 400, 525, 487, 828, 654, 307, 141, 638, 770, 775, 282, 54, 758, 197, 492, 320, 86, 790, 275, 237, 923, 25, 591, 605, 61, 824, 79, 631, 532, 337, 867, 423, 340, 597, 682, 923, 287, 408, 503, 361, 881, 196, 468, 759, 746, 389, 124, 784, 198, 865, 538, 451, 178, 772, 653, 121, 497, 598, 711, 716, 241, 159, 429, 88, 799, 761, 639, 105, 54, 807, 351, 435, 793, 873, 360, 8, 881, 479, 693, 576, 849, 875, 771, 621, 134, 863, 8, 171, 799, 924, 103, 63, 491, 538, 597, 855, 697, 499, 7, 886, 286, 85, 107, 220, 319, 124, 197, 150, 729, 899, 585, 540, 676, 414, 256, 856, 596, 259, 882, 436, 26, 273, 753, 127, 679, 390, 654, 42, 276, 420, 247, 629, 116, 803, 131, 25, 403, 645, 462, 897, 151, 622, 108, 167, 227, 831, 887, 662, 739, 263, 829, 56, 624, 317, 908, 378, 39, 393, 861, 338, 202, 179, 907, 109, 360, 736, 554, 342, 594, 125, 433, 394, 195, 698, 844, 912, 530, 842, 337, 294, 528, 231, 735, 93, 8, 579, 42, 148, 609, 233, 782, 887, 888, 915, 620, 78, 137, 161, 282, 217, 775, 564, 33, 195, 36, 584, 679, 775, 476, 309, 230, 303, 708, 143, 679, 502, 814, 193, 508, 532, 542, 580, 603, 641, 338, 361, 542, 537, 810, 394, 764, 136, 167, 611, 881, 775, 267, 433, 142, 202, 828, 363, 101, 728, 660, 583, 483, 786, 717, 190, 809, 422, 567, 741, 695, 310, 120, 177, 47, 494, 345, 508, 16, 639, 402, 625, 286, 298, 358, 54, 705, 916, 291, 424, 375, 883, 655, 675, 498, 498, 884, 862, 365, 310, 805, 763, 855, 354, 777, 543, 53, 773, 120, 408, 234, 728, 438, 914, 3, 670, 546, 465, 449, 923, 51, 546, 709, 648, 96, 320, 682, 326, 848, 234, 855, 791, 20, 97, 901, 351, 317, 764, 767, 312, 206, 139, 610, 578, 646, 264, 389, 238, 675, 595, 430, 88}
compareIntSlice(t, expected, level.Compute(inputData), "SecLvl 8")
}

354
vendor/github.com/boombuler/barcode/pdf417/highlevel.go generated vendored Normal file
View File

@@ -0,0 +1,354 @@
package pdf417
import (
"errors"
"math/big"
"github.com/boombuler/barcode/utils"
)
type encodingMode byte
type subMode byte
const (
encText encodingMode = iota
encNumeric
encBinary
subUpper subMode = iota
subLower
subMixed
subPunct
latch_to_text = 900
latch_to_byte_padded = 901
latch_to_numeric = 902
latch_to_byte = 924
shift_to_byte = 913
min_numeric_count = 13
)
var (
mixedMap map[rune]int
punctMap map[rune]int
)
func init() {
mixedMap = make(map[rune]int)
mixedRaw := []rune{
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 38, 13, 9, 44, 58,
35, 45, 46, 36, 47, 43, 37, 42, 61, 94, 0, 32, 0, 0, 0,
}
for idx, ch := range mixedRaw {
if ch > 0 {
mixedMap[ch] = idx
}
}
punctMap = make(map[rune]int)
punctRaw := []rune{
59, 60, 62, 64, 91, 92, 93, 95, 96, 126, 33, 13, 9, 44, 58,
10, 45, 46, 36, 47, 34, 124, 42, 40, 41, 63, 123, 125, 39, 0,
}
for idx, ch := range punctRaw {
if ch > 0 {
punctMap[ch] = idx
}
}
}
func determineConsecutiveDigitCount(data []rune) int {
cnt := 0
for _, r := range data {
if utils.RuneToInt(r) == -1 {
break
}
cnt++
}
return cnt
}
func encodeNumeric(digits []rune) ([]int, error) {
digitCount := len(digits)
chunkCount := digitCount / 44
if digitCount%44 != 0 {
chunkCount++
}
codeWords := []int{}
for i := 0; i < chunkCount; i++ {
start := i * 44
end := start + 44
if end > digitCount {
end = digitCount
}
chunk := digits[start:end]
chunkNum := big.NewInt(0)
_, ok := chunkNum.SetString("1"+string(chunk), 10)
if !ok {
return nil, errors.New("Failed converting: " + string(chunk))
}
cws := []int{}
for chunkNum.Cmp(big.NewInt(0)) > 0 {
newChunk, cw := chunkNum.DivMod(chunkNum, big.NewInt(900), big.NewInt(0))
chunkNum = newChunk
cws = append([]int{int(cw.Int64())}, cws...)
}
codeWords = append(codeWords, cws...)
}
return codeWords, nil
}
func determineConsecutiveTextCount(msg []rune) int {
result := 0
isText := func(ch rune) bool {
return ch == '\t' || ch == '\n' || ch == '\r' || (ch >= 32 && ch <= 126)
}
for i, ch := range msg {
numericCount := determineConsecutiveDigitCount(msg[i:])
if numericCount >= min_numeric_count || (numericCount == 0 && !isText(ch)) {
break
}
result++
}
return result
}
func encodeText(text []rune, submode subMode) (subMode, []int) {
isAlphaUpper := func(ch rune) bool {
return ch == ' ' || (ch >= 'A' && ch <= 'Z')
}
isAlphaLower := func(ch rune) bool {
return ch == ' ' || (ch >= 'a' && ch <= 'z')
}
isMixed := func(ch rune) bool {
_, ok := mixedMap[ch]
return ok
}
isPunctuation := func(ch rune) bool {
_, ok := punctMap[ch]
return ok
}
idx := 0
var tmp []int
for idx < len(text) {
ch := text[idx]
switch submode {
case subUpper:
if isAlphaUpper(ch) {
if ch == ' ' {
tmp = append(tmp, 26) //space
} else {
tmp = append(tmp, int(ch-'A'))
}
} else {
if isAlphaLower(ch) {
submode = subLower
tmp = append(tmp, 27) // lower latch
continue
} else if isMixed(ch) {
submode = subMixed
tmp = append(tmp, 28) // mixed latch
continue
} else {
tmp = append(tmp, 29) // punctuation switch
tmp = append(tmp, punctMap[ch])
break
}
}
break
case subLower:
if isAlphaLower(ch) {
if ch == ' ' {
tmp = append(tmp, 26) //space
} else {
tmp = append(tmp, int(ch-'a'))
}
} else {
if isAlphaUpper(ch) {
tmp = append(tmp, 27) //upper switch
tmp = append(tmp, int(ch-'A'))
break
} else if isMixed(ch) {
submode = subMixed
tmp = append(tmp, 28) //mixed latch
continue
} else {
tmp = append(tmp, 29) //punctuation switch
tmp = append(tmp, punctMap[ch])
break
}
}
break
case subMixed:
if isMixed(ch) {
tmp = append(tmp, mixedMap[ch])
} else {
if isAlphaUpper(ch) {
submode = subUpper
tmp = append(tmp, 28) //upper latch
continue
} else if isAlphaLower(ch) {
submode = subLower
tmp = append(tmp, 27) //lower latch
continue
} else {
if idx+1 < len(text) {
next := text[idx+1]
if isPunctuation(next) {
submode = subPunct
tmp = append(tmp, 25) //punctuation latch
continue
}
}
tmp = append(tmp, 29) //punctuation switch
tmp = append(tmp, punctMap[ch])
}
}
break
default: //subPunct
if isPunctuation(ch) {
tmp = append(tmp, punctMap[ch])
} else {
submode = subUpper
tmp = append(tmp, 29) //upper latch
continue
}
}
idx++
}
h := 0
result := []int{}
for i, val := range tmp {
if i%2 != 0 {
h = (h * 30) + val
result = append(result, h)
} else {
h = val
}
}
if len(tmp)%2 != 0 {
result = append(result, (h*30)+29)
}
return submode, result
}
func determineConsecutiveBinaryCount(msg []byte) int {
result := 0
for i, _ := range msg {
numericCount := determineConsecutiveDigitCount([]rune(string(msg[i:])))
if numericCount >= min_numeric_count {
break
}
textCount := determineConsecutiveTextCount([]rune(string(msg[i:])))
if textCount > 5 {
break
}
result++
}
return result
}
func encodeBinary(data []byte, startmode encodingMode) []int {
result := []int{}
count := len(data)
if count == 1 && startmode == encText {
result = append(result, shift_to_byte)
} else if (count % 6) == 0 {
result = append(result, latch_to_byte)
} else {
result = append(result, latch_to_byte_padded)
}
idx := 0
// Encode sixpacks
if count >= 6 {
words := make([]int, 5)
for (count - idx) >= 6 {
var t int64 = 0
for i := 0; i < 6; i++ {
t = t << 8
t += int64(data[idx+i])
}
for i := 0; i < 5; i++ {
words[4-i] = int(t % 900)
t = t / 900
}
result = append(result, words...)
idx += 6
}
}
//Encode rest (remaining n<5 bytes if any)
for i := idx; i < count; i++ {
result = append(result, int(data[i]&0xff))
}
return result
}
func highlevelEncode(dataStr string) ([]int, error) {
encodingMode := encText
textSubMode := subUpper
result := []int{}
data := []byte(dataStr)
for len(data) > 0 {
numericCount := determineConsecutiveDigitCount([]rune(string(data)))
if numericCount >= min_numeric_count || numericCount == len(data) {
result = append(result, latch_to_numeric)
encodingMode = encNumeric
textSubMode = subUpper
numData, err := encodeNumeric([]rune(string(data[:numericCount])))
if err != nil {
return nil, err
}
result = append(result, numData...)
data = data[numericCount:]
} else {
textCount := determineConsecutiveTextCount([]rune(string(data)))
if textCount >= 5 || textCount == len(data) {
if encodingMode != encText {
result = append(result, latch_to_text)
encodingMode = encText
textSubMode = subUpper
}
var txtData []int
textSubMode, txtData = encodeText([]rune(string(data[:textCount])), textSubMode)
result = append(result, txtData...)
data = data[textCount:]
} else {
binaryCount := determineConsecutiveBinaryCount(data)
if binaryCount == 0 {
binaryCount = 1
}
bytes := data[:binaryCount]
if len(bytes) != 1 || encodingMode != encText {
encodingMode = encBinary
textSubMode = subUpper
}
byteData := encodeBinary(bytes, encodingMode)
result = append(result, byteData...)
data = data[binaryCount:]
}
}
}
return result, nil
}

View File

@@ -0,0 +1,41 @@
package pdf417
import "testing"
func compareIntSlice(t *testing.T, expected, actual []int, testStr string) {
if len(actual) != len(expected) {
t.Errorf("Invalid slice size. Expected %d got %d while encoding %q", len(expected), len(actual), testStr)
return
}
for i, a := range actual {
if e := expected[i]; e != a {
t.Errorf("Unexpected value at position %d. Expected %d got %d while encoding %q", i, e, a, testStr)
}
}
}
func TestHighlevelEncode(t *testing.T) {
runTest := func(msg string, expected ...int) {
if codes, err := highlevelEncode(msg); err != nil {
t.Error(err)
} else {
compareIntSlice(t, expected, codes, msg)
}
}
runTest("01234", 902, 112, 434)
runTest("Super !", 567, 615, 137, 809, 329)
runTest("Super ", 567, 615, 137, 809)
runTest("ABC123", 1, 88, 32, 119)
runTest("123ABC", 841, 63, 840, 32)
}
func TestBinaryEncoder(t *testing.T) {
runTest := func(msg string, expected ...int) {
codes := encodeBinary([]byte(msg), encText)
compareIntSlice(t, expected, codes, msg)
}
runTest("alcool", 924, 163, 238, 432, 766, 244)
runTest("alcoolique", 901, 163, 238, 432, 766, 244, 105, 113, 117, 101)
}

40
vendor/github.com/boombuler/barcode/pdf417/pdfcode.go generated vendored Normal file
View File

@@ -0,0 +1,40 @@
package pdf417
import (
"image"
"image/color"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type pdfBarcode struct {
data string
width int
code *utils.BitList
}
func (c *pdfBarcode) Metadata() barcode.Metadata {
return barcode.Metadata{barcode.TypePDF, 2}
}
func (c *pdfBarcode) Content() string {
return c.data
}
func (c *pdfBarcode) ColorModel() color.Model {
return color.Gray16Model
}
func (c *pdfBarcode) Bounds() image.Rectangle {
height := c.code.Len() / c.width
return image.Rect(0, 0, c.width, height*moduleHeight)
}
func (c *pdfBarcode) At(x, y int) color.Color {
if c.code.GetBit((y/moduleHeight)*c.width + x) {
return color.Black
}
return color.White
}

66
vendor/github.com/boombuler/barcode/qr/alphanumeric.go generated vendored Normal file
View File

@@ -0,0 +1,66 @@
package qr
import (
"errors"
"fmt"
"strings"
"github.com/boombuler/barcode/utils"
)
const charSet string = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
func stringToAlphaIdx(content string) <-chan int {
result := make(chan int)
go func() {
for _, r := range content {
idx := strings.IndexRune(charSet, r)
result <- idx
if idx < 0 {
break
}
}
close(result)
}()
return result
}
func encodeAlphaNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
contentLenIsOdd := len(content)%2 == 1
contentBitCount := (len(content) / 2) * 11
if contentLenIsOdd {
contentBitCount += 6
}
vi := findSmallestVersionInfo(ecl, alphaNumericMode, contentBitCount)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
res := new(utils.BitList)
res.AddBits(int(alphaNumericMode), 4)
res.AddBits(len(content), vi.charCountBits(alphaNumericMode))
encoder := stringToAlphaIdx(content)
for idx := 0; idx < len(content)/2; idx++ {
c1 := <-encoder
c2 := <-encoder
if c1 < 0 || c2 < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric)
}
res.AddBits(c1*45+c2, 11)
}
if contentLenIsOdd {
c := <-encoder
if c < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, AlphaNumeric)
}
res.AddBits(c, 6)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}

View File

@@ -0,0 +1,44 @@
package qr
import (
"bytes"
"testing"
)
func makeString(length int, content string) string {
res := ""
for i := 0; i < length; i++ {
res += content
}
return res
}
func Test_AlphaNumericEncoding(t *testing.T) {
encode := AlphaNumeric.getEncoder()
x, vi, err := encode("HELLO WORLD", M)
if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{32, 91, 11, 120, 209, 114, 220, 77, 67, 64, 236, 17, 236, 17, 236, 17}) != 0 {
t.Errorf("\"HELLO WORLD\" failed to encode: %s", err)
}
x, vi, err = encode(makeString(4296, "A"), L)
if x == nil || vi == nil || err != nil {
t.Fail()
}
x, vi, err = encode(makeString(4297, "A"), L)
if x != nil || vi != nil || err == nil {
t.Fail()
}
x, vi, err = encode("ABc", L)
if x != nil || vi != nil || err == nil {
t.Fail()
}
x, vi, err = encode("hello world", M)
if x != nil || vi != nil || err == nil {
t.Error("\"hello world\" should not be encodable in alphanumeric mode")
}
}

23
vendor/github.com/boombuler/barcode/qr/automatic.go generated vendored Normal file
View File

@@ -0,0 +1,23 @@
package qr
import (
"fmt"
"github.com/boombuler/barcode/utils"
)
func encodeAuto(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
bits, vi, _ := Numeric.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
bits, vi, _ = AlphaNumeric.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
bits, vi, _ = Unicode.getEncoder()(content, ecl)
if bits != nil && vi != nil {
return bits, vi, nil
}
return nil, nil, fmt.Errorf("No encoding found to encode \"%s\"", content)
}

View File

@@ -0,0 +1,30 @@
package qr
import (
"bytes"
"testing"
)
func Test_AutomaticEncoding(t *testing.T) {
tests := map[string]encodeFn{
"0123456789": Numeric.getEncoder(),
"ALPHA NUMERIC": AlphaNumeric.getEncoder(),
"unicode encoing": Unicode.getEncoder(),
"very long unicode encoding" + makeString(3000, "A"): nil,
}
for str, enc := range tests {
testValue, _, _ := Auto.getEncoder()(str, M)
if enc != nil {
correctValue, _, _ := enc(str, M)
if testValue == nil || bytes.Compare(correctValue.GetBytes(), testValue.GetBytes()) != 0 {
t.Errorf("wrong encoding used for '%s'", str)
}
} else {
if testValue != nil {
t.Errorf("wrong encoding used for '%s'", str)
}
}
}
}

59
vendor/github.com/boombuler/barcode/qr/blocks.go generated vendored Normal file
View File

@@ -0,0 +1,59 @@
package qr
type block struct {
data []byte
ecc []byte
}
type blockList []*block
func splitToBlocks(data <-chan byte, vi *versionInfo) blockList {
result := make(blockList, vi.NumberOfBlocksInGroup1+vi.NumberOfBlocksInGroup2)
for b := 0; b < int(vi.NumberOfBlocksInGroup1); b++ {
blk := new(block)
blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup1)
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup1); cw++ {
blk.data[cw] = <-data
}
blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
result[b] = blk
}
for b := 0; b < int(vi.NumberOfBlocksInGroup2); b++ {
blk := new(block)
blk.data = make([]byte, vi.DataCodeWordsPerBlockInGroup2)
for cw := 0; cw < int(vi.DataCodeWordsPerBlockInGroup2); cw++ {
blk.data[cw] = <-data
}
blk.ecc = ec.calcECC(blk.data, vi.ErrorCorrectionCodewordsPerBlock)
result[int(vi.NumberOfBlocksInGroup1)+b] = blk
}
return result
}
func (bl blockList) interleave(vi *versionInfo) []byte {
var maxCodewordCount int
if vi.DataCodeWordsPerBlockInGroup1 > vi.DataCodeWordsPerBlockInGroup2 {
maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup1)
} else {
maxCodewordCount = int(vi.DataCodeWordsPerBlockInGroup2)
}
resultLen := (vi.DataCodeWordsPerBlockInGroup1+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup1 +
(vi.DataCodeWordsPerBlockInGroup2+vi.ErrorCorrectionCodewordsPerBlock)*vi.NumberOfBlocksInGroup2
result := make([]byte, 0, resultLen)
for i := 0; i < maxCodewordCount; i++ {
for b := 0; b < len(bl); b++ {
if len(bl[b].data) > i {
result = append(result, bl[b].data[i])
}
}
}
for i := 0; i < int(vi.ErrorCorrectionCodewordsPerBlock); i++ {
for b := 0; b < len(bl); b++ {
result = append(result, bl[b].ecc[i])
}
}
return result
}

36
vendor/github.com/boombuler/barcode/qr/blocks_test.go generated vendored Normal file
View File

@@ -0,0 +1,36 @@
package qr
import (
"bytes"
"testing"
)
func Test_Blocks(t *testing.T) {
byteIt := make(chan byte)
go func() {
for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} {
byteIt <- b
}
close(byteIt)
}()
vi := &versionInfo{5, Q, 18, 2, 15, 2, 16}
data := splitToBlocks(byteIt, vi).interleave(vi)
if bytes.Compare(data, []byte{67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236}) != 0 {
t.Fail()
}
byteIt2 := make(chan byte)
go func() {
for _, b := range []byte{67, 85, 70, 134, 87, 38, 85, 194, 119, 50, 6, 18, 6, 103, 38, 246, 246, 66, 7, 118, 134, 242, 7, 38, 86, 22, 198, 199, 146, 6, 182, 230, 247, 119, 50, 7, 118, 134, 87, 38, 82, 6, 134, 151, 50, 7, 70, 247, 118, 86, 194, 6, 151, 50, 16, 236, 17, 236, 17, 236, 17, 236} {
byteIt2 <- b
}
close(byteIt2)
}()
vi = &versionInfo{5, Q, 18, 2, 16, 2, 15}
data = splitToBlocks(byteIt2, vi).interleave(vi)
if bytes.Compare(data, []byte{67, 246, 247, 247, 85, 66, 119, 118, 70, 7, 50, 86, 134, 118, 7, 194, 87, 134, 118, 6, 38, 242, 134, 151, 85, 7, 87, 50, 194, 38, 38, 16, 119, 86, 82, 236, 50, 22, 6, 17, 6, 198, 134, 236, 18, 199, 151, 17, 6, 146, 50, 236, 103, 6, 7, 17, 38, 182, 70, 236, 246, 230, 71, 101, 27, 62, 13, 91, 166, 86, 138, 16, 78, 229, 102, 11, 199, 107, 2, 182, 132, 103, 89, 66, 136, 69, 78, 255, 116, 129, 126, 163, 219, 234, 158, 216, 42, 234, 97, 62, 186, 59, 123, 148, 220, 191, 254, 145, 82, 95, 129, 79, 236, 254, 30, 174, 228, 50, 181, 110, 150, 205, 34, 235, 242, 0, 115, 147, 58, 243, 28, 140, 221, 219}) != 0 {
t.Fail()
}
}

416
vendor/github.com/boombuler/barcode/qr/encoder.go generated vendored Normal file
View File

@@ -0,0 +1,416 @@
// Package qr can be used to create QR barcodes.
package qr
import (
"image"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error)
// Encoding mode for QR Codes.
type Encoding byte
const (
// Auto will choose ths best matching encoding
Auto Encoding = iota
// Numeric encoding only encodes numbers [0-9]
Numeric
// AlphaNumeric encoding only encodes uppercase letters, numbers and [Space], $, %, *, +, -, ., /, :
AlphaNumeric
// Unicode encoding encodes the string as utf-8
Unicode
// only for testing purpose
unknownEncoding
)
func (e Encoding) getEncoder() encodeFn {
switch e {
case Auto:
return encodeAuto
case Numeric:
return encodeNumeric
case AlphaNumeric:
return encodeAlphaNumeric
case Unicode:
return encodeUnicode
}
return nil
}
func (e Encoding) String() string {
switch e {
case Auto:
return "Auto"
case Numeric:
return "Numeric"
case AlphaNumeric:
return "AlphaNumeric"
case Unicode:
return "Unicode"
}
return ""
}
// Encode returns a QR barcode with the given content, error correction level and uses the given encoding
func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (barcode.Barcode, error) {
bits, vi, err := mode.getEncoder()(content, level)
if err != nil {
return nil, err
}
blocks := splitToBlocks(bits.IterateBytes(), vi)
data := blocks.interleave(vi)
result := render(data, vi)
result.content = content
return result, nil
}
func render(data []byte, vi *versionInfo) *qrcode {
dim := vi.modulWidth()
results := make([]*qrcode, 8)
for i := 0; i < 8; i++ {
results[i] = newBarcode(dim)
}
occupied := newBarcode(dim)
setAll := func(x int, y int, val bool) {
occupied.Set(x, y, true)
for i := 0; i < 8; i++ {
results[i].Set(x, y, val)
}
}
drawFinderPatterns(vi, setAll)
drawAlignmentPatterns(occupied, vi, setAll)
//Timing Pattern:
var i int
for i = 0; i < dim; i++ {
if !occupied.Get(i, 6) {
setAll(i, 6, i%2 == 0)
}
if !occupied.Get(6, i) {
setAll(6, i, i%2 == 0)
}
}
// Dark Module
setAll(8, dim-8, true)
drawVersionInfo(vi, setAll)
drawFormatInfo(vi, -1, occupied.Set)
for i := 0; i < 8; i++ {
drawFormatInfo(vi, i, results[i].Set)
}
// Write the data
var curBitNo int
for pos := range iterateModules(occupied) {
var curBit bool
if curBitNo < len(data)*8 {
curBit = ((data[curBitNo/8] >> uint(7-(curBitNo%8))) & 1) == 1
} else {
curBit = false
}
for i := 0; i < 8; i++ {
setMasked(pos.X, pos.Y, curBit, i, results[i].Set)
}
curBitNo++
}
lowestPenalty := ^uint(0)
lowestPenaltyIdx := -1
for i := 0; i < 8; i++ {
p := results[i].calcPenalty()
if p < lowestPenalty {
lowestPenalty = p
lowestPenaltyIdx = i
}
}
return results[lowestPenaltyIdx]
}
func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) {
switch mask {
case 0:
val = val != (((y + x) % 2) == 0)
break
case 1:
val = val != ((y % 2) == 0)
break
case 2:
val = val != ((x % 3) == 0)
break
case 3:
val = val != (((y + x) % 3) == 0)
break
case 4:
val = val != (((y/2 + x/3) % 2) == 0)
break
case 5:
val = val != (((y*x)%2)+((y*x)%3) == 0)
break
case 6:
val = val != ((((y*x)%2)+((y*x)%3))%2 == 0)
break
case 7:
val = val != ((((y+x)%2)+((y*x)%3))%2 == 0)
}
set(x, y, val)
}
func iterateModules(occupied *qrcode) <-chan image.Point {
result := make(chan image.Point)
allPoints := make(chan image.Point)
go func() {
curX := occupied.dimension - 1
curY := occupied.dimension - 1
isUpward := true
for true {
if isUpward {
allPoints <- image.Pt(curX, curY)
allPoints <- image.Pt(curX-1, curY)
curY--
if curY < 0 {
curY = 0
curX -= 2
if curX == 6 {
curX--
}
if curX < 0 {
break
}
isUpward = false
}
} else {
allPoints <- image.Pt(curX, curY)
allPoints <- image.Pt(curX-1, curY)
curY++
if curY >= occupied.dimension {
curY = occupied.dimension - 1
curX -= 2
if curX == 6 {
curX--
}
isUpward = true
if curX < 0 {
break
}
}
}
}
close(allPoints)
}()
go func() {
for pt := range allPoints {
if !occupied.Get(pt.X, pt.Y) {
result <- pt
}
}
close(result)
}()
return result
}
func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) {
dim := vi.modulWidth()
drawPattern := func(xoff int, yoff int) {
for x := -1; x < 8; x++ {
for y := -1; y < 8; y++ {
val := (x == 0 || x == 6 || y == 0 || y == 6 || (x > 1 && x < 5 && y > 1 && y < 5)) && (x <= 6 && y <= 6 && x >= 0 && y >= 0)
if x+xoff >= 0 && x+xoff < dim && y+yoff >= 0 && y+yoff < dim {
set(x+xoff, y+yoff, val)
}
}
}
}
drawPattern(0, 0)
drawPattern(0, dim-7)
drawPattern(dim-7, 0)
}
func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(int, int, bool)) {
drawPattern := func(xoff int, yoff int) {
for x := -2; x <= 2; x++ {
for y := -2; y <= 2; y++ {
val := x == -2 || x == 2 || y == -2 || y == 2 || (x == 0 && y == 0)
set(x+xoff, y+yoff, val)
}
}
}
positions := vi.alignmentPatternPlacements()
for _, x := range positions {
for _, y := range positions {
if occupied.Get(x, y) {
continue
}
drawPattern(x, y)
}
}
}
var formatInfos = map[ErrorCorrectionLevel]map[int][]bool{
L: {
0: []bool{true, true, true, false, true, true, true, true, true, false, false, false, true, false, false},
1: []bool{true, true, true, false, false, true, false, true, true, true, true, false, false, true, true},
2: []bool{true, true, true, true, true, false, true, true, false, true, false, true, false, true, false},
3: []bool{true, true, true, true, false, false, false, true, false, false, true, true, true, false, true},
4: []bool{true, true, false, false, true, true, false, false, false, true, false, true, true, true, true},
5: []bool{true, true, false, false, false, true, true, false, false, false, true, true, false, false, false},
6: []bool{true, true, false, true, true, false, false, false, true, false, false, false, false, false, true},
7: []bool{true, true, false, true, false, false, true, false, true, true, true, false, true, true, false},
},
M: {
0: []bool{true, false, true, false, true, false, false, false, false, false, true, false, false, true, false},
1: []bool{true, false, true, false, false, false, true, false, false, true, false, false, true, false, true},
2: []bool{true, false, true, true, true, true, false, false, true, true, true, true, true, false, false},
3: []bool{true, false, true, true, false, true, true, false, true, false, false, true, false, true, true},
4: []bool{true, false, false, false, true, false, true, true, true, true, true, true, false, false, true},
5: []bool{true, false, false, false, false, false, false, true, true, false, false, true, true, true, false},
6: []bool{true, false, false, true, true, true, true, true, false, false, true, false, true, true, true},
7: []bool{true, false, false, true, false, true, false, true, false, true, false, false, false, false, false},
},
Q: {
0: []bool{false, true, true, false, true, false, true, false, true, false, true, true, true, true, true},
1: []bool{false, true, true, false, false, false, false, false, true, true, false, true, false, false, false},
2: []bool{false, true, true, true, true, true, true, false, false, true, true, false, false, false, true},
3: []bool{false, true, true, true, false, true, false, false, false, false, false, false, true, true, false},
4: []bool{false, true, false, false, true, false, false, true, false, true, true, false, true, false, false},
5: []bool{false, true, false, false, false, false, true, true, false, false, false, false, false, true, true},
6: []bool{false, true, false, true, true, true, false, true, true, false, true, true, false, true, false},
7: []bool{false, true, false, true, false, true, true, true, true, true, false, true, true, false, true},
},
H: {
0: []bool{false, false, true, false, true, true, false, true, false, false, false, true, false, false, true},
1: []bool{false, false, true, false, false, true, true, true, false, true, true, true, true, true, false},
2: []bool{false, false, true, true, true, false, false, true, true, true, false, false, true, true, true},
3: []bool{false, false, true, true, false, false, true, true, true, false, true, false, false, false, false},
4: []bool{false, false, false, false, true, true, true, false, true, true, false, false, false, true, false},
5: []bool{false, false, false, false, false, true, false, false, true, false, true, false, true, false, true},
6: []bool{false, false, false, true, true, false, true, false, false, false, false, true, true, false, false},
7: []bool{false, false, false, true, false, false, false, false, false, true, true, true, false, true, true},
},
}
func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bool)) {
var formatInfo []bool
if usedMask == -1 {
formatInfo = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} // Set all to true cause -1 --> occupied mask.
} else {
formatInfo = formatInfos[vi.Level][usedMask]
}
if len(formatInfo) == 15 {
dim := vi.modulWidth()
set(0, 8, formatInfo[0])
set(1, 8, formatInfo[1])
set(2, 8, formatInfo[2])
set(3, 8, formatInfo[3])
set(4, 8, formatInfo[4])
set(5, 8, formatInfo[5])
set(7, 8, formatInfo[6])
set(8, 8, formatInfo[7])
set(8, 7, formatInfo[8])
set(8, 5, formatInfo[9])
set(8, 4, formatInfo[10])
set(8, 3, formatInfo[11])
set(8, 2, formatInfo[12])
set(8, 1, formatInfo[13])
set(8, 0, formatInfo[14])
set(8, dim-1, formatInfo[0])
set(8, dim-2, formatInfo[1])
set(8, dim-3, formatInfo[2])
set(8, dim-4, formatInfo[3])
set(8, dim-5, formatInfo[4])
set(8, dim-6, formatInfo[5])
set(8, dim-7, formatInfo[6])
set(dim-8, 8, formatInfo[7])
set(dim-7, 8, formatInfo[8])
set(dim-6, 8, formatInfo[9])
set(dim-5, 8, formatInfo[10])
set(dim-4, 8, formatInfo[11])
set(dim-3, 8, formatInfo[12])
set(dim-2, 8, formatInfo[13])
set(dim-1, 8, formatInfo[14])
}
}
var versionInfoBitsByVersion = map[byte][]bool{
7: []bool{false, false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false},
8: []bool{false, false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false},
9: []bool{false, false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true},
10: []bool{false, false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true},
11: []bool{false, false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false},
12: []bool{false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false},
13: []bool{false, false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true},
14: []bool{false, false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true},
15: []bool{false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false},
16: []bool{false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false},
17: []bool{false, true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true},
18: []bool{false, true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true},
19: []bool{false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false},
20: []bool{false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true, false},
21: []bool{false, true, false, true, false, true, false, true, true, false, true, false, false, false, false, false, true, true},
22: []bool{false, true, false, true, true, false, true, false, false, false, true, true, false, false, true, false, false, true},
23: []bool{false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false, false},
24: []bool{false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false, false},
25: []bool{false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, false, false, true},
26: []bool{false, true, true, false, true, false, true, true, true, true, true, false, true, false, true, false, true, true},
27: []bool{false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true, false},
28: []bool{false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true, false},
29: []bool{false, true, true, true, false, true, false, false, true, true, false, false, true, true, true, true, true, true},
30: []bool{false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, true, false, true},
31: []bool{false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false, false},
32: []bool{true, false, false, false, false, false, true, false, false, true, true, true, false, true, false, true, false, true},
33: []bool{true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false, false},
34: []bool{true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true, false},
35: []bool{true, false, false, false, true, true, false, true, true, true, true, false, false, true, true, true, true, true},
36: []bool{true, false, false, true, false, false, true, false, true, true, false, false, false, false, true, false, true, true},
37: []bool{true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true, false},
38: []bool{true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false},
39: []bool{true, false, false, true, true, true, false, true, false, true, false, true, false, false, false, false, false, true},
40: []bool{true, false, true, false, false, false, true, true, false, false, false, true, true, false, true, false, false, true},
}
func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) {
versionInfoBits, ok := versionInfoBitsByVersion[vi.Version]
if ok && len(versionInfoBits) > 0 {
for i := 0; i < len(versionInfoBits); i++ {
x := (vi.modulWidth() - 11) + i%3
y := i / 3
set(x, y, versionInfoBits[len(versionInfoBits)-i-1])
set(y, x, versionInfoBits[len(versionInfoBits)-i-1])
}
}
}
func addPaddingAndTerminator(bl *utils.BitList, vi *versionInfo) {
for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ {
bl.AddBit(false)
}
for bl.Len()%8 != 0 {
bl.AddBit(false)
}
for i := 0; bl.Len() < vi.totalDataBytes()*8; i++ {
if i%2 == 0 {
bl.AddByte(236)
} else {
bl.AddByte(17)
}
}
}

134
vendor/github.com/boombuler/barcode/qr/encoder_test.go generated vendored Normal file
View File

@@ -0,0 +1,134 @@
package qr
import (
"fmt"
"image/png"
"os"
"testing"
"github.com/boombuler/barcode"
)
type test struct {
Text string
Mode Encoding
ECL ErrorCorrectionLevel
Result string
}
var tests = []test{
test{
Text: "hello world",
Mode: Unicode,
ECL: H,
Result: `
+++++++.+.+.+...+.+++++++
+.....+.++...+++..+.....+
+.+++.+.+.+.++.++.+.+++.+
+.+++.+....++.++..+.+++.+
+.+++.+..+...++.+.+.+++.+
+.....+.+..+..+++.+.....+
+++++++.+.+.+.+.+.+++++++
........++..+..+.........
..+++.+.+++.+.++++++..+++
+++..+..+...++.+...+..+..
+...+.++++....++.+..++.++
++.+.+.++...+...+.+....++
..+..+++.+.+++++.++++++++
+.+++...+..++..++..+..+..
+.....+..+.+.....+++++.++
+.+++.....+...+.+.+++...+
+.+..+++...++.+.+++++++..
........+....++.+...+.+..
+++++++......++++.+.+.+++
+.....+....+...++...++.+.
+.+++.+.+.+...+++++++++..
+.+++.+.++...++...+.++..+
+.+++.+.++.+++++..++.+..+
+.....+..+++..++.+.++...+
+++++++....+..+.+..+..+++`,
},
}
func Test_GetUnknownEncoder(t *testing.T) {
if unknownEncoding.getEncoder() != nil {
t.Fail()
}
}
func Test_EncodingStringer(t *testing.T) {
tests := map[Encoding]string{
Auto: "Auto",
Numeric: "Numeric",
AlphaNumeric: "AlphaNumeric",
Unicode: "Unicode",
unknownEncoding: "",
}
for enc, str := range tests {
if enc.String() != str {
t.Fail()
}
}
}
func Test_InvalidEncoding(t *testing.T) {
_, err := Encode("hello world", H, Numeric)
if err == nil {
t.Fail()
}
}
func imgStrToBools(str string) []bool {
res := make([]bool, 0, len(str))
for _, r := range str {
if r == '+' {
res = append(res, true)
} else if r == '.' {
res = append(res, false)
}
}
return res
}
func Test_Encode(t *testing.T) {
for _, tst := range tests {
res, err := Encode(tst.Text, tst.ECL, tst.Mode)
if err != nil {
t.Error(err)
}
qrCode, ok := res.(*qrcode)
if !ok {
t.Fail()
}
testRes := imgStrToBools(tst.Result)
if (qrCode.dimension * qrCode.dimension) != len(testRes) {
t.Fail()
}
t.Logf("dim %d", qrCode.dimension)
for i := 0; i < len(testRes); i++ {
x := i % qrCode.dimension
y := i / qrCode.dimension
if qrCode.Get(x, y) != testRes[i] {
t.Errorf("Failed at index %d", i)
}
}
}
}
func ExampleEncode() {
f, _ := os.Create("qrcode.png")
defer f.Close()
qrcode, err := Encode("hello world", L, Auto)
if err != nil {
fmt.Println(err)
} else {
qrcode, err = barcode.Scale(qrcode, 100, 100)
if err != nil {
fmt.Println(err)
} else {
png.Encode(f, qrcode)
}
}
}

View File

@@ -0,0 +1,29 @@
package qr
import (
"github.com/boombuler/barcode/utils"
)
type errorCorrection struct {
rs *utils.ReedSolomonEncoder
}
var ec = newErrorCorrection()
func newErrorCorrection() *errorCorrection {
fld := utils.NewGaloisField(285, 256, 0)
return &errorCorrection{utils.NewReedSolomonEncoder(fld)}
}
func (ec *errorCorrection) calcECC(data []byte, eccCount byte) []byte {
dataInts := make([]int, len(data))
for i := 0; i < len(data); i++ {
dataInts[i] = int(data[i])
}
res := ec.rs.Encode(dataInts, int(eccCount))
result := make([]byte, len(res))
for i := 0; i < len(res); i++ {
result[i] = byte(res[i])
}
return result
}

View File

@@ -0,0 +1,60 @@
package qr
import (
"bytes"
"testing"
)
func Test_ErrorCorrection(t *testing.T) {
doTest := func(b []byte, ecc []byte) {
cnt := byte(len(ecc))
res := ec.calcECC(b, cnt)
if bytes.Compare(res, ecc) != 0 {
t.Errorf("ECC error!\nGot: %v\nExpected:%v", res, ecc)
}
}
// Issue #5
doTest([]byte{66, 196, 148, 21, 99, 19, 151, 151, 53, 149, 54, 195, 4, 133, 87, 84, 115, 85, 22, 148, 52, 71, 102, 68, 134, 182, 247, 119, 22, 68, 117, 134, 35, 4, 134, 38, 21, 84, 21, 117, 87, 164, 135, 115, 211, 208, 236, 17, 236, 17, 236, 17, 236, 17, 236}, []byte{187, 187, 171, 253, 164, 129, 104, 133, 3, 75, 87, 98, 241, 146, 138})
// Other tests
doTest([]byte{17, 168, 162, 241, 255, 205, 240, 179, 88, 101, 71, 130, 2, 54, 147, 111, 232, 58, 202, 171, 85, 22, 229, 187}, []byte{30, 142, 171, 131, 189})
doTest([]byte{36, 153, 55, 100, 228, 252, 0, 35, 85, 7, 237, 117, 182, 73, 83, 244, 8, 64, 55, 252, 200, 250, 72, 92, 97, 125, 96}, []byte{129, 124, 218, 148, 49, 108, 68, 255, 58, 212, 56, 60, 142, 45, 216, 124, 253, 214, 206, 208, 145, 169, 43})
doTest([]byte{250, 195, 230, 128, 31, 168, 86, 123, 244, 129, 74, 130, 222, 225, 140, 129, 114, 132, 128, 88, 96, 13, 165, 132, 116, 22, 42, 81, 219, 3, 102, 156, 69, 70, 90, 68, 7, 245, 150, 160, 252, 121, 20}, []byte{124, 23, 233, 71, 200, 211, 54, 141, 10, 23, 206, 147, 116, 35, 45, 218, 158, 193, 80, 194, 129, 147, 8, 78, 229, 112, 89, 161, 167, 203, 11, 245, 186, 187, 17, 7, 175})
doTest([]byte{121, 234, 24, 188, 218, 238, 248, 223, 98, 124, 237, 30, 98, 12, 9, 126, 5, 160, 240, 27, 174, 60, 152, 134, 71, 122, 125, 238, 223, 91, 231, 248, 230, 152, 250, 44, 17, 149, 0, 20, 109, 188, 227, 202}, []byte{209, 71, 225, 216, 240, 127, 111, 98, 194, 133, 114, 63, 35, 167, 184, 4, 209, 211, 40, 14, 74, 37, 21, 76, 95, 206, 90, 152, 110, 64, 6, 92, 80, 255, 127, 35, 111, 25, 1, 73})
doTest([]byte{165, 233, 141, 34, 247, 216, 35, 163, 61, 61, 81, 146, 116, 96, 113, 10, 0, 6, 148, 244, 55, 201, 17, 220, 109, 111}, []byte{93, 173, 231, 160})
doTest([]byte{173, 242, 89, 205, 24, 33, 213, 147, 96, 189, 100, 15, 213, 67, 91, 189, 218, 127, 32, 160, 162, 99, 187, 221, 53, 121, 238, 219, 215, 176, 181, 135, 56, 71, 246, 74, 228}, []byte{194, 130, 43, 168, 223, 144, 223, 49, 5, 162, 62, 218, 50, 205, 249, 84, 188, 25, 109, 110, 49, 224, 194, 244, 83, 221, 236, 71, 197, 159, 182})
doTest([]byte{82, 138, 221, 169, 67, 161, 132, 31, 243, 110, 83, 1, 238, 79, 255, 57, 74, 54, 123, 151, 159, 50, 250, 188, 176, 8, 221, 215, 141, 77, 16}, []byte{197, 122, 225, 65, 40, 69, 153, 100, 73, 245, 150, 213, 104, 127, 3})
doTest([]byte{5, 206, 21, 196, 185, 120, 60, 177, 90, 251, 109, 131, 174, 199, 55, 56, 14, 171, 19, 104, 236, 218, 31, 144, 33, 249, 58, 195, 173, 145, 166, 93, 122, 171, 232, 128, 233, 116, 144, 189, 62, 230, 68, 55, 140, 56, 1, 65, 165, 158, 127}, []byte{73, 141, 230, 252, 225, 173, 251, 194, 150, 98, 141, 241, 246, 11, 16, 8, 42})
doTest([]byte{112, 106, 43, 174, 133, 163, 192, 61, 121, 3, 200, 84, 15, 9, 3, 222, 183, 78, 153, 26, 85, 41, 5, 149, 232, 3, 233, 247, 249, 29, 15, 18, 4, 96, 9, 64, 188, 210}, []byte{16, 254, 143, 110, 63, 167, 213, 242, 95, 78, 215, 145, 231, 59, 158, 36, 149, 247, 123, 114, 247, 202, 15, 56, 229, 163, 186, 73, 82, 230, 111, 108, 111, 182, 193, 46, 116})
doTest([]byte{208, 128, 197, 227, 124, 226, 125, 46, 253, 98, 238, 80, 229, 134, 167, 70, 101, 150, 198, 130, 185, 200, 68, 91}, []byte{229, 167, 187, 39, 92, 90, 210, 25, 206, 237, 90, 194, 206, 39, 2, 11, 78, 48, 247})
doTest([]byte{79, 175, 255, 194, 34, 229, 234, 200, 74, 213, 100, 33, 24, 5, 133, 186, 249, 151, 46, 190, 44, 126, 184, 195, 219, 37, 11, 225, 23, 8, 59, 106, 239, 198, 146, 205, 47, 59, 63, 9, 102, 29, 60, 209, 226, 67, 126, 193, 252, 255, 206, 172, 44, 53, 137, 209, 246}, []byte{237, 8, 12, 44, 90, 243, 24, 100, 123, 216, 185, 91, 182, 60, 9, 145, 126, 254, 139, 24, 211, 150, 219, 28, 138, 197, 13, 109, 227, 31, 60, 128, 237, 181, 183, 2, 138, 232, 112, 5})
doTest([]byte{253, 217, 8, 176, 66, 153, 249, 49, 82, 114, 184, 139, 190, 87}, []byte{28, 55, 193, 193, 179, 246, 222, 5, 95, 96, 13, 242})
doTest([]byte{15, 65, 231, 224, 151, 167, 74, 228, 23}, []byte{200, 90, 82})
doTest([]byte{61, 186, 61, 193, 215, 243, 84, 66, 48, 93, 108, 249, 55, 232}, []byte{0, 180, 53, 152, 134, 252, 165, 168})
doTest([]byte{78, 68, 116, 15, 85}, []byte{36})
doTest([]byte{122, 143}, []byte{245})
doTest([]byte{78, 85, 143, 35}, []byte{226, 85})
doTest([]byte{11, 188, 118, 21, 177, 224, 151, 105, 21, 245, 251, 162, 72, 175, 248, 134, 123, 251, 160, 163, 42, 57, 53, 222, 195, 49, 199, 151, 5, 236, 160, 57, 212, 241, 44, 43}, []byte{186, 106})
doTest([]byte{157, 99, 220, 166, 63, 18, 225, 215, 71, 95, 99, 200, 218, 147, 131, 245, 222, 209, 135, 152, 82, 128, 24, 0, 100, 40, 84, 193, 205, 86, 130, 204, 235, 100, 94, 61}, []byte{41, 171, 66, 233})
doTest([]byte{249, 34, 253, 235, 233, 104, 52, 60, 17, 13, 182, 223, 19, 91, 164, 2, 196, 29, 74, 219, 65, 23, 190, 31, 10, 241, 221, 150, 221, 118, 53, 69, 45, 90, 215, 100, 155, 102, 150, 176, 203, 39, 22, 70, 10, 238}, []byte{161, 49, 179, 149, 178, 146, 208, 144, 19, 158, 180, 152, 243, 138, 143, 243, 82, 112, 229, 10, 113, 255, 139, 246})
doTest([]byte{39, 232, 159, 64, 242, 235, 66, 226, 100, 221, 225, 247, 139, 157, 95, 155}, []byte{41, 9, 244})
doTest([]byte{177, 185, 131, 64, 103, 93, 134, 153, 15, 26, 0, 119, 21, 27, 174, 181, 111, 245, 214, 244, 83, 66, 24, 244, 255, 189, 133, 158, 37, 46, 199, 123, 110, 153, 61, 137, 163, 231, 129, 65, 186, 89, 219, 39, 226, 236, 199, 197, 73, 213}, []byte{37, 59, 125, 211, 249, 177, 107, 79, 107, 47, 242, 168, 49, 38, 168, 198, 199, 91, 212, 22, 107, 244})
doTest([]byte{196, 226, 29, 110, 161, 143, 64, 169, 216, 231, 115}, []byte{253, 93, 218, 129, 37})
doTest([]byte{133, 8, 124, 221, 36, 17, 135, 115, 149, 58, 250, 103, 241, 18, 19, 246, 191, 85, 80, 255, 93, 182, 140, 123, 206, 232, 20, 166, 216, 105, 210, 229, 249, 212, 93, 227, 75, 231, 36, 195, 166, 246, 47, 168, 35, 7, 176, 124, 44, 179, 24, 145}, []byte{78, 57, 134, 181, 215, 149, 111, 51, 172, 58, 114, 3, 140, 186, 126, 40, 190})
doTest([]byte{245, 206, 124, 0, 15, 59, 253, 225, 155}, []byte{65, 14, 188, 213, 18, 113, 161, 16})
doTest([]byte{20, 109, 28, 180, 48, 170, 216, 48, 140, 89, 103}, []byte{193, 147, 50, 209, 160})
doTest([]byte{87, 198, 56, 151, 121, 37, 81, 64, 193, 24, 222, 142, 102, 74, 216, 233, 198, 197, 90, 4, 65, 14, 154, 147, 200, 252, 8, 64, 97, 150, 136, 141}, []byte{231, 190, 32, 90, 100, 40, 41, 103, 200, 200, 243, 75, 177, 7, 93, 28, 83, 47, 188, 236, 20, 95, 69, 104, 155, 102, 110, 197})
doTest([]byte{168, 72, 2, 101, 103, 118, 218, 38, 82, 85, 62, 37, 201, 96, 255, 71, 198}, []byte{129, 33, 28, 228, 195, 120, 101, 46, 119, 126})
doTest([]byte{130, 162, 73, 44, 165, 207, 124, 28, 17, 223, 43, 143, 81, 70, 205, 161, 143, 230, 97, 94, 228, 41, 26, 187, 69, 85, 162, 51, 168, 64, 26, 207, 245, 128}, []byte{6, 171})
doTest([]byte{95, 28, 93, 149, 234, 89, 201, 71, 39, 197, 236, 223, 251, 190, 112, 96, 101, 53, 40, 88, 136, 141, 230, 80, 45, 73, 116, 208, 197, 91, 154, 209, 128, 214, 66, 114, 137, 204, 115, 139, 96, 211, 148, 127, 104, 194}, []byte{10, 102, 57, 95, 61, 212, 130, 71, 74, 58, 82, 115, 238, 213, 251, 184, 203, 250, 55, 186, 37, 16, 71, 247, 146, 194, 74, 208, 221, 6, 81, 172, 204, 73, 102, 40, 247, 174, 213, 37, 225, 246, 8, 58})
doTest([]byte{207, 185, 106, 191, 87, 109, 110, 210, 54, 12, 103, 161, 228}, []byte{214, 138, 159, 195, 154, 236, 33, 243, 53, 79, 227})
doTest([]byte{203, 43, 26, 94, 37, 123, 254, 215, 153, 193, 157, 248, 180, 249, 103, 232, 107, 17, 138, 0, 11, 240, 218, 122, 19, 103, 112, 60, 125, 100, 209, 166, 103, 81, 200, 84, 77, 100, 18, 110, 209, 225, 209, 254, 185, 116, 186, 216, 206, 36, 252, 144, 90, 247, 117, 219, 81, 160}, []byte{185, 176, 106, 253, 76, 153, 185, 211, 187, 153, 210, 31, 99, 4, 46, 145, 221, 99, 236, 19, 126, 138, 66, 26, 40, 217, 170, 217, 147})
doTest([]byte{11, 193, 90, 52, 239, 247, 144, 99, 48, 19, 154, 6, 255, 28, 47, 41, 30, 220}, []byte{235, 165, 125, 82, 28, 116, 21, 133, 243, 222, 241, 20, 134})
doTest([]byte{173, 151, 109, 88, 104, 65, 76, 111, 219, 237, 2, 173, 25, 84, 98, 16, 135, 157, 14, 194, 228, 86, 167, 187, 137, 245, 144, 61, 200, 76, 188, 117, 223, 172, 16, 116, 84, 1, 203, 173, 170, 32, 135, 67, 16}, []byte{150, 31, 11, 211, 82, 221, 251, 84, 254, 121, 68, 34, 211, 142, 197, 246, 138, 204, 60, 197, 210, 238, 142, 234, 187, 200, 179, 228})
doTest([]byte{171, 185, 30, 162, 129, 205, 254, 186, 86, 239, 178, 206, 115, 177, 14, 166, 143, 48, 141, 205, 109, 67, 238, 187, 134, 210, 96, 23, 195, 206, 100, 171, 156, 8, 229, 131, 169, 169, 59, 167, 224, 241, 185, 132, 162, 50, 87, 252, 156, 122, 248, 19, 130, 31, 127}, []byte{62, 42, 216, 109, 23, 176, 255, 137, 139, 90, 7, 186, 175, 243, 160, 206, 37, 94, 157, 217, 11, 169, 126, 41, 73, 133, 212, 232, 249, 117, 70, 147, 137, 156, 43, 243, 234, 155, 94, 38, 59, 211, 218, 165, 3, 33, 231, 237, 92, 16, 128})
doTest([]byte{98, 28, 174, 108, 231, 247, 135, 139, 6, 50, 107, 203, 138, 252, 229, 245, 230, 236, 124, 138, 105, 25, 83, 122}, []byte{97, 214, 25, 2, 14, 48, 65, 212, 241, 200, 81, 57, 176, 59, 16, 55, 20, 91, 66})
doTest([]byte{73, 214, 80, 41, 125, 136, 126, 184, 70, 141, 140, 58, 249, 250, 49, 249, 155, 0, 236, 49, 17, 125, 18, 29}, []byte{128, 16, 47, 235, 125, 128, 97, 245, 177, 210, 219, 195})
doTest([]byte{3, 220, 98, 73, 200, 52, 8, 107, 173, 177, 58, 221, 180, 226, 76, 210, 182, 88, 104, 171, 243, 129, 88, 112, 126, 83, 141, 50, 106, 204, 195, 51, 141, 75, 132, 161}, []byte{110, 178, 213, 174, 1, 241, 95})
doTest([]byte{196, 88, 50, 142, 76, 128, 190, 189, 76, 9, 228, 62, 198, 186, 180, 240, 62, 130, 132, 242}, []byte{244, 89, 17, 143, 3, 180, 150, 242, 167, 214, 209, 133, 120, 213, 173, 59, 25, 158, 251})
doTest([]byte{166, 214, 1, 225, 237, 7, 80, 104, 94, 170, 125, 184, 148, 16, 121, 101, 52, 216, 177, 192, 6, 132, 77, 44, 5, 9, 126, 156, 12, 2, 29, 99, 51, 78, 177, 92, 140, 107, 146, 183, 109, 227, 171, 57, 193, 14, 37}, []byte{245, 46, 189, 11, 202, 195, 89, 53, 215, 172, 132, 196, 145, 141, 239, 160, 242, 7, 85, 251, 193, 85})
}

56
vendor/github.com/boombuler/barcode/qr/numeric.go generated vendored Normal file
View File

@@ -0,0 +1,56 @@
package qr
import (
"errors"
"fmt"
"strconv"
"github.com/boombuler/barcode/utils"
)
func encodeNumeric(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
contentBitCount := (len(content) / 3) * 10
switch len(content) % 3 {
case 1:
contentBitCount += 4
case 2:
contentBitCount += 7
}
vi := findSmallestVersionInfo(ecl, numericMode, contentBitCount)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
res := new(utils.BitList)
res.AddBits(int(numericMode), 4)
res.AddBits(len(content), vi.charCountBits(numericMode))
for pos := 0; pos < len(content); pos += 3 {
var curStr string
if pos+3 <= len(content) {
curStr = content[pos : pos+3]
} else {
curStr = content[pos:]
}
i, err := strconv.Atoi(curStr)
if err != nil || i < 0 {
return nil, nil, fmt.Errorf("\"%s\" can not be encoded as %s", content, Numeric)
}
var bitCnt byte
switch len(curStr) % 3 {
case 0:
bitCnt = 10
case 1:
bitCnt = 4
break
case 2:
bitCnt = 7
break
}
res.AddBits(i, bitCnt)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}

26
vendor/github.com/boombuler/barcode/qr/numeric_test.go generated vendored Normal file
View File

@@ -0,0 +1,26 @@
package qr
import (
"bytes"
"testing"
)
func Test_NumericEncoding(t *testing.T) {
encode := Numeric.getEncoder()
x, vi, err := encode("01234567", H)
if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 32, 12, 86, 97, 128, 236, 17, 236}) != 0 {
t.Error("\"01234567\" failed to encode")
}
x, vi, err = encode("0123456789012345", H)
if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{16, 64, 12, 86, 106, 110, 20, 234, 80}) != 0 {
t.Error("\"0123456789012345\" failed to encode")
}
x, vi, err = encode("foo", H)
if err == nil {
t.Error("Numeric encoding should not be able to encode \"foo\"")
}
x, vi, err = encode(makeString(14297, "1"), H)
if x != nil || vi != nil || err == nil {
t.Fail()
}
}

166
vendor/github.com/boombuler/barcode/qr/qrcode.go generated vendored Normal file
View File

@@ -0,0 +1,166 @@
package qr
import (
"image"
"image/color"
"math"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/utils"
)
type qrcode struct {
dimension int
data *utils.BitList
content string
}
func (qr *qrcode) Content() string {
return qr.content
}
func (qr *qrcode) Metadata() barcode.Metadata {
return barcode.Metadata{barcode.TypeQR, 2}
}
func (qr *qrcode) ColorModel() color.Model {
return color.Gray16Model
}
func (qr *qrcode) Bounds() image.Rectangle {
return image.Rect(0, 0, qr.dimension, qr.dimension)
}
func (qr *qrcode) At(x, y int) color.Color {
if qr.Get(x, y) {
return color.Black
}
return color.White
}
func (qr *qrcode) Get(x, y int) bool {
return qr.data.GetBit(x*qr.dimension + y)
}
func (qr *qrcode) Set(x, y int, val bool) {
qr.data.SetBit(x*qr.dimension+y, val)
}
func (qr *qrcode) calcPenalty() uint {
return qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4()
}
func (qr *qrcode) calcPenaltyRule1() uint {
var result uint
for x := 0; x < qr.dimension; x++ {
checkForX := false
var cntX uint
checkForY := false
var cntY uint
for y := 0; y < qr.dimension; y++ {
if qr.Get(x, y) == checkForX {
cntX++
} else {
checkForX = !checkForX
if cntX >= 5 {
result += cntX - 2
}
cntX = 1
}
if qr.Get(y, x) == checkForY {
cntY++
} else {
checkForY = !checkForY
if cntY >= 5 {
result += cntY - 2
}
cntY = 1
}
}
if cntX >= 5 {
result += cntX - 2
}
if cntY >= 5 {
result += cntY - 2
}
}
return result
}
func (qr *qrcode) calcPenaltyRule2() uint {
var result uint
for x := 0; x < qr.dimension-1; x++ {
for y := 0; y < qr.dimension-1; y++ {
check := qr.Get(x, y)
if qr.Get(x, y+1) == check && qr.Get(x+1, y) == check && qr.Get(x+1, y+1) == check {
result += 3
}
}
}
return result
}
func (qr *qrcode) calcPenaltyRule3() uint {
pattern1 := []bool{true, false, true, true, true, false, true, false, false, false, false}
pattern2 := []bool{false, false, false, false, true, false, true, true, true, false, true}
var result uint
for x := 0; x <= qr.dimension-len(pattern1); x++ {
for y := 0; y < qr.dimension; y++ {
pattern1XFound := true
pattern2XFound := true
pattern1YFound := true
pattern2YFound := true
for i := 0; i < len(pattern1); i++ {
iv := qr.Get(x+i, y)
if iv != pattern1[i] {
pattern1XFound = false
}
if iv != pattern2[i] {
pattern2XFound = false
}
iv = qr.Get(y, x+i)
if iv != pattern1[i] {
pattern1YFound = false
}
if iv != pattern2[i] {
pattern2YFound = false
}
}
if pattern1XFound || pattern2XFound {
result += 40
}
if pattern1YFound || pattern2YFound {
result += 40
}
}
}
return result
}
func (qr *qrcode) calcPenaltyRule4() uint {
totalNum := qr.data.Len()
trueCnt := 0
for i := 0; i < totalNum; i++ {
if qr.data.GetBit(i) {
trueCnt++
}
}
percDark := float64(trueCnt) * 100 / float64(totalNum)
floor := math.Abs(math.Floor(percDark/5) - 10)
ceil := math.Abs(math.Ceil(percDark/5) - 10)
return uint(math.Min(floor, ceil) * 10)
}
func newBarcode(dim int) *qrcode {
res := new(qrcode)
res.dimension = dim
res.data = utils.NewBitList(dim * dim)
return res
}

126
vendor/github.com/boombuler/barcode/qr/qrcode_test.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package qr
import (
"image/color"
"testing"
)
func Test_NewQRCode(t *testing.T) {
bc := newBarcode(2)
if bc == nil {
t.Fail()
}
if bc.data.Len() != 4 {
t.Fail()
}
if bc.dimension != 2 {
t.Fail()
}
}
func Test_QRBasics(t *testing.T) {
qr := newBarcode(10)
if qr.ColorModel() != color.Gray16Model {
t.Fail()
}
code, _ := Encode("test", L, Unicode)
if code.Content() != "test" {
t.Fail()
}
if code.Metadata().Dimensions != 2 {
t.Fail()
}
bounds := code.Bounds()
if bounds.Min.X != 0 || bounds.Min.Y != 0 || bounds.Max.X != 21 || bounds.Max.Y != 21 {
t.Fail()
}
if code.At(0, 0) != color.Black || code.At(0, 7) != color.White {
t.Fail()
}
qr = code.(*qrcode)
if !qr.Get(0, 0) || qr.Get(0, 7) {
t.Fail()
}
sum := qr.calcPenaltyRule1() + qr.calcPenaltyRule2() + qr.calcPenaltyRule3() + qr.calcPenaltyRule4()
if qr.calcPenalty() != sum {
t.Fail()
}
}
func Test_Penalty1(t *testing.T) {
qr := newBarcode(7)
if qr.calcPenaltyRule1() != 70 {
t.Fail()
}
qr.Set(0, 0, true)
if qr.calcPenaltyRule1() != 68 {
t.Fail()
}
qr.Set(0, 6, true)
if qr.calcPenaltyRule1() != 66 {
t.Fail()
}
}
func Test_Penalty2(t *testing.T) {
qr := newBarcode(3)
if qr.calcPenaltyRule2() != 12 {
t.Fail()
}
qr.Set(0, 0, true)
qr.Set(1, 1, true)
qr.Set(2, 0, true)
if qr.calcPenaltyRule2() != 0 {
t.Fail()
}
qr.Set(1, 1, false)
if qr.calcPenaltyRule2() != 6 {
t.Fail()
}
}
func Test_Penalty3(t *testing.T) {
runTest := func(content string, result uint) {
code, _ := Encode(content, L, AlphaNumeric)
qr := code.(*qrcode)
if qr.calcPenaltyRule3() != result {
t.Errorf("Failed Penalty Rule 3 for content \"%s\" got %d but expected %d", content, qr.calcPenaltyRule3(), result)
}
}
runTest("A", 80)
runTest("FOO", 40)
runTest("0815", 0)
}
func Test_Penalty4(t *testing.T) {
qr := newBarcode(3)
if qr.calcPenaltyRule4() != 100 {
t.Fail()
}
qr.Set(0, 0, true)
if qr.calcPenaltyRule4() != 70 {
t.Fail()
}
qr.Set(0, 1, true)
if qr.calcPenaltyRule4() != 50 {
t.Fail()
}
qr.Set(0, 2, true)
if qr.calcPenaltyRule4() != 30 {
t.Fail()
}
qr.Set(1, 0, true)
if qr.calcPenaltyRule4() != 10 {
t.Fail()
}
qr.Set(1, 1, true)
if qr.calcPenaltyRule4() != 10 {
t.Fail()
}
qr = newBarcode(2)
qr.Set(0, 0, true)
qr.Set(1, 0, true)
if qr.calcPenaltyRule4() != 0 {
t.Fail()
}
}

27
vendor/github.com/boombuler/barcode/qr/unicode.go generated vendored Normal file
View File

@@ -0,0 +1,27 @@
package qr
import (
"errors"
"github.com/boombuler/barcode/utils"
)
func encodeUnicode(content string, ecl ErrorCorrectionLevel) (*utils.BitList, *versionInfo, error) {
data := []byte(content)
vi := findSmallestVersionInfo(ecl, byteMode, len(data)*8)
if vi == nil {
return nil, nil, errors.New("To much data to encode")
}
// It's not correct to add the unicode bytes to the result directly but most readers can't handle the
// required ECI header...
res := new(utils.BitList)
res.AddBits(int(byteMode), 4)
res.AddBits(len(content), vi.charCountBits(byteMode))
for _, b := range data {
res.AddByte(b)
}
addPaddingAndTerminator(res, vi)
return res, vi, nil
}

18
vendor/github.com/boombuler/barcode/qr/unicode_test.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
package qr
import (
"bytes"
"testing"
)
func Test_UnicodeEncoding(t *testing.T) {
encode := Unicode.getEncoder()
x, vi, err := encode("A", H) // 65
if x == nil || vi == nil || vi.Version != 1 || bytes.Compare(x.GetBytes(), []byte{64, 20, 16, 236, 17, 236, 17, 236, 17}) != 0 {
t.Errorf("\"A\" failed to encode: %s", err)
}
_, _, err = encode(makeString(3000, "A"), H)
if err == nil {
t.Error("Unicode encoding should not be able to encode a 3kb string")
}
}

310
vendor/github.com/boombuler/barcode/qr/versioninfo.go generated vendored Normal file
View File

@@ -0,0 +1,310 @@
package qr
import "math"
// ErrorCorrectionLevel indicates the amount of "backup data" stored in the QR code
type ErrorCorrectionLevel byte
const (
// L recovers 7% of data
L ErrorCorrectionLevel = iota
// M recovers 15% of data
M
// Q recovers 25% of data
Q
// H recovers 30% of data
H
)
func (ecl ErrorCorrectionLevel) String() string {
switch ecl {
case L:
return "L"
case M:
return "M"
case Q:
return "Q"
case H:
return "H"
}
return "unknown"
}
type encodingMode byte
const (
numericMode encodingMode = 1
alphaNumericMode encodingMode = 2
byteMode encodingMode = 4
kanjiMode encodingMode = 8
)
type versionInfo struct {
Version byte
Level ErrorCorrectionLevel
ErrorCorrectionCodewordsPerBlock byte
NumberOfBlocksInGroup1 byte
DataCodeWordsPerBlockInGroup1 byte
NumberOfBlocksInGroup2 byte
DataCodeWordsPerBlockInGroup2 byte
}
var versionInfos = []*versionInfo{
&versionInfo{1, L, 7, 1, 19, 0, 0},
&versionInfo{1, M, 10, 1, 16, 0, 0},
&versionInfo{1, Q, 13, 1, 13, 0, 0},
&versionInfo{1, H, 17, 1, 9, 0, 0},
&versionInfo{2, L, 10, 1, 34, 0, 0},
&versionInfo{2, M, 16, 1, 28, 0, 0},
&versionInfo{2, Q, 22, 1, 22, 0, 0},
&versionInfo{2, H, 28, 1, 16, 0, 0},
&versionInfo{3, L, 15, 1, 55, 0, 0},
&versionInfo{3, M, 26, 1, 44, 0, 0},
&versionInfo{3, Q, 18, 2, 17, 0, 0},
&versionInfo{3, H, 22, 2, 13, 0, 0},
&versionInfo{4, L, 20, 1, 80, 0, 0},
&versionInfo{4, M, 18, 2, 32, 0, 0},
&versionInfo{4, Q, 26, 2, 24, 0, 0},
&versionInfo{4, H, 16, 4, 9, 0, 0},
&versionInfo{5, L, 26, 1, 108, 0, 0},
&versionInfo{5, M, 24, 2, 43, 0, 0},
&versionInfo{5, Q, 18, 2, 15, 2, 16},
&versionInfo{5, H, 22, 2, 11, 2, 12},
&versionInfo{6, L, 18, 2, 68, 0, 0},
&versionInfo{6, M, 16, 4, 27, 0, 0},
&versionInfo{6, Q, 24, 4, 19, 0, 0},
&versionInfo{6, H, 28, 4, 15, 0, 0},
&versionInfo{7, L, 20, 2, 78, 0, 0},
&versionInfo{7, M, 18, 4, 31, 0, 0},
&versionInfo{7, Q, 18, 2, 14, 4, 15},
&versionInfo{7, H, 26, 4, 13, 1, 14},
&versionInfo{8, L, 24, 2, 97, 0, 0},
&versionInfo{8, M, 22, 2, 38, 2, 39},
&versionInfo{8, Q, 22, 4, 18, 2, 19},
&versionInfo{8, H, 26, 4, 14, 2, 15},
&versionInfo{9, L, 30, 2, 116, 0, 0},
&versionInfo{9, M, 22, 3, 36, 2, 37},
&versionInfo{9, Q, 20, 4, 16, 4, 17},
&versionInfo{9, H, 24, 4, 12, 4, 13},
&versionInfo{10, L, 18, 2, 68, 2, 69},
&versionInfo{10, M, 26, 4, 43, 1, 44},
&versionInfo{10, Q, 24, 6, 19, 2, 20},
&versionInfo{10, H, 28, 6, 15, 2, 16},
&versionInfo{11, L, 20, 4, 81, 0, 0},
&versionInfo{11, M, 30, 1, 50, 4, 51},
&versionInfo{11, Q, 28, 4, 22, 4, 23},
&versionInfo{11, H, 24, 3, 12, 8, 13},
&versionInfo{12, L, 24, 2, 92, 2, 93},
&versionInfo{12, M, 22, 6, 36, 2, 37},
&versionInfo{12, Q, 26, 4, 20, 6, 21},
&versionInfo{12, H, 28, 7, 14, 4, 15},
&versionInfo{13, L, 26, 4, 107, 0, 0},
&versionInfo{13, M, 22, 8, 37, 1, 38},
&versionInfo{13, Q, 24, 8, 20, 4, 21},
&versionInfo{13, H, 22, 12, 11, 4, 12},
&versionInfo{14, L, 30, 3, 115, 1, 116},
&versionInfo{14, M, 24, 4, 40, 5, 41},
&versionInfo{14, Q, 20, 11, 16, 5, 17},
&versionInfo{14, H, 24, 11, 12, 5, 13},
&versionInfo{15, L, 22, 5, 87, 1, 88},
&versionInfo{15, M, 24, 5, 41, 5, 42},
&versionInfo{15, Q, 30, 5, 24, 7, 25},
&versionInfo{15, H, 24, 11, 12, 7, 13},
&versionInfo{16, L, 24, 5, 98, 1, 99},
&versionInfo{16, M, 28, 7, 45, 3, 46},
&versionInfo{16, Q, 24, 15, 19, 2, 20},
&versionInfo{16, H, 30, 3, 15, 13, 16},
&versionInfo{17, L, 28, 1, 107, 5, 108},
&versionInfo{17, M, 28, 10, 46, 1, 47},
&versionInfo{17, Q, 28, 1, 22, 15, 23},
&versionInfo{17, H, 28, 2, 14, 17, 15},
&versionInfo{18, L, 30, 5, 120, 1, 121},
&versionInfo{18, M, 26, 9, 43, 4, 44},
&versionInfo{18, Q, 28, 17, 22, 1, 23},
&versionInfo{18, H, 28, 2, 14, 19, 15},
&versionInfo{19, L, 28, 3, 113, 4, 114},
&versionInfo{19, M, 26, 3, 44, 11, 45},
&versionInfo{19, Q, 26, 17, 21, 4, 22},
&versionInfo{19, H, 26, 9, 13, 16, 14},
&versionInfo{20, L, 28, 3, 107, 5, 108},
&versionInfo{20, M, 26, 3, 41, 13, 42},
&versionInfo{20, Q, 30, 15, 24, 5, 25},
&versionInfo{20, H, 28, 15, 15, 10, 16},
&versionInfo{21, L, 28, 4, 116, 4, 117},
&versionInfo{21, M, 26, 17, 42, 0, 0},
&versionInfo{21, Q, 28, 17, 22, 6, 23},
&versionInfo{21, H, 30, 19, 16, 6, 17},
&versionInfo{22, L, 28, 2, 111, 7, 112},
&versionInfo{22, M, 28, 17, 46, 0, 0},
&versionInfo{22, Q, 30, 7, 24, 16, 25},
&versionInfo{22, H, 24, 34, 13, 0, 0},
&versionInfo{23, L, 30, 4, 121, 5, 122},
&versionInfo{23, M, 28, 4, 47, 14, 48},
&versionInfo{23, Q, 30, 11, 24, 14, 25},
&versionInfo{23, H, 30, 16, 15, 14, 16},
&versionInfo{24, L, 30, 6, 117, 4, 118},
&versionInfo{24, M, 28, 6, 45, 14, 46},
&versionInfo{24, Q, 30, 11, 24, 16, 25},
&versionInfo{24, H, 30, 30, 16, 2, 17},
&versionInfo{25, L, 26, 8, 106, 4, 107},
&versionInfo{25, M, 28, 8, 47, 13, 48},
&versionInfo{25, Q, 30, 7, 24, 22, 25},
&versionInfo{25, H, 30, 22, 15, 13, 16},
&versionInfo{26, L, 28, 10, 114, 2, 115},
&versionInfo{26, M, 28, 19, 46, 4, 47},
&versionInfo{26, Q, 28, 28, 22, 6, 23},
&versionInfo{26, H, 30, 33, 16, 4, 17},
&versionInfo{27, L, 30, 8, 122, 4, 123},
&versionInfo{27, M, 28, 22, 45, 3, 46},
&versionInfo{27, Q, 30, 8, 23, 26, 24},
&versionInfo{27, H, 30, 12, 15, 28, 16},
&versionInfo{28, L, 30, 3, 117, 10, 118},
&versionInfo{28, M, 28, 3, 45, 23, 46},
&versionInfo{28, Q, 30, 4, 24, 31, 25},
&versionInfo{28, H, 30, 11, 15, 31, 16},
&versionInfo{29, L, 30, 7, 116, 7, 117},
&versionInfo{29, M, 28, 21, 45, 7, 46},
&versionInfo{29, Q, 30, 1, 23, 37, 24},
&versionInfo{29, H, 30, 19, 15, 26, 16},
&versionInfo{30, L, 30, 5, 115, 10, 116},
&versionInfo{30, M, 28, 19, 47, 10, 48},
&versionInfo{30, Q, 30, 15, 24, 25, 25},
&versionInfo{30, H, 30, 23, 15, 25, 16},
&versionInfo{31, L, 30, 13, 115, 3, 116},
&versionInfo{31, M, 28, 2, 46, 29, 47},
&versionInfo{31, Q, 30, 42, 24, 1, 25},
&versionInfo{31, H, 30, 23, 15, 28, 16},
&versionInfo{32, L, 30, 17, 115, 0, 0},
&versionInfo{32, M, 28, 10, 46, 23, 47},
&versionInfo{32, Q, 30, 10, 24, 35, 25},
&versionInfo{32, H, 30, 19, 15, 35, 16},
&versionInfo{33, L, 30, 17, 115, 1, 116},
&versionInfo{33, M, 28, 14, 46, 21, 47},
&versionInfo{33, Q, 30, 29, 24, 19, 25},
&versionInfo{33, H, 30, 11, 15, 46, 16},
&versionInfo{34, L, 30, 13, 115, 6, 116},
&versionInfo{34, M, 28, 14, 46, 23, 47},
&versionInfo{34, Q, 30, 44, 24, 7, 25},
&versionInfo{34, H, 30, 59, 16, 1, 17},
&versionInfo{35, L, 30, 12, 121, 7, 122},
&versionInfo{35, M, 28, 12, 47, 26, 48},
&versionInfo{35, Q, 30, 39, 24, 14, 25},
&versionInfo{35, H, 30, 22, 15, 41, 16},
&versionInfo{36, L, 30, 6, 121, 14, 122},
&versionInfo{36, M, 28, 6, 47, 34, 48},
&versionInfo{36, Q, 30, 46, 24, 10, 25},
&versionInfo{36, H, 30, 2, 15, 64, 16},
&versionInfo{37, L, 30, 17, 122, 4, 123},
&versionInfo{37, M, 28, 29, 46, 14, 47},
&versionInfo{37, Q, 30, 49, 24, 10, 25},
&versionInfo{37, H, 30, 24, 15, 46, 16},
&versionInfo{38, L, 30, 4, 122, 18, 123},
&versionInfo{38, M, 28, 13, 46, 32, 47},
&versionInfo{38, Q, 30, 48, 24, 14, 25},
&versionInfo{38, H, 30, 42, 15, 32, 16},
&versionInfo{39, L, 30, 20, 117, 4, 118},
&versionInfo{39, M, 28, 40, 47, 7, 48},
&versionInfo{39, Q, 30, 43, 24, 22, 25},
&versionInfo{39, H, 30, 10, 15, 67, 16},
&versionInfo{40, L, 30, 19, 118, 6, 119},
&versionInfo{40, M, 28, 18, 47, 31, 48},
&versionInfo{40, Q, 30, 34, 24, 34, 25},
&versionInfo{40, H, 30, 20, 15, 61, 16},
}
func (vi *versionInfo) totalDataBytes() int {
g1Data := int(vi.NumberOfBlocksInGroup1) * int(vi.DataCodeWordsPerBlockInGroup1)
g2Data := int(vi.NumberOfBlocksInGroup2) * int(vi.DataCodeWordsPerBlockInGroup2)
return (g1Data + g2Data)
}
func (vi *versionInfo) charCountBits(m encodingMode) byte {
switch m {
case numericMode:
if vi.Version < 10 {
return 10
} else if vi.Version < 27 {
return 12
}
return 14
case alphaNumericMode:
if vi.Version < 10 {
return 9
} else if vi.Version < 27 {
return 11
}
return 13
case byteMode:
if vi.Version < 10 {
return 8
}
return 16
case kanjiMode:
if vi.Version < 10 {
return 8
} else if vi.Version < 27 {
return 10
}
return 12
default:
return 0
}
}
func (vi *versionInfo) modulWidth() int {
return ((int(vi.Version) - 1) * 4) + 21
}
func (vi *versionInfo) alignmentPatternPlacements() []int {
if vi.Version == 1 {
return make([]int, 0)
}
first := 6
last := vi.modulWidth() - 7
space := float64(last - first)
count := int(math.Ceil(space/28)) + 1
result := make([]int, count)
result[0] = first
result[len(result)-1] = last
if count > 2 {
step := int(math.Ceil(float64(last-first) / float64(count-1)))
if step%2 == 1 {
frac := float64(last-first) / float64(count-1)
_, x := math.Modf(frac)
if x >= 0.5 {
frac = math.Ceil(frac)
} else {
frac = math.Floor(frac)
}
if int(frac)%2 == 0 {
step--
} else {
step++
}
}
for i := 1; i <= count-2; i++ {
result[i] = last - (step * (count - 1 - i))
}
}
return result
}
func findSmallestVersionInfo(ecl ErrorCorrectionLevel, mode encodingMode, dataBits int) *versionInfo {
dataBits = dataBits + 4 // mode indicator
for _, vi := range versionInfos {
if vi.Level == ecl {
if (vi.totalDataBytes() * 8) >= (dataBits + int(vi.charCountBits(mode))) {
return vi
}
}
}
return nil
}

View File

@@ -0,0 +1,157 @@
package qr
import "testing"
var testvi = &versionInfo{7, M, 0, 1, 10, 2, 5} // Fake versionInfo to run some of the tests
func Test_ErrorCorrectionStringer(t *testing.T) {
tests := map[ErrorCorrectionLevel]string{
L: "L", M: "M", Q: "Q", H: "H", ErrorCorrectionLevel(99): "unknown",
}
for ecl, str := range tests {
if ecl.String() != str {
t.Fail()
}
}
}
func Test_CharCountBits(t *testing.T) {
v1 := &versionInfo{5, M, 0, 0, 0, 0, 0}
v2 := &versionInfo{15, M, 0, 0, 0, 0, 0}
v3 := &versionInfo{30, M, 0, 0, 0, 0, 0}
if v1.charCountBits(numericMode) != 10 {
t.Fail()
}
if v1.charCountBits(alphaNumericMode) != 9 {
t.Fail()
}
if v1.charCountBits(byteMode) != 8 {
t.Fail()
}
if v1.charCountBits(kanjiMode) != 8 {
t.Fail()
}
if v2.charCountBits(numericMode) != 12 {
t.Fail()
}
if v2.charCountBits(alphaNumericMode) != 11 {
t.Fail()
}
if v2.charCountBits(byteMode) != 16 {
t.Fail()
}
if v2.charCountBits(kanjiMode) != 10 {
t.Fail()
}
if v3.charCountBits(numericMode) != 14 {
t.Fail()
}
if v3.charCountBits(alphaNumericMode) != 13 {
t.Fail()
}
if v3.charCountBits(byteMode) != 16 {
t.Fail()
}
if v3.charCountBits(kanjiMode) != 12 {
t.Fail()
}
if v1.charCountBits(encodingMode(3)) != 0 {
t.Fail()
}
}
func Test_TotalDataBytes(t *testing.T) {
if testvi.totalDataBytes() != 20 {
t.Fail()
}
}
func Test_ModulWidth(t *testing.T) {
if testvi.modulWidth() != 45 {
t.Fail()
}
}
func Test_FindSmallestVersionInfo(t *testing.T) {
if findSmallestVersionInfo(H, alphaNumericMode, 10208) != nil {
t.Error("there should be no version with this capacity")
}
test := func(cap int, tVersion byte) {
v := findSmallestVersionInfo(H, alphaNumericMode, cap)
if v == nil || v.Version != tVersion {
t.Errorf("version %d should be returned.", tVersion)
}
}
test(10191, 40)
test(5591, 29)
test(5592, 30)
test(190, 3)
test(200, 4)
}
type aligmnentTest struct {
version byte
patterns []int
}
var allAligmnentTests = []*aligmnentTest{
&aligmnentTest{1, []int{}},
&aligmnentTest{2, []int{6, 18}},
&aligmnentTest{3, []int{6, 22}},
&aligmnentTest{4, []int{6, 26}},
&aligmnentTest{5, []int{6, 30}},
&aligmnentTest{6, []int{6, 34}},
&aligmnentTest{7, []int{6, 22, 38}},
&aligmnentTest{8, []int{6, 24, 42}},
&aligmnentTest{9, []int{6, 26, 46}},
&aligmnentTest{10, []int{6, 28, 50}},
&aligmnentTest{11, []int{6, 30, 54}},
&aligmnentTest{12, []int{6, 32, 58}},
&aligmnentTest{13, []int{6, 34, 62}},
&aligmnentTest{14, []int{6, 26, 46, 66}},
&aligmnentTest{15, []int{6, 26, 48, 70}},
&aligmnentTest{16, []int{6, 26, 50, 74}},
&aligmnentTest{17, []int{6, 30, 54, 78}},
&aligmnentTest{18, []int{6, 30, 56, 82}},
&aligmnentTest{19, []int{6, 30, 58, 86}},
&aligmnentTest{20, []int{6, 34, 62, 90}},
&aligmnentTest{21, []int{6, 28, 50, 72, 94}},
&aligmnentTest{22, []int{6, 26, 50, 74, 98}},
&aligmnentTest{23, []int{6, 30, 54, 78, 102}},
&aligmnentTest{24, []int{6, 28, 54, 80, 106}},
&aligmnentTest{25, []int{6, 32, 58, 84, 110}},
&aligmnentTest{26, []int{6, 30, 58, 86, 114}},
&aligmnentTest{27, []int{6, 34, 62, 90, 118}},
&aligmnentTest{28, []int{6, 26, 50, 74, 98, 122}},
&aligmnentTest{29, []int{6, 30, 54, 78, 102, 126}},
&aligmnentTest{30, []int{6, 26, 52, 78, 104, 130}},
&aligmnentTest{31, []int{6, 30, 56, 82, 108, 134}},
&aligmnentTest{32, []int{6, 34, 60, 86, 112, 138}},
&aligmnentTest{33, []int{6, 30, 58, 86, 114, 142}},
&aligmnentTest{34, []int{6, 34, 62, 90, 118, 146}},
&aligmnentTest{35, []int{6, 30, 54, 78, 102, 126, 150}},
&aligmnentTest{36, []int{6, 24, 50, 76, 102, 128, 154}},
&aligmnentTest{37, []int{6, 28, 54, 80, 106, 132, 158}},
&aligmnentTest{38, []int{6, 32, 58, 84, 110, 136, 162}},
&aligmnentTest{39, []int{6, 26, 54, 82, 110, 138, 166}},
&aligmnentTest{40, []int{6, 30, 58, 86, 114, 142, 170}},
}
func Test_AlignmentPatternPlacements(t *testing.T) {
for _, at := range allAligmnentTests {
vi := &versionInfo{at.version, M, 0, 0, 0, 0, 0}
res := vi.alignmentPatternPlacements()
if len(res) != len(at.patterns) {
t.Errorf("number of alignmentpatterns missmatch for version %d", at.version)
}
for i := 0; i < len(res); i++ {
if res[i] != at.patterns[i] {
t.Errorf("alignmentpatterns for version %d missmatch on index %d", at.version, i)
}
}
}
}

134
vendor/github.com/boombuler/barcode/scaledbarcode.go generated vendored Normal file
View File

@@ -0,0 +1,134 @@
package barcode
import (
"errors"
"fmt"
"image"
"image/color"
"math"
)
type wrapFunc func(x, y int) color.Color
type scaledBarcode struct {
wrapped Barcode
wrapperFunc wrapFunc
rect image.Rectangle
}
type intCSscaledBC struct {
scaledBarcode
}
func (bc *scaledBarcode) Content() string {
return bc.wrapped.Content()
}
func (bc *scaledBarcode) Metadata() Metadata {
return bc.wrapped.Metadata()
}
func (bc *scaledBarcode) ColorModel() color.Model {
return bc.wrapped.ColorModel()
}
func (bc *scaledBarcode) Bounds() image.Rectangle {
return bc.rect
}
func (bc *scaledBarcode) At(x, y int) color.Color {
return bc.wrapperFunc(x, y)
}
func (bc *intCSscaledBC) CheckSum() int {
if cs, ok := bc.wrapped.(BarcodeIntCS); ok {
return cs.CheckSum()
}
return 0
}
// Scale returns a resized barcode with the given width and height.
func Scale(bc Barcode, width, height int) (Barcode, error) {
switch bc.Metadata().Dimensions {
case 1:
return scale1DCode(bc, width, height)
case 2:
return scale2DCode(bc, width, height)
}
return nil, errors.New("unsupported barcode format")
}
func newScaledBC(wrapped Barcode, wrapperFunc wrapFunc, rect image.Rectangle) Barcode {
result := &scaledBarcode{
wrapped: wrapped,
wrapperFunc: wrapperFunc,
rect: rect,
}
if _, ok := wrapped.(BarcodeIntCS); ok {
return &intCSscaledBC{*result}
}
return result
}
func scale2DCode(bc Barcode, width, height int) (Barcode, error) {
orgBounds := bc.Bounds()
orgWidth := orgBounds.Max.X - orgBounds.Min.X
orgHeight := orgBounds.Max.Y - orgBounds.Min.Y
factor := int(math.Min(float64(width)/float64(orgWidth), float64(height)/float64(orgHeight)))
if factor <= 0 {
return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx%d", orgWidth, orgHeight)
}
offsetX := (width - (orgWidth * factor)) / 2
offsetY := (height - (orgHeight * factor)) / 2
wrap := func(x, y int) color.Color {
if x < offsetX || y < offsetY {
return color.White
}
x = (x - offsetX) / factor
y = (y - offsetY) / factor
if x >= orgWidth || y >= orgHeight {
return color.White
}
return bc.At(x, y)
}
return newScaledBC(
bc,
wrap,
image.Rect(0, 0, width, height),
), nil
}
func scale1DCode(bc Barcode, width, height int) (Barcode, error) {
orgBounds := bc.Bounds()
orgWidth := orgBounds.Max.X - orgBounds.Min.X
factor := int(float64(width) / float64(orgWidth))
if factor <= 0 {
return nil, fmt.Errorf("can not scale barcode to an image smaller than %dx1", orgWidth)
}
offsetX := (width - (orgWidth * factor)) / 2
wrap := func(x, y int) color.Color {
if x < offsetX {
return color.White
}
x = (x - offsetX) / factor
if x >= orgWidth {
return color.White
}
return bc.At(x, 0)
}
return newScaledBC(
bc,
wrap,
image.Rect(0, 0, width, height),
), nil
}

View File

@@ -0,0 +1,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
}
}

View File

@@ -0,0 +1,45 @@
package twooffive
import (
"image/color"
"testing"
)
func Test_AddCheckSum(t *testing.T) {
if sum, err := AddCheckSum("1234567"); err != nil || sum != "12345670" {
t.Fail()
}
if _, err := AddCheckSum("1ABC"); err == nil {
t.Fail()
}
if _, err := AddCheckSum(""); err == nil {
t.Fail()
}
}
func Test_Encode(t *testing.T) {
_, err := Encode("FOOBAR", false)
if err == nil {
t.Error("\"FOOBAR\" should not be encodable")
}
testEncode := func(interleaved bool, txt, testResult string) {
code, err := Encode(txt, interleaved)
if err != nil || code == nil {
t.Fail()
} else {
if code.Bounds().Max.X != len(testResult) {
t.Errorf("%v: length missmatch! %v != %v", txt, code.Bounds().Max.X, len(testResult))
} else {
for i, r := range testResult {
if (code.At(i, 0) == color.Black) != (r == '1') {
t.Errorf("%v: code missmatch on position %d", txt, i)
}
}
}
}
}
testEncode(false, "12345670", "1101101011101010101110101110101011101110111010101010101110101110111010111010101011101110101010101011101110101011101110101101011")
testEncode(true, "12345670", "10101110100010101110001110111010001010001110100011100010101010100011100011101101")
}

View File

@@ -0,0 +1,57 @@
// Package utils contain some utilities which are needed to create barcodes
package utils
import (
"image"
"image/color"
"github.com/boombuler/barcode"
)
type base1DCode struct {
*BitList
kind string
content string
}
type base1DCodeIntCS struct {
base1DCode
checksum int
}
func (c *base1DCode) Content() string {
return c.content
}
func (c *base1DCode) Metadata() barcode.Metadata {
return barcode.Metadata{c.kind, 1}
}
func (c *base1DCode) ColorModel() color.Model {
return color.Gray16Model
}
func (c *base1DCode) Bounds() image.Rectangle {
return image.Rect(0, 0, c.Len(), 1)
}
func (c *base1DCode) At(x, y int) color.Color {
if c.GetBit(x) {
return color.Black
}
return color.White
}
func (c *base1DCodeIntCS) CheckSum() int {
return c.checksum
}
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
func New1DCodeIntCheckSum(codeKind, content string, bars *BitList, checksum int) barcode.BarcodeIntCS {
return &base1DCodeIntCS{base1DCode{bars, codeKind, content}, checksum}
}
// New1DCode creates a new 1D barcode where the bars are represented by the bits in the bars BitList
func New1DCode(codeKind, content string, bars *BitList) barcode.Barcode {
return &base1DCode{bars, codeKind, content}
}

119
vendor/github.com/boombuler/barcode/utils/bitlist.go generated vendored Normal file
View File

@@ -0,0 +1,119 @@
package utils
// BitList is a list that contains bits
type BitList struct {
count int
data []int32
}
// NewBitList returns a new BitList with the given length
// all bits are initialize with false
func NewBitList(capacity int) *BitList {
bl := new(BitList)
bl.count = capacity
x := 0
if capacity%32 != 0 {
x = 1
}
bl.data = make([]int32, capacity/32+x)
return bl
}
// Len returns the number of contained bits
func (bl *BitList) Len() int {
return bl.count
}
func (bl *BitList) grow() {
growBy := len(bl.data)
if growBy < 128 {
growBy = 128
} else if growBy >= 1024 {
growBy = 1024
}
nd := make([]int32, len(bl.data)+growBy)
copy(nd, bl.data)
bl.data = nd
}
// AddBit appends the given bits to the end of the list
func (bl *BitList) AddBit(bits ...bool) {
for _, bit := range bits {
itmIndex := bl.count / 32
for itmIndex >= len(bl.data) {
bl.grow()
}
bl.SetBit(bl.count, bit)
bl.count++
}
}
// SetBit sets the bit at the given index to the given value
func (bl *BitList) SetBit(index int, value bool) {
itmIndex := index / 32
itmBitShift := 31 - (index % 32)
if value {
bl.data[itmIndex] = bl.data[itmIndex] | 1<<uint(itmBitShift)
} else {
bl.data[itmIndex] = bl.data[itmIndex] & ^(1 << uint(itmBitShift))
}
}
// GetBit returns the bit at the given index
func (bl *BitList) GetBit(index int) bool {
itmIndex := index / 32
itmBitShift := 31 - (index % 32)
return ((bl.data[itmIndex] >> uint(itmBitShift)) & 1) == 1
}
// AddByte appends all 8 bits of the given byte to the end of the list
func (bl *BitList) AddByte(b byte) {
for i := 7; i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1)
}
}
// AddBits appends the last (LSB) 'count' bits of 'b' the the end of the list
func (bl *BitList) AddBits(b int, count byte) {
for i := int(count) - 1; i >= 0; i-- {
bl.AddBit(((b >> uint(i)) & 1) == 1)
}
}
// GetBytes returns all bits of the BitList as a []byte
func (bl *BitList) GetBytes() []byte {
len := bl.count >> 3
if (bl.count % 8) != 0 {
len++
}
result := make([]byte, len)
for i := 0; i < len; i++ {
shift := (3 - (i % 4)) * 8
result[i] = (byte)((bl.data[i/4] >> uint(shift)) & 0xFF)
}
return result
}
// IterateBytes iterates through all bytes contained in the BitList
func (bl *BitList) IterateBytes() <-chan byte {
res := make(chan byte)
go func() {
c := bl.count
shift := 24
i := 0
for c > 0 {
res <- byte((bl.data[i] >> uint(shift)) & 0xFF)
shift -= 8
if shift < 0 {
shift = 24
i++
}
c -= 8
}
close(res)
}()
return res
}

View File

@@ -0,0 +1,65 @@
package utils
// GaloisField encapsulates galois field arithmetics
type GaloisField struct {
Size int
Base int
ALogTbl []int
LogTbl []int
}
// NewGaloisField creates a new galois field
func NewGaloisField(pp, fieldSize, b int) *GaloisField {
result := new(GaloisField)
result.Size = fieldSize
result.Base = b
result.ALogTbl = make([]int, fieldSize)
result.LogTbl = make([]int, fieldSize)
x := 1
for i := 0; i < fieldSize; i++ {
result.ALogTbl[i] = x
x = x * 2
if x >= fieldSize {
x = (x ^ pp) & (fieldSize - 1)
}
}
for i := 0; i < fieldSize; i++ {
result.LogTbl[result.ALogTbl[i]] = int(i)
}
return result
}
func (gf *GaloisField) Zero() *GFPoly {
return NewGFPoly(gf, []int{0})
}
// AddOrSub add or substract two numbers
func (gf *GaloisField) AddOrSub(a, b int) int {
return a ^ b
}
// Multiply multiplys two numbers
func (gf *GaloisField) Multiply(a, b int) int {
if a == 0 || b == 0 {
return 0
}
return gf.ALogTbl[(gf.LogTbl[a]+gf.LogTbl[b])%(gf.Size-1)]
}
// Divide divides two numbers
func (gf *GaloisField) Divide(a, b int) int {
if b == 0 {
panic("divide by zero")
} else if a == 0 {
return 0
}
return gf.ALogTbl[(gf.LogTbl[a]-gf.LogTbl[b])%(gf.Size-1)]
}
func (gf *GaloisField) Invers(num int) int {
return gf.ALogTbl[(gf.Size-1)-gf.LogTbl[num]]
}

View File

@@ -0,0 +1,59 @@
package utils
import (
"testing"
)
func Test_GF(t *testing.T) {
log := []int{
0, 255, 1, 240, 2, 225, 241, 53, 3, 38, 226, 133, 242, 43, 54, 210,
4, 195, 39, 114, 227, 106, 134, 28, 243, 140, 44, 23, 55, 118, 211, 234,
5, 219, 196, 96, 40, 222, 115, 103, 228, 78, 107, 125, 135, 8, 29, 162,
244, 186, 141, 180, 45, 99, 24, 49, 56, 13, 119, 153, 212, 199, 235, 91,
6, 76, 220, 217, 197, 11, 97, 184, 41, 36, 223, 253, 116, 138, 104, 193,
229, 86, 79, 171, 108, 165, 126, 145, 136, 34, 9, 74, 30, 32, 163, 84,
245, 173, 187, 204, 142, 81, 181, 190, 46, 88, 100, 159, 25, 231, 50, 207,
57, 147, 14, 67, 120, 128, 154, 248, 213, 167, 200, 63, 236, 110, 92, 176,
7, 161, 77, 124, 221, 102, 218, 95, 198, 90, 12, 152, 98, 48, 185, 179,
42, 209, 37, 132, 224, 52, 254, 239, 117, 233, 139, 22, 105, 27, 194, 113,
230, 206, 87, 158, 80, 189, 172, 203, 109, 175, 166, 62, 127, 247, 146, 66,
137, 192, 35, 252, 10, 183, 75, 216, 31, 83, 33, 73, 164, 144, 85, 170,
246, 65, 174, 61, 188, 202, 205, 157, 143, 169, 82, 72, 182, 215, 191, 251,
47, 178, 89, 151, 101, 94, 160, 123, 26, 112, 232, 21, 51, 238, 208, 131,
58, 69, 148, 18, 15, 16, 68, 17, 121, 149, 129, 19, 155, 59, 249, 70,
214, 250, 168, 71, 201, 156, 64, 60, 237, 130, 111, 20, 93, 122, 177, 150,
}
alog := []int{
1, 2, 4, 8, 16, 32, 64, 128, 45, 90, 180, 69, 138, 57, 114, 228,
229, 231, 227, 235, 251, 219, 155, 27, 54, 108, 216, 157, 23, 46, 92, 184,
93, 186, 89, 178, 73, 146, 9, 18, 36, 72, 144, 13, 26, 52, 104, 208,
141, 55, 110, 220, 149, 7, 14, 28, 56, 112, 224, 237, 247, 195, 171, 123,
246, 193, 175, 115, 230, 225, 239, 243, 203, 187, 91, 182, 65, 130, 41, 82,
164, 101, 202, 185, 95, 190, 81, 162, 105, 210, 137, 63, 126, 252, 213, 135,
35, 70, 140, 53, 106, 212, 133, 39, 78, 156, 21, 42, 84, 168, 125, 250,
217, 159, 19, 38, 76, 152, 29, 58, 116, 232, 253, 215, 131, 43, 86, 172,
117, 234, 249, 223, 147, 11, 22, 44, 88, 176, 77, 154, 25, 50, 100, 200,
189, 87, 174, 113, 226, 233, 255, 211, 139, 59, 118, 236, 245, 199, 163, 107,
214, 129, 47, 94, 188, 85, 170, 121, 242, 201, 191, 83, 166, 97, 194, 169,
127, 254, 209, 143, 51, 102, 204, 181, 71, 142, 49, 98, 196, 165, 103, 206,
177, 79, 158, 17, 34, 68, 136, 61, 122, 244, 197, 167, 99, 198, 161, 111,
222, 145, 15, 30, 60, 120, 240, 205, 183, 67, 134, 33, 66, 132, 37, 74,
148, 5, 10, 20, 40, 80, 160, 109, 218, 153, 31, 62, 124, 248, 221, 151,
3, 6, 12, 24, 48, 96, 192, 173, 119, 238, 241, 207, 179, 75, 150, 1,
}
gf := NewGaloisField(301, 256, 1)
if len(gf.LogTbl) != len(gf.ALogTbl) || len(gf.LogTbl) != len(log) {
t.Fail()
}
for i := 0; i < len(log); i++ {
if gf.LogTbl[i] != log[i] {
t.Error("Invalid Log Table")
}
if gf.ALogTbl[i] != alog[i] {
t.Error("Invalid ALog Table")
}
}
}

103
vendor/github.com/boombuler/barcode/utils/gfpoly.go generated vendored Normal file
View File

@@ -0,0 +1,103 @@
package utils
type GFPoly struct {
gf *GaloisField
Coefficients []int
}
func (gp *GFPoly) Degree() int {
return len(gp.Coefficients) - 1
}
func (gp *GFPoly) Zero() bool {
return gp.Coefficients[0] == 0
}
// GetCoefficient returns the coefficient of x ^ degree
func (gp *GFPoly) GetCoefficient(degree int) int {
return gp.Coefficients[gp.Degree()-degree]
}
func (gp *GFPoly) AddOrSubstract(other *GFPoly) *GFPoly {
if gp.Zero() {
return other
} else if other.Zero() {
return gp
}
smallCoeff := gp.Coefficients
largeCoeff := other.Coefficients
if len(smallCoeff) > len(largeCoeff) {
largeCoeff, smallCoeff = smallCoeff, largeCoeff
}
sumDiff := make([]int, len(largeCoeff))
lenDiff := len(largeCoeff) - len(smallCoeff)
copy(sumDiff, largeCoeff[:lenDiff])
for i := lenDiff; i < len(largeCoeff); i++ {
sumDiff[i] = int(gp.gf.AddOrSub(int(smallCoeff[i-lenDiff]), int(largeCoeff[i])))
}
return NewGFPoly(gp.gf, sumDiff)
}
func (gp *GFPoly) MultByMonominal(degree int, coeff int) *GFPoly {
if coeff == 0 {
return gp.gf.Zero()
}
size := len(gp.Coefficients)
result := make([]int, size+degree)
for i := 0; i < size; i++ {
result[i] = int(gp.gf.Multiply(int(gp.Coefficients[i]), int(coeff)))
}
return NewGFPoly(gp.gf, result)
}
func (gp *GFPoly) Multiply(other *GFPoly) *GFPoly {
if gp.Zero() || other.Zero() {
return gp.gf.Zero()
}
aCoeff := gp.Coefficients
aLen := len(aCoeff)
bCoeff := other.Coefficients
bLen := len(bCoeff)
product := make([]int, aLen+bLen-1)
for i := 0; i < aLen; i++ {
ac := int(aCoeff[i])
for j := 0; j < bLen; j++ {
bc := int(bCoeff[j])
product[i+j] = int(gp.gf.AddOrSub(int(product[i+j]), gp.gf.Multiply(ac, bc)))
}
}
return NewGFPoly(gp.gf, product)
}
func (gp *GFPoly) Divide(other *GFPoly) (quotient *GFPoly, remainder *GFPoly) {
quotient = gp.gf.Zero()
remainder = gp
fld := gp.gf
denomLeadTerm := other.GetCoefficient(other.Degree())
inversDenomLeadTerm := fld.Invers(int(denomLeadTerm))
for remainder.Degree() >= other.Degree() && !remainder.Zero() {
degreeDiff := remainder.Degree() - other.Degree()
scale := int(fld.Multiply(int(remainder.GetCoefficient(remainder.Degree())), inversDenomLeadTerm))
term := other.MultByMonominal(degreeDiff, scale)
itQuot := NewMonominalPoly(fld, degreeDiff, scale)
quotient = quotient.AddOrSubstract(itQuot)
remainder = remainder.AddOrSubstract(term)
}
return
}
func NewMonominalPoly(field *GaloisField, degree int, coeff int) *GFPoly {
if coeff == 0 {
return field.Zero()
}
result := make([]int, degree+1)
result[0] = coeff
return NewGFPoly(field, result)
}
func NewGFPoly(field *GaloisField, coefficients []int) *GFPoly {
for len(coefficients) > 1 && coefficients[0] == 0 {
coefficients = coefficients[1:]
}
return &GFPoly{field, coefficients}
}

View File

@@ -0,0 +1,44 @@
package utils
import (
"sync"
)
type ReedSolomonEncoder struct {
gf *GaloisField
polynomes []*GFPoly
m *sync.Mutex
}
func NewReedSolomonEncoder(gf *GaloisField) *ReedSolomonEncoder {
return &ReedSolomonEncoder{
gf, []*GFPoly{NewGFPoly(gf, []int{1})}, new(sync.Mutex),
}
}
func (rs *ReedSolomonEncoder) getPolynomial(degree int) *GFPoly {
rs.m.Lock()
defer rs.m.Unlock()
if degree >= len(rs.polynomes) {
last := rs.polynomes[len(rs.polynomes)-1]
for d := len(rs.polynomes); d <= degree; d++ {
next := last.Multiply(NewGFPoly(rs.gf, []int{1, rs.gf.ALogTbl[d-1+rs.gf.Base]}))
rs.polynomes = append(rs.polynomes, next)
last = next
}
}
return rs.polynomes[degree]
}
func (rs *ReedSolomonEncoder) Encode(data []int, eccCount int) []int {
generator := rs.getPolynomial(eccCount)
info := NewGFPoly(rs.gf, data)
info = info.MultByMonominal(eccCount, 1)
_, remainder := info.Divide(generator)
result := make([]int, eccCount)
numZero := int(eccCount) - len(remainder.Coefficients)
copy(result[numZero:], remainder.Coefficients)
return result
}

19
vendor/github.com/boombuler/barcode/utils/runeint.go generated vendored Normal file
View File

@@ -0,0 +1,19 @@
package utils
// RuneToInt converts a rune between '0' and '9' to an integer between 0 and 9
// If the rune is outside of this range -1 is returned.
func RuneToInt(r rune) int {
if r >= '0' && r <= '9' {
return int(r - '0')
}
return -1
}
// IntToRune converts a digit 0 - 9 to the rune '0' - '9'. If the given int is outside
// of this range 'F' is returned!
func IntToRune(i int) rune {
if i >= 0 && i <= 9 {
return rune(i + '0')
}
return 'F'
}

View File

@@ -0,0 +1,24 @@
package utils
import "testing"
func Test_RuneToIntIntToRune(t *testing.T) {
if IntToRune(0) != '0' {
t.Errorf("failed IntToRune(0) returned %d", string(IntToRune(0)))
}
if IntToRune(9) != '9' {
t.Errorf("failed IntToRune(9) returned %d", IntToRune(9))
}
if IntToRune(10) != 'F' {
t.Errorf("failed IntToRune(10) returned %d", IntToRune(10))
}
if RuneToInt('0') != 0 {
t.Error("failed RuneToInt('0') returned %d", RuneToInt(0))
}
if RuneToInt('9') != 9 {
t.Error("failed RuneToInt('9') returned %d", RuneToInt(9))
}
if RuneToInt('F') != -1 {
t.Error("failed RuneToInt('F') returned %d", RuneToInt('F'))
}
}