diff options
Diffstat (limited to 'vendor/github.com/skip2/go-qrcode/regular_symbol.go')
-rw-r--r-- | vendor/github.com/skip2/go-qrcode/regular_symbol.go | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/vendor/github.com/skip2/go-qrcode/regular_symbol.go b/vendor/github.com/skip2/go-qrcode/regular_symbol.go new file mode 100644 index 00000000..134be18e --- /dev/null +++ b/vendor/github.com/skip2/go-qrcode/regular_symbol.go @@ -0,0 +1,309 @@ +// go-qrcode +// Copyright 2014 Tom Harwood + +package qrcode + +import ( + bitset "github.com/skip2/go-qrcode/bitset" +) + +type regularSymbol struct { + version qrCodeVersion + mask int + + data *bitset.Bitset + + symbol *symbol + size int +} + +// Abbreviated true/false. +const ( + b0 = false + b1 = true +) + +var ( + alignmentPatternCenter = [][]int{ + {}, // Version 0 doesn't exist. + {}, // Version 1 doesn't use alignment patterns. + {6, 18}, + {6, 22}, + {6, 26}, + {6, 30}, + {6, 34}, + {6, 22, 38}, + {6, 24, 42}, + {6, 26, 46}, + {6, 28, 50}, + {6, 30, 54}, + {6, 32, 58}, + {6, 34, 62}, + {6, 26, 46, 66}, + {6, 26, 48, 70}, + {6, 26, 50, 74}, + {6, 30, 54, 78}, + {6, 30, 56, 82}, + {6, 30, 58, 86}, + {6, 34, 62, 90}, + {6, 28, 50, 72, 94}, + {6, 26, 50, 74, 98}, + {6, 30, 54, 78, 102}, + {6, 28, 54, 80, 106}, + {6, 32, 58, 84, 110}, + {6, 30, 58, 86, 114}, + {6, 34, 62, 90, 118}, + {6, 26, 50, 74, 98, 122}, + {6, 30, 54, 78, 102, 126}, + {6, 26, 52, 78, 104, 130}, + {6, 30, 56, 82, 108, 134}, + {6, 34, 60, 86, 112, 138}, + {6, 30, 58, 86, 114, 142}, + {6, 34, 62, 90, 118, 146}, + {6, 30, 54, 78, 102, 126, 150}, + {6, 24, 50, 76, 102, 128, 154}, + {6, 28, 54, 80, 106, 132, 158}, + {6, 32, 58, 84, 110, 136, 162}, + {6, 26, 54, 82, 110, 138, 166}, + {6, 30, 58, 86, 114, 142, 170}, + } + + finderPattern = [][]bool{ + {b1, b1, b1, b1, b1, b1, b1}, + {b1, b0, b0, b0, b0, b0, b1}, + {b1, b0, b1, b1, b1, b0, b1}, + {b1, b0, b1, b1, b1, b0, b1}, + {b1, b0, b1, b1, b1, b0, b1}, + {b1, b0, b0, b0, b0, b0, b1}, + {b1, b1, b1, b1, b1, b1, b1}, + } + + finderPatternSize = 7 + + finderPatternHorizontalBorder = [][]bool{ + {b0, b0, b0, b0, b0, b0, b0, b0}, + } + + finderPatternVerticalBorder = [][]bool{ + {b0}, + {b0}, + {b0}, + {b0}, + {b0}, + {b0}, + {b0}, + {b0}, + } + + alignmentPattern = [][]bool{ + {b1, b1, b1, b1, b1}, + {b1, b0, b0, b0, b1}, + {b1, b0, b1, b0, b1}, + {b1, b0, b0, b0, b1}, + {b1, b1, b1, b1, b1}, + } +) + +func buildRegularSymbol(version qrCodeVersion, mask int, + data *bitset.Bitset) (*symbol, error) { + m := ®ularSymbol{ + version: version, + mask: mask, + data: data, + + symbol: newSymbol(version.symbolSize(), version.quietZoneSize()), + size: version.symbolSize(), + } + + m.addFinderPatterns() + m.addAlignmentPatterns() + m.addTimingPatterns() + m.addFormatInfo() + m.addVersionInfo() + + ok, err := m.addData() + if !ok { + return nil, err + } + + return m.symbol, nil +} + +func (m *regularSymbol) addFinderPatterns() { + fpSize := finderPatternSize + fp := finderPattern + fpHBorder := finderPatternHorizontalBorder + fpVBorder := finderPatternVerticalBorder + + // Top left Finder Pattern. + m.symbol.set2dPattern(0, 0, fp) + m.symbol.set2dPattern(0, fpSize, fpHBorder) + m.symbol.set2dPattern(fpSize, 0, fpVBorder) + + // Top right Finder Pattern. + m.symbol.set2dPattern(m.size-fpSize, 0, fp) + m.symbol.set2dPattern(m.size-fpSize-1, fpSize, fpHBorder) + m.symbol.set2dPattern(m.size-fpSize-1, 0, fpVBorder) + + // Bottom left Finder Pattern. + m.symbol.set2dPattern(0, m.size-fpSize, fp) + m.symbol.set2dPattern(0, m.size-fpSize-1, fpHBorder) + m.symbol.set2dPattern(fpSize, m.size-fpSize-1, fpVBorder) +} + +func (m *regularSymbol) addAlignmentPatterns() { + for _, x := range alignmentPatternCenter[m.version.version] { + for _, y := range alignmentPatternCenter[m.version.version] { + if !m.symbol.empty(x, y) { + continue + } + + m.symbol.set2dPattern(x-2, y-2, alignmentPattern) + } + } +} + +func (m *regularSymbol) addTimingPatterns() { + value := true + + for i := finderPatternSize + 1; i < m.size-finderPatternSize; i++ { + m.symbol.set(i, finderPatternSize-1, value) + m.symbol.set(finderPatternSize-1, i, value) + + value = !value + } +} + +func (m *regularSymbol) addFormatInfo() { + fpSize := finderPatternSize + l := formatInfoLengthBits - 1 + + f := m.version.formatInfo(m.mask) + + // Bits 0-7, under the top right finder pattern. + for i := 0; i <= 7; i++ { + m.symbol.set(m.size-i-1, fpSize+1, f.At(l-i)) + } + + // Bits 0-5, right of the top left finder pattern. + for i := 0; i <= 5; i++ { + m.symbol.set(fpSize+1, i, f.At(l-i)) + } + + // Bits 6-8 on the corner of the top left finder pattern. + m.symbol.set(fpSize+1, fpSize, f.At(l-6)) + m.symbol.set(fpSize+1, fpSize+1, f.At(l-7)) + m.symbol.set(fpSize, fpSize+1, f.At(l-8)) + + // Bits 9-14 on the underside of the top left finder pattern. + for i := 9; i <= 14; i++ { + m.symbol.set(14-i, fpSize+1, f.At(l-i)) + } + + // Bits 8-14 on the right side of the bottom left finder pattern. + for i := 8; i <= 14; i++ { + m.symbol.set(fpSize+1, m.size-fpSize+i-8, f.At(l-i)) + } + + // Always dark symbol. + m.symbol.set(fpSize+1, m.size-fpSize-1, true) +} + +func (m *regularSymbol) addVersionInfo() { + fpSize := finderPatternSize + + v := m.version.versionInfo() + l := versionInfoLengthBits - 1 + + if v == nil { + return + } + + for i := 0; i < v.Len(); i++ { + // Above the bottom left finder pattern. + m.symbol.set(i/3, m.size-fpSize-4+i%3, v.At(l-i)) + + // Left of the top right finder pattern. + m.symbol.set(m.size-fpSize-4+i%3, i/3, v.At(l-i)) + } +} + +type direction uint8 + +const ( + up direction = iota + down +) + +func (m *regularSymbol) addData() (bool, error) { + xOffset := 1 + dir := up + + x := m.size - 2 + y := m.size - 1 + + for i := 0; i < m.data.Len(); i++ { + var mask bool + switch m.mask { + case 0: + mask = (y+x+xOffset)%2 == 0 + case 1: + mask = y%2 == 0 + case 2: + mask = (x+xOffset)%3 == 0 + case 3: + mask = (y+x+xOffset)%3 == 0 + case 4: + mask = (y/2+(x+xOffset)/3)%2 == 0 + case 5: + mask = (y*(x+xOffset))%2+(y*(x+xOffset))%3 == 0 + case 6: + mask = ((y*(x+xOffset))%2+((y*(x+xOffset))%3))%2 == 0 + case 7: + mask = ((y+x+xOffset)%2+((y*(x+xOffset))%3))%2 == 0 + } + + // != is equivalent to XOR. + m.symbol.set(x+xOffset, y, mask != m.data.At(i)) + + if i == m.data.Len()-1 { + break + } + + // Find next free bit in the symbol. + for { + if xOffset == 1 { + xOffset = 0 + } else { + xOffset = 1 + + if dir == up { + if y > 0 { + y-- + } else { + dir = down + x -= 2 + } + } else { + if y < m.size-1 { + y++ + } else { + dir = up + x -= 2 + } + } + } + + // Skip over the vertical timing pattern entirely. + if x == 5 { + x-- + } + + if m.symbol.empty(x+xOffset, y) { + break + } + } + } + + return true, nil +} |