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

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))
}