@moralcode/qrcode-brightscript 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Paramount
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # QR-Code-generator-brightscript
2
+
3
+ ## Introduction:
4
+
5
+ With this Library, adding a QR code to your Roku app is a simple as including this in your xml file:
6
+
7
+ \<qrCode text="https://www.paramountplus.com/" />
8
+
9
+ ## License
10
+
11
+ Copyright (c) 2022 Paramount (MIT License)
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+
31
+ ## Attribution
32
+
33
+ This work, ["QR-Code-generator-brightscript"](https://github.com/paramount-engineering/QR-Code-generator-brightscript), is a derivative of ["QR Code generator"](https://github.com/nayuki/QR-Code-generator) by [Project Nayuki](https://www.nayuki.io/page/qr-code-generator-library), used under [MIT](https://choosealicense.com/licenses/mit/). ["QR-Code-generator-brightscript"](https://github.com/paramount-engineering/QR-Code-generator-brightscript) is licensed under [MIT](https://choosealicense.com/licenses/mit/) BY [Paramount](https://www.paramount.com).
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "@moralcode/qrcode-brightscript",
3
+ "version": "0.1.0",
4
+ "description": "A Roku component that can generate QR codes",
5
+ "keywords": [
6
+ "ropm",
7
+ "roku",
8
+ "brightscript",
9
+ "brighterscript"
10
+ ],
11
+ "files": [
12
+ "src/**/*"
13
+ ],
14
+ "ropm": {
15
+ "rootDir": "src"
16
+ }
17
+ }
@@ -0,0 +1,201 @@
1
+ '**************************************************************************************
2
+ ' QR Code generator library (Brightscript)
3
+ ' Copyright (c) Kevin Hoos.
4
+ '**************************************************************************************
5
+ ' Ported from:
6
+ ' Copyright (c) Project Nayuki. (MIT License)
7
+ ' https://www.nayuki.io/page/qr-code-generator-library
8
+ '
9
+ ' Permission is hereby granted, free of charge, to any person obtaining a copy of
10
+ ' this software and associated documentation files (the "Software"), to deal in
11
+ ' the Software without restriction, including without limitation the rights to
12
+ ' use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13
+ ' the Software, and to permit persons to whom the Software is furnished to do so,
14
+ ' subject to the following conditions:
15
+ ' - The above copyright notice and this permission notice shall be included in
16
+ ' all copies or substantial portions of the Software.
17
+ ' - The Software is provided "as is", without warranty of any kind, express or
18
+ ' implied, including but not limited to the warranties of merchantability,
19
+ ' fitness for a particular purpose and noninfringement. In no event shall the
20
+ ' authors or copyright holders be liable for any claim, damages or other
21
+ ' liability, whether in an action of contract, tort or otherwise, arising from,
22
+ ' out of or in connection with the Software or the use or other dealings in the
23
+ ' Software.
24
+ '**************************************************************************************
25
+
26
+
27
+ '---- QR Code symbol class ----
28
+
29
+ '**************************************************************************************
30
+ ' A QR Code symbol, which is a type of two-dimension barcode.
31
+ ' Invented by Denso Wave and described in the ISO/IEC 18004 standard.
32
+ ' Instances of this class represent an immutable square grid of dark and light cells.
33
+ ' The class provides static factory functions to create a QR Code from text or binary data.
34
+ ' The class covers the QR Code Model 2 specification, supporting all versions (sizes)
35
+ ' from 1 to 40, all 4 error correction levels, and 4 character encoding modes.
36
+ '
37
+ ' Ways to create a QR Code object:
38
+ ' - High level: Take the payload data and call QrCode.encodeText() or QrCode.encodeBinary().
39
+ ' - Mid level: Custom-make the list of segments and call QrCode.encodeSegments().
40
+ ' - Low level: Custom-make the array of data codeword bytes (including
41
+ ' segment headers and final padding, excluding error correction codewords),
42
+ ' supply the appropriate version number, and call the QrCode() constructor.
43
+ ' (Note that all ways require supplying the desired error correction level.)
44
+ '**************************************************************************************
45
+ function QrCode()
46
+ this = {}
47
+ '-- Static factory functions (high level) --
48
+ this.encodeText = _qrCode_high_encodeText
49
+ this.encodeBinary = _qrCode_high_encodeBinary
50
+
51
+
52
+ '-- Static factory functions (mid level) --
53
+ this.encodeSegments = _qrCode_mid_encodeSegments
54
+
55
+
56
+ '-- Fields --
57
+
58
+ ' The width and height of this QR Code, measured in modules, between
59
+ ' 21 and 177 (inclusive). This is equal to version * 4 + 17.
60
+ this.size = 0
61
+
62
+ ' The index of the mask pattern used in this QR Code, which is between 0 and 7 (inclusive).
63
+ ' Even if a QR Code is created with automatic masking requested (mask = -1),
64
+ ' the resulting object still has a mask value between 0 and 7.
65
+ this.mask = -1
66
+
67
+ ' The modules of this QR Code (false = light, true = dark).
68
+ ' Immutable after constructor finishes. Accessed through getModule().
69
+ this.modules = []
70
+
71
+ ' Indicates function modules that are not subjected to masking. Discarded when constructor finishes.
72
+ this.isFunction = []
73
+
74
+
75
+ '-- Constructor (low level) and fields --
76
+ this.constructor = _qrCode_low_constructor
77
+
78
+
79
+ '-- Accessor methods --
80
+ this.getModule = _qrCode_low_getModule
81
+
82
+
83
+ '-- Private helper methods for constructor: Drawing function modules --
84
+ this.drawFunctionPatterns = _qrCode_draw_drawFunctionPatterns
85
+ this.drawFormatBits = _qrCode_draw_drawFormatBits
86
+ this.drawVersion = _qrCode_draw_drawVersion
87
+ this.drawFinderPattern = _qrCode_draw_drawFinderPattern
88
+ this.drawAlignmentPattern = _qrCode_draw_drawAlignmentPattern
89
+ this.setFunctionModule = _qrCode_draw_setFunctionModule
90
+
91
+
92
+ '-- Private helper methods for constructor: Codewords and masking --
93
+ this.addEccAndInterleave = _qrCode_mask_addEccAndInterleave
94
+ this.drawCodewords = _qrCode_mask_drawCodewords
95
+ this.applyMask = _qrCode_mask_applyMask
96
+ this.getPenaltyScore = _qrCode_mask_getPenaltyScore
97
+
98
+
99
+ '-- Private helper functions --
100
+ this.getAlignmentPatternPositions = _qrCode_help_getAlignmentPatternPositions
101
+ this.getNumRawDataModules = _qrCode_help_getNumRawDataModules
102
+ this.getNumDataCodewords = _qrCode_help_getNumDataCodewords
103
+ this.reedSolomonComputeDivisor = _qrCode_help_reedSolomonComputeDivisor
104
+ this.reedSolomonComputeRemainder = _qrCode_help_reedSolomonComputeRemainder
105
+ this.reedSolomonMultiply = _qrCode_help_reedSolomonMultiply
106
+ this.finderPenaltyCountPatterns = _qrCode_help_finderPenaltyCountPatterns
107
+ this.finderPenaltyTerminateAndCount = _qrCode_help_finderPenaltyTerminateAndCount
108
+ this.finderPenaltyAddHistory = _qrCode_help_finderPenaltyAddHistory
109
+
110
+ this.QrSegment = QrSegment()
111
+ this.Ecc = []
112
+ levels = ["LOW", "MEDIUM", "QUARTILE", "HIGH"]
113
+ for each level in levels
114
+ ecc = CreateObject("roSGNode", "QREcc")
115
+ ecc.level = level
116
+ this.Ecc.push(ecc)
117
+ next
118
+
119
+
120
+ '-- Constants and tables --
121
+
122
+ ' The minimum version number supported in the QR Code Model 2 standard.
123
+ this.MIN_VERSION = 1
124
+ ' The maximum version number supported in the QR Code Model 2 standard.
125
+ this.MAX_VERSION = 40
126
+
127
+ ' For use in getPenaltyScore(), when evaluating which mask is best.
128
+ this.PENALTY_N1 = 3
129
+ this.PENALTY_N2 = 3
130
+ this.PENALTY_N3 = 40
131
+ this.PENALTY_N4 = 10
132
+
133
+ this.ECC_CODEWORDS_PER_BLOCK = [
134
+ ' Version: (note that index 0 is for padding, and is set to an illegal value)
135
+ '0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
136
+ [-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], ' Low
137
+ [-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28], ' Medium
138
+ [-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], ' Quartile
139
+ [-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30], ' High
140
+ ]
141
+
142
+ this.NUM_ERROR_CORRECTION_BLOCKS = [
143
+ ' Version: (note that index 0 is for padding, and is set to an illegal value)
144
+ '0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level
145
+ [-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25], ' Low
146
+ [-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49], ' Medium
147
+ [-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68], ' Quartile
148
+ [-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81], ' High
149
+ ]
150
+
151
+ return this
152
+ end function
153
+
154
+ function onTextChanged(nodeEvent)
155
+ time = createObject("roTimespan")
156
+ text = nodeEvent.getData()
157
+ qr = QrCode()
158
+ ecl = getEcl()
159
+ qr.encodeText(text, ecl)
160
+ ba = CreateObject("roByteArray")
161
+ ba.FromAsciiString(text)
162
+ digest = CreateObject("roEVPDigest")
163
+ digest.Setup("sha1")
164
+ sha1 = digest.Process(ba)
165
+ renderCode(qr, "tmp:/" + sha1 + ".png")
166
+ ?"Time:", time.totalMilliseconds(), text
167
+ end function
168
+
169
+ function getEcl()
170
+ ecl = CreateObject("roSGNode", "QREcc")
171
+ ecl.level = "LOW"
172
+ if not isNullOrEmpty(m.top.ecl) then
173
+ ecl.level = uCase(m.top.ecl)
174
+ end if
175
+ return ecl
176
+ end function
177
+
178
+ sub renderCode(qr as object, filename as string)
179
+ border = m.top.border
180
+ pixel = m.top.pixel
181
+ lightColor = m.top.lightColor
182
+ darkColor = m.top.darkColor
183
+ size = qr.size
184
+ imageSide = ((border * 2) + size) * pixel
185
+
186
+ bm = CreateObject("roBitmap", { width: imageSide, height: imageSide, AlphaEnable: true })
187
+ if bm <> invalid then
188
+ bm.DrawRect(0, 0, imageSide, imageSide, lightColor)
189
+ for y = 0 to size - 1
190
+ for x = 0 to size - 1
191
+ if qr.modules[y][x] = 1 then
192
+ bm.DrawRect((border + x) * pixel, (border + y) * pixel, pixel, pixel, darkColor)
193
+ end if
194
+ next
195
+ next
196
+ bm.Finish()
197
+ ba = bm.GetPng(0, 0, imageSide, imageSide)
198
+ ba.WriteFile(filename)
199
+ m.top.uri = filename
200
+ end if
201
+ end sub
@@ -0,0 +1,126 @@
1
+ '-- Private helper methods for constructor: Drawing function modules --
2
+
3
+ ' Reads this object's version field, and draws and marks all function modules.
4
+ function _qrCode_draw_drawFunctionPatterns()
5
+ ' Draw horizontal and vertical timing patterns
6
+ for i = 0 to m.size - 1
7
+ m.setFunctionModule(6, i, i MOD 2 = 0)
8
+ m.setFunctionModule(i, 6, i MOD 2 = 0)
9
+ next
10
+
11
+ ' Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
12
+ m.drawFinderPattern(3, 3)
13
+ m.drawFinderPattern(m.size - 4, 3)
14
+ m.drawFinderPattern(3, m.size - 4)
15
+
16
+ ' Draw numerous alignment patterns
17
+ alignPatPos = m.getAlignmentPatternPositions()
18
+ numAlign = alignPatPos.count()
19
+ for i = 0 to numAlign - 1
20
+ for j = 0 to numAlign - 1
21
+ ' Don't draw on the three finder corners
22
+ if (not ((i = 0) and (j = 0) or (i = 0) and (j = numAlign - 1) or (i = numAlign - 1) and (j = 0))) then
23
+ m.drawAlignmentPattern(alignPatPos[i], alignPatPos[j])
24
+ end if
25
+ next
26
+ next
27
+
28
+ ' Draw configuration data
29
+ m.drawFormatBits(0) ' Dummy mask value; overwritten later in the constructor
30
+ m.drawVersion()
31
+ end function
32
+
33
+
34
+ ' Draws two copies of the format bits (with its own error correction code)
35
+ ' based on the given mask and this object's error correction level field.
36
+ function _qrCode_draw_drawFormatBits(mask as integer)
37
+ ' Calculate error correction code and pack bits
38
+ data = m.errorCorrectionLevel.formatBits << 3 or mask ' errCorrLvl is uint2, mask is uint3
39
+ remain = data
40
+ for i = 0 to 9
41
+ remain = xor((remain << 1), (remain >> 9) * &h537)
42
+ next
43
+ bits = xor((data << 10 or remain), &h5412) ' uint15
44
+ assert(bits >> 15 = 0)
45
+
46
+ ' Draw first copy
47
+ for i = 0 to 5
48
+ m.setFunctionModule(8, i, getBit(bits, i))
49
+ next
50
+ m.setFunctionModule(8, 7, getBit(bits, 6))
51
+ m.setFunctionModule(8, 8, getBit(bits, 7))
52
+ m.setFunctionModule(7, 8, getBit(bits, 8))
53
+ for i = 9 to 14
54
+ m.setFunctionModule(14 - i, 8, getBit(bits, i))
55
+ next
56
+
57
+ ' Draw second copy
58
+ for i = 0 to 7
59
+ m.setFunctionModule(m.size - 1 - i, 8, getBit(bits, i))
60
+ next
61
+ for i = 8 to 14
62
+ m.setFunctionModule(8, m.size - 15 + i, getBit(bits, i))
63
+ next
64
+ m.setFunctionModule(8, m.size - 8, true) ' Always dark
65
+ end function
66
+
67
+
68
+ ' Draws two copies of the version bits (with its own error correction code),
69
+ ' based on this object's version field, iff 7 <= version <= 40.
70
+ function _qrCode_draw_drawVersion()
71
+ if (m.version < 7) then
72
+ return false
73
+ end if
74
+
75
+ ' Calculate error correction code and pack bits
76
+ remain = m.version ' version is uint6, in the range [7, 40]
77
+ for i = 0 to 11
78
+ remain = xor((remain << 1), (remain >> 11) * &h1F25)
79
+ next
80
+ bits = m.version << 12 or remain ' uint18
81
+ assert(bits >> 18 = 0)
82
+
83
+ ' Draw two copies
84
+ for i = 0 to 17
85
+ color = getBit(bits, i)
86
+ a = m.size - 11 + i MOD 3
87
+ b = floor(i / 3)
88
+ m.setFunctionModule(a, b, color)
89
+ m.setFunctionModule(b, a, color)
90
+ next
91
+ end function
92
+
93
+
94
+ ' Draws a 9*9 finder pattern including the border separator,
95
+ ' with the center module at (x, y). Modules can be out of bounds.
96
+ function _qrCode_draw_drawFinderPattern(x as integer, y as integer)
97
+ for dy = -4 to 4
98
+ for dx = -4 to 4
99
+ dist = max(abs(dx), abs(dy)) ' Chebyshev/infinity norm
100
+ xx = x + dx
101
+ yy = y + dy
102
+ if ((0 <= xx) and (xx < m.size) and (0 <= yy) and (yy < m.size)) then
103
+ m.setFunctionModule(xx, yy, (dist <> 2) and (dist <> 4))
104
+ end if
105
+ next
106
+ next
107
+ end function
108
+
109
+
110
+ ' Draws a 5*5 alignment pattern, with the center module
111
+ ' at (x, y). All modules must be in bounds.
112
+ function _qrCode_draw_drawAlignmentPattern(x as integer, y as integer)
113
+ for dy = -2 to 2
114
+ for dx = -2 to 2
115
+ m.setFunctionModule(x + dx, y + dy, max(abs(dx), abs(dy)) <> 1)
116
+ next
117
+ next
118
+ end function
119
+
120
+
121
+ ' Sets the color of a module and marks it as a function module.
122
+ ' Only used by the constructor. Coordinates must be in bounds.
123
+ function _qrCode_draw_setFunctionModule(x as integer, y as integer, isDark as boolean)
124
+ m.modules[y][x] = iif(isDark, 1, 0)
125
+ m.isFunction[y][x] = true
126
+ end function
@@ -0,0 +1,148 @@
1
+ '-- Private helper functions --
2
+
3
+ ' Returns an ascending list of positions of alignment patterns for this version number.
4
+ ' Each position is in the range [0,177), and are used on both the x and y axes.
5
+ ' This could be implemented as lookup table of 40 variable-length lists of integers.
6
+ function _qrCode_help_getAlignmentPatternPositions() as object
7
+ if (m.version = 1) then
8
+ return []
9
+ else
10
+ numAlign = floor(m.version / 7) + 2
11
+ stepSize = iif(m.version = 32, 26, ceil((m.version * 4 + 4) / (numAlign * 2 - 2)) * 2)
12
+ result = []
13
+ position = m.size - 7
14
+ while(result.count() < numAlign)
15
+ result.unshift(position)
16
+ position -= stepSize
17
+ end while
18
+ return result
19
+ end if
20
+ end function
21
+
22
+
23
+ ' Returns the number of data bits that can be stored in a QR Code of the given version number, after
24
+ ' all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
25
+ ' The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
26
+ function _qrCode_help_getNumRawDataModules(ver as integer) as integer
27
+ if ((ver < m.MIN_VERSION) or (ver > m.MAX_VERSION)) then
28
+ throw("Version number out of range")
29
+ end if
30
+ result = (16 * ver + 128) * ver + 64
31
+ if (ver >= 2) then
32
+ numAlign = floor(ver / 7) + 2
33
+ result -= (25 * numAlign - 10) * numAlign - 55
34
+ if (ver >= 7) then
35
+ result -= 36
36
+ end if
37
+ end if
38
+ assert((208 <= result) and (result <= 29648))
39
+ return result
40
+ end function
41
+
42
+
43
+ ' Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
44
+ ' QR Code of the given version number and error correction level, with remainder bits discarded.
45
+ ' This stateless pure function could be implemented as a (40*4)-cell lookup table.
46
+ function _qrCode_help_getNumDataCodewords(ver as integer, ecl as object) as integer
47
+ return floor(m.getNumRawDataModules(ver) / 8) - m.ECC_CODEWORDS_PER_BLOCK[ecl.ordinal][ver] * m.NUM_ERROR_CORRECTION_BLOCKS[ecl.ordinal][ver]
48
+ end function
49
+
50
+
51
+ ' Returns a Reed-Solomon ECC generator polynomial for the given degree. This could be
52
+ ' implemented as a lookup table over all possible parameter values, instead of as an algorithm.
53
+ function _qrCode_help_reedSolomonComputeDivisor(degree as integer) as object
54
+ if ((degree < 1) or (degree > 255)) then
55
+ throw("Degree out of range")
56
+ end if
57
+ ' Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
58
+ ' For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array [255, 8, 93].
59
+ result = []
60
+ for i = 0 to degree - 2
61
+ result.push(0)
62
+ next
63
+ result.push(1) ' Start off with the monomial x^0
64
+
65
+ ' Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
66
+ ' and drop the highest monomial term which is always 1x^degree.
67
+ ' Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).
68
+ root = 1
69
+ for i = 0 to degree - 1
70
+ ' Multiply the current product by (x - r^i)
71
+ for j = 0 to result.count() - 1
72
+ result[j] = m.reedSolomonMultiply(result[j], root)
73
+ if (j + 1 < result.count()) then
74
+ result[j] = xor(result[j], result[j + 1])
75
+ end if
76
+ next
77
+ root = m.reedSolomonMultiply(root, &h02)
78
+ next
79
+ return result
80
+ end function
81
+
82
+
83
+ ' Returns the Reed-Solomon error correction codeword for the given data and divisor polynomials.
84
+ function _qrCode_help_reedSolomonComputeRemainder(data as object, divisor as object) as object
85
+ result = []
86
+ for each _d in divisor ' Prefix d with underscore to avoid unused variable warning
87
+ result.push(0)
88
+ next
89
+ for each b in data ' Polynomial division
90
+ factor = xor(b, result.shift())
91
+ result.push(0)
92
+ for i = 0 to divisor.count() - 1
93
+ coef = divisor[i]
94
+ res = result[i]
95
+ result[i] = xor(res, m.reedSolomonMultiply(coef, factor))
96
+ next
97
+ next
98
+ return result
99
+ end function
100
+
101
+
102
+ ' Returns the product of the two given field elements modulo GF(2^8/0x11D). The arguments and result
103
+ ' are unsigned 8-bit integers. This could be implemented as a lookup table of 256*256 entries of uint8.
104
+ function _qrCode_help_reedSolomonMultiply(x as integer, y as integer) as integer
105
+ if ((x >> 8 <> 0) or (y >> 8 <> 0)) then
106
+ throw("Byte out of range")
107
+ end if
108
+ ' Russian peasant multiplication
109
+ z = 0
110
+ for i = 7 to 0 step -1
111
+ z = xor((z << 1), ((z >> 7) * &h11D))
112
+ z = xor(z, ((y >> i) and 1) * x)
113
+ next
114
+ assert(z >> 8 = 0)
115
+ return z
116
+ end function
117
+
118
+
119
+ ' Can only be called immediately after a light run is added, and
120
+ ' returns either 0, 1, or 2. A helper function for getPenaltyScore().
121
+ function _qrCode_help_finderPenaltyCountPatterns(runHistory as object) as integer
122
+ n = runHistory[1]
123
+ assert(n <= m.size * 3)
124
+ core = iif((n > 0) and (runHistory[2] = n) and (runHistory[3] = n * 3) and (runHistory[4] = n) and (runHistory[5] = n), 1, 0)
125
+ return (core and iif(runHistory[0] >= n * 4, 1, 0) and iif(runHistory[6] >= n, 1, 0)) + (core and iif(runHistory[6] >= n * 4, 1, 0) and iif(runHistory[0] >= n, 1, 0))
126
+ end function
127
+
128
+
129
+ ' Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore().
130
+ function _qrCode_help_finderPenaltyTerminateAndCount(currentRunColor as boolean, currentRunLength as integer, runHistory as object) as integer
131
+ if (currentRunColor) then ' Terminate dark run
132
+ m.finderPenaltyAddHistory(currentRunLength, runHistory)
133
+ currentRunLength = 0
134
+ end if
135
+ currentRunLength += m.size ' Add light border to final run
136
+ m.finderPenaltyAddHistory(currentRunLength, runHistory)
137
+ return m.finderPenaltyCountPatterns(runHistory)
138
+ end function
139
+
140
+
141
+ ' Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore().
142
+ function _qrCode_help_finderPenaltyAddHistory(currentRunLength as integer, runHistory as object)
143
+ if (runHistory[0] = 0)
144
+ currentRunLength += m.size ' Add light border to initial run
145
+ end if
146
+ runHistory.pop()
147
+ runHistory.unshift(currentRunLength)
148
+ end function
@@ -0,0 +1,20 @@
1
+ '-- Static factory functions (high level) --
2
+
3
+ ' Returns a QR Code representing the given Unicode text string at the given error correction level.
4
+ ' As a conservative upper bound, this function is guaranteed to succeed for strings that have 738 or fewer
5
+ ' Unicode code points (not UTF-16 code units) if the low error correction level is used. The smallest possible
6
+ ' QR Code version is automatically chosen for the output. The ECC level of the result may be higher than the
7
+ ' ecl argument if it can be done without increasing the version.
8
+ function _qrCode_high_encodeText(text as string, ecl as object) as object
9
+ segs = m.QrSegment.makeSegments(text)
10
+ return m.encodeSegments(segs, ecl)
11
+ end function
12
+
13
+ ' Returns a QR Code representing the given binary data at the given error correction level.
14
+ ' This function always encodes using the binary segment mode, not any text mode. The maximum number of
15
+ ' bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
16
+ ' The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
17
+ function _qrCode_high_encodeBinary(data as object, ecl as object) as object
18
+ seg = m.QrSegment.makeBytes(data)
19
+ return m.encodeSegments([seg], ecl)
20
+ end function
@@ -0,0 +1,68 @@
1
+ '-- Constructor (low level) and fields --
2
+
3
+ ' Creates a new QR Code with the given version number,
4
+ ' error correction level, data codeword bytes, and mask number.
5
+ ' This is a low - level API that most users should not use directly.
6
+ ' A mid - level API is the encodeSegments() function.
7
+ function _qrCode_low_constructor(version as integer, errorCorrectionLevel as object, dataCodewords as object, msk as integer)
8
+ ' The version number of this QR Code, which is between 1 and 40 (inclusive).
9
+ ' This determines the size of this barcode.
10
+ m.version = version
11
+
12
+ ' The error correction level used in this QR Code.
13
+ m.errorCorrectionLevel = errorCorrectionLevel
14
+
15
+ ' Check scalar arguments
16
+ if ((version < m.MIN_VERSION) or (version > m.MAX_VERSION)) then
17
+ throw("Version value out of range")
18
+ end if
19
+ if ((msk < -1) or (msk > 7)) then
20
+ throw("Mask value out of range")
21
+ end if
22
+ m.size = version * 4 + 17
23
+
24
+ ' Initialize both grids to be size * size arrays of boolean false
25
+ for y = 0 to m.size - 1
26
+ m.modules[y] = []
27
+ m.isFunction[y] = []
28
+ for x = 0 to m.size - 1
29
+ m.modules[y][x] = 0 ' Initially all light
30
+ m.isFunction[y][x] = false
31
+ next
32
+ next
33
+
34
+ ' Compute ECC, draw modules
35
+ m.drawFunctionPatterns()
36
+ allCodewords = m.addEccAndInterleave(dataCodewords)
37
+ m.drawCodewords(allCodewords)
38
+
39
+ ' Do masking
40
+ if (msk = -1) then ' Automatically choose best mask
41
+ minPenalty = 1000000000
42
+ for i = 0 to 7
43
+ m.applyMask(i)
44
+ m.drawFormatBits(i)
45
+ penalty = m.getPenaltyScore()
46
+ if (penalty < minPenalty) then
47
+ msk = i
48
+ minPenalty = penalty
49
+ end if
50
+ m.applyMask(i) ' Undoes the mask due to XOR
51
+ next
52
+ end if
53
+ assert((0 <= msk) and (msk <= 7))
54
+ m.mask = msk
55
+ m.applyMask(msk) ' Apply the final choice of mask
56
+ m.drawFormatBits(msk) ' Overwrite old format bits
57
+
58
+ m.isFunction = []
59
+ end function
60
+
61
+ '-- Accessor methods --
62
+
63
+ ' Returns the color of the module (pixel) at the given coordinates, which is false
64
+ ' for light or true for dark. The top left corner has the coordinates (x = 0, y = 0).
65
+ ' if the given coordinates are out of bounds, then false (light) is returned.
66
+ function _qrCode_low_getModule(x as integer, y as integer) as boolean
67
+ return (0 <= x) and (x < m.size) and (0 <= y) and (y < m.size) and m.modules[y][x]
68
+ end function