Add 2fa for authentification (#383)
Fix user tests Add swagger docs Fix lint Add totp check when logging in Make totp enrollment work Add migration for totp table go mod vendor Add routes for totp routes Add route handler for totp routes Add basic implementation to enroll a user in totp Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/api/pulls/383
This commit is contained in:
1
vendor/github.com/boombuler/barcode/.gitignore
generated
vendored
Normal file
1
vendor/github.com/boombuler/barcode/.gitignore
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
.vscode/
|
21
vendor/github.com/boombuler/barcode/LICENSE
generated
vendored
Normal file
21
vendor/github.com/boombuler/barcode/LICENSE
generated
vendored
Normal 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
53
vendor/github.com/boombuler/barcode/README.md
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
[](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.
|
42
vendor/github.com/boombuler/barcode/barcode.go
generated
vendored
Normal file
42
vendor/github.com/boombuler/barcode/barcode.go
generated
vendored
Normal 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
|
||||
}
|
1
vendor/github.com/boombuler/barcode/go.mod
generated
vendored
Normal file
1
vendor/github.com/boombuler/barcode/go.mod
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module github.com/boombuler/barcode
|
66
vendor/github.com/boombuler/barcode/qr/alphanumeric.go
generated
vendored
Normal file
66
vendor/github.com/boombuler/barcode/qr/alphanumeric.go
generated
vendored
Normal 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
|
||||
}
|
23
vendor/github.com/boombuler/barcode/qr/automatic.go
generated
vendored
Normal file
23
vendor/github.com/boombuler/barcode/qr/automatic.go
generated
vendored
Normal 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)
|
||||
}
|
59
vendor/github.com/boombuler/barcode/qr/blocks.go
generated
vendored
Normal file
59
vendor/github.com/boombuler/barcode/qr/blocks.go
generated
vendored
Normal 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
|
||||
}
|
416
vendor/github.com/boombuler/barcode/qr/encoder.go
generated
vendored
Normal file
416
vendor/github.com/boombuler/barcode/qr/encoder.go
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
29
vendor/github.com/boombuler/barcode/qr/errorcorrection.go
generated
vendored
Normal file
29
vendor/github.com/boombuler/barcode/qr/errorcorrection.go
generated
vendored
Normal 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
|
||||
}
|
56
vendor/github.com/boombuler/barcode/qr/numeric.go
generated
vendored
Normal file
56
vendor/github.com/boombuler/barcode/qr/numeric.go
generated
vendored
Normal 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
|
||||
}
|
166
vendor/github.com/boombuler/barcode/qr/qrcode.go
generated
vendored
Normal file
166
vendor/github.com/boombuler/barcode/qr/qrcode.go
generated
vendored
Normal 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
|
||||
}
|
27
vendor/github.com/boombuler/barcode/qr/unicode.go
generated
vendored
Normal file
27
vendor/github.com/boombuler/barcode/qr/unicode.go
generated
vendored
Normal 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
|
||||
}
|
310
vendor/github.com/boombuler/barcode/qr/versioninfo.go
generated
vendored
Normal file
310
vendor/github.com/boombuler/barcode/qr/versioninfo.go
generated
vendored
Normal 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
|
||||
}
|
134
vendor/github.com/boombuler/barcode/scaledbarcode.go
generated
vendored
Normal file
134
vendor/github.com/boombuler/barcode/scaledbarcode.go
generated
vendored
Normal 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
|
||||
}
|
57
vendor/github.com/boombuler/barcode/utils/base1dcode.go
generated
vendored
Normal file
57
vendor/github.com/boombuler/barcode/utils/base1dcode.go
generated
vendored
Normal 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
|
||||
}
|
||||
|
||||
// New1DCodeIntCheckSum 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
119
vendor/github.com/boombuler/barcode/utils/bitlist.go
generated
vendored
Normal 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
|
||||
}
|
65
vendor/github.com/boombuler/barcode/utils/galoisfield.go
generated
vendored
Normal file
65
vendor/github.com/boombuler/barcode/utils/galoisfield.go
generated
vendored
Normal 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]]
|
||||
}
|
103
vendor/github.com/boombuler/barcode/utils/gfpoly.go
generated
vendored
Normal file
103
vendor/github.com/boombuler/barcode/utils/gfpoly.go
generated
vendored
Normal 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}
|
||||
}
|
44
vendor/github.com/boombuler/barcode/utils/reedsolomon.go
generated
vendored
Normal file
44
vendor/github.com/boombuler/barcode/utils/reedsolomon.go
generated
vendored
Normal 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
19
vendor/github.com/boombuler/barcode/utils/runeint.go
generated
vendored
Normal 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'
|
||||
}
|
Reference in New Issue
Block a user