mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Two factor authentication support (#630)
* Initial commit for 2FA support Signed-off-by: Andrew <write@imaginarycode.com> * Add vendored files * Add missing depends * A few clean ups * Added improvements, proper encryption * Better encryption key * Simplify "key" generation * Make 2FA enrollment page more robust * Fix typo * Rename twofa/2FA to TwoFactor * UNIQUE INDEX -> UNIQUE
This commit is contained in:
		
							
								
								
									
										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. | ||||
							
								
								
									
										18
									
								
								vendor/github.com/boombuler/barcode/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/boombuler/barcode/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| ##Introduction## | ||||
| This is a package for GO which can be used to create different types of barcodes. | ||||
|  | ||||
| ##Supported Barcode Types## | ||||
| * Aztec Code | ||||
| * Codabar | ||||
| * Code 128 | ||||
| * Code 39 | ||||
| * EAN 8 | ||||
| * EAN 13 | ||||
| * Datamatrix | ||||
| * QR Codes | ||||
| * 2 of 5 | ||||
|  | ||||
| ##Documentation## | ||||
| See [GoDoc](https://godoc.org/github.com/boombuler/barcode) | ||||
|  | ||||
| To create a barcode use the Encode function from one of the subpackages. | ||||
							
								
								
									
										21
									
								
								vendor/github.com/boombuler/barcode/barcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								vendor/github.com/boombuler/barcode/barcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package barcode | ||||
|  | ||||
| import "image" | ||||
|  | ||||
| // 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 | ||||
| 	CheckSum() int | ||||
| } | ||||
							
								
								
									
										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 | ||||
| } | ||||
							
								
								
									
										170
									
								
								vendor/github.com/boombuler/barcode/qr/qrcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								vendor/github.com/boombuler/barcode/qr/qrcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| 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{"QR Code", 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) CheckSum() int { | ||||
| 	return 0 | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										115
									
								
								vendor/github.com/boombuler/barcode/scaledbarcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								vendor/github.com/boombuler/barcode/scaledbarcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| 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 | ||||
| } | ||||
|  | ||||
| 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 *scaledBarcode) CheckSum() int { | ||||
| 	return bc.wrapped.CheckSum() | ||||
| } | ||||
|  | ||||
| // 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 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 then %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 &scaledBarcode{ | ||||
| 		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 then %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 &scaledBarcode{ | ||||
| 		bc, | ||||
| 		wrap, | ||||
| 		image.Rect(0, 0, width, height), | ||||
| 	}, nil | ||||
|  | ||||
| } | ||||
							
								
								
									
										48
									
								
								vendor/github.com/boombuler/barcode/utils/base1dcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/boombuler/barcode/utils/base1dcode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | ||||
| // 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 | ||||
| 	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 *base1DCode) CheckSum() int { | ||||
| 	return c.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, checksum int) barcode.Barcode { | ||||
| 	return &base1DCode{bars, codeKind, content, checksum} | ||||
| } | ||||
							
								
								
									
										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