rqrcode_core 0.1.2 → 1.2.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +12 -14
- data/.gitignore +1 -0
- data/CHANGELOG.md +44 -0
- data/Gemfile.lock +33 -4
- data/README.md +56 -21
- data/Rakefile +17 -8
- data/lib/rqrcode_core/qrcode/qr_8bit_byte.rb +4 -12
- data/lib/rqrcode_core/qrcode/qr_alphanumeric.rb +18 -25
- data/lib/rqrcode_core/qrcode/qr_bit_buffer.rb +14 -24
- data/lib/rqrcode_core/qrcode/qr_code.rb +210 -286
- data/lib/rqrcode_core/qrcode/qr_math.rb +9 -10
- data/lib/rqrcode_core/qrcode/qr_multi.rb +13 -0
- data/lib/rqrcode_core/qrcode/qr_numeric.rb +9 -20
- data/lib/rqrcode_core/qrcode/qr_polynomial.rb +15 -15
- data/lib/rqrcode_core/qrcode/qr_rs_block.rb +8 -10
- data/lib/rqrcode_core/qrcode/qr_segment.rb +61 -0
- data/lib/rqrcode_core/qrcode/qr_util.rb +48 -49
- data/lib/rqrcode_core/qrcode.rb +11 -9
- data/lib/rqrcode_core/version.rb +1 -1
- data/rqrcode_core.gemspec +17 -17
- metadata +21 -4
@@ -2,141 +2,73 @@
|
|
2
2
|
|
3
3
|
module RQRCodeCore
|
4
4
|
QRMODE = {
|
5
|
-
:
|
6
|
-
:
|
7
|
-
:
|
8
|
-
}
|
5
|
+
mode_number: 1 << 0,
|
6
|
+
mode_alpha_numk: 1 << 1,
|
7
|
+
mode_8bit_byte: 1 << 2
|
8
|
+
}.freeze
|
9
9
|
|
10
10
|
QRMODE_NAME = {
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
|
11
|
+
number: :mode_number,
|
12
|
+
alphanumeric: :mode_alpha_numk,
|
13
|
+
byte_8bit: :mode_8bit_byte,
|
14
|
+
multi: :mode_multi
|
15
|
+
}.freeze
|
15
16
|
|
16
17
|
QRERRORCORRECTLEVEL = {
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
}
|
18
|
+
l: 1,
|
19
|
+
m: 0,
|
20
|
+
q: 3,
|
21
|
+
h: 2
|
22
|
+
}.freeze
|
22
23
|
|
23
24
|
QRMASKPATTERN = {
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
}
|
25
|
+
pattern000: 0,
|
26
|
+
pattern001: 1,
|
27
|
+
pattern010: 2,
|
28
|
+
pattern011: 3,
|
29
|
+
pattern100: 4,
|
30
|
+
pattern101: 5,
|
31
|
+
pattern110: 6,
|
32
|
+
pattern111: 7
|
33
|
+
}.freeze
|
33
34
|
|
34
35
|
QRMASKCOMPUTATIONS = [
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
]
|
36
|
+
proc { |i, j| (i + j) % 2 == 0 },
|
37
|
+
proc { |i, j| i % 2 == 0 },
|
38
|
+
proc { |i, j| j % 3 == 0 },
|
39
|
+
proc { |i, j| (i + j) % 3 == 0 },
|
40
|
+
proc { |i, j| ((i / 2).floor + (j / 3).floor) % 2 == 0 },
|
41
|
+
proc { |i, j| (i * j) % 2 + (i * j) % 3 == 0 },
|
42
|
+
proc { |i, j| ((i * j) % 2 + (i * j) % 3) % 2 == 0 },
|
43
|
+
proc { |i, j| ((i * j) % 3 + (i + j) % 2) % 2 == 0 }
|
44
|
+
].freeze
|
44
45
|
|
45
46
|
QRPOSITIONPATTERNLENGTH = (7 + 1) * 2 + 1
|
46
47
|
QRFORMATINFOLENGTH = 15
|
47
48
|
|
48
|
-
#http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable1-e.html
|
49
|
-
#http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable2-e.html
|
50
|
-
#http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable3-e.html
|
51
|
-
#http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable4-e.html
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
],
|
67
|
-
mode_8bit_byte: [
|
68
|
-
17, 32, 53, 78, 106, 134, 154, 192, 230, 271,
|
69
|
-
321, 367, 425, 458, 520, 586, 644, 718, 792, 858,
|
70
|
-
929, 1003, 1091, 1171, 1273, 1367, 1465, 1528, 1628, 1732,
|
71
|
-
1840, 1952, 2068, 2188, 2303, 2431, 2563, 2699, 2809, 2953
|
72
|
-
],
|
73
|
-
},
|
74
|
-
m: {
|
75
|
-
mode_number: [
|
76
|
-
34, 63, 101, 149, 202, 255, 293, 365, 432, 513,
|
77
|
-
604, 691, 796, 871, 991, 1082, 1212, 1346, 1500, 1600,
|
78
|
-
1708, 1872, 2059, 2188, 2395, 2544, 2701, 2857, 3035, 3289,
|
79
|
-
3486, 3693, 3909, 4134, 4343, 4588, 4775, 5039, 5313, 5596,
|
80
|
-
],
|
81
|
-
mode_alpha_numk: [
|
82
|
-
20, 38, 61, 90, 122, 154, 178, 221, 262, 311,
|
83
|
-
366, 419, 483, 528, 600, 656, 734, 816, 909, 970,
|
84
|
-
1035, 1134, 1248, 1326, 1451, 1542, 1637, 1732, 1839, 1994,
|
85
|
-
2113, 2238, 2369, 2506, 2632, 2780, 2894, 3054, 3220, 3391
|
86
|
-
],
|
87
|
-
mode_8bit_byte: [
|
88
|
-
14, 26, 42, 62, 84, 106, 122, 152, 180, 213,
|
89
|
-
251, 287, 331, 362, 412, 450, 504, 560, 624, 666,
|
90
|
-
711, 779, 857, 911, 997, 1059, 1125, 1190, 1264, 1370,
|
91
|
-
1452, 1538, 1628, 1722, 1809, 1911, 1989, 2099, 2213, 2331
|
92
|
-
],
|
93
|
-
},
|
94
|
-
q: {
|
95
|
-
mode_number: [
|
96
|
-
27, 48, 77, 111, 144, 178, 207, 259, 312, 364,
|
97
|
-
427, 489, 580, 621, 703, 775, 876, 948, 1063, 1159,
|
98
|
-
1224, 1358, 1468, 1588, 1718, 1804, 1933, 2085, 2181, 2358,
|
99
|
-
2473, 2670, 2805, 2949, 3081, 3244, 3417, 3599, 3791, 3993
|
100
|
-
],
|
101
|
-
mode_alpha_numk: [
|
102
|
-
16, 29, 47, 67, 87, 108, 125, 157, 189, 221,
|
103
|
-
259, 296, 352, 376, 426, 470, 531, 574, 644, 702,
|
104
|
-
742, 823, 890, 963, 1041, 1094, 1172, 1263, 1322, 1429,
|
105
|
-
1499, 1618, 1700, 1787, 1867, 1966, 2071, 2181, 2298, 2420
|
106
|
-
],
|
107
|
-
mode_8bit_byte: [
|
108
|
-
11, 20, 32, 46, 60, 74, 86, 108, 130, 151,
|
109
|
-
177, 203, 241, 258, 292, 22, 364, 394, 442, 482,
|
110
|
-
509, 565, 611, 661, 715, 751, 805, 868, 908, 982,
|
111
|
-
1030, 1112, 1168, 1228, 1283, 1351, 1423, 1499, 1579, 1663
|
112
|
-
],
|
113
|
-
},
|
114
|
-
h: {
|
115
|
-
mode_number: [
|
116
|
-
17, 34, 58, 82, 106, 139, 154, 202, 235, 288, 331, 374, 427, 468, 530, 602, 674,
|
117
|
-
331, 374, 427, 468, 530, 602, 674, 746, 813, 919,
|
118
|
-
969, 1056, 1108, 1228, 1286, 1425, 1501, 1581, 1677, 1782,
|
119
|
-
1897, 2022, 2157, 2301, 2361, 2524, 2625, 2735, 2927, 3057
|
120
|
-
|
121
|
-
],
|
122
|
-
mode_alpha_numk: [
|
123
|
-
10, 20, 35, 50, 64, 84, 93, 122, 143, 174, 200,
|
124
|
-
200, 227, 259, 283, 321, 365, 408, 452, 493, 557,
|
125
|
-
587, 640, 672, 744, 779, 864, 910, 958, 1016, 1080,
|
126
|
-
1150, 1226, 1307, 1394, 1431, 1530, 1591, 1658, 1774, 1852
|
127
|
-
],
|
128
|
-
mode_8bit_byte: [
|
129
|
-
7, 14, 24, 34, 44, 58, 64, 84, 98, 119,
|
130
|
-
137, 155, 177, 194, 220, 250, 280, 310, 338, 382,
|
131
|
-
403, 439, 461, 511, 535, 593, 625, 658, 698, 742,
|
132
|
-
790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273
|
133
|
-
],
|
134
|
-
},
|
135
|
-
}
|
49
|
+
# http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable1-e.html
|
50
|
+
# http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable2-e.html
|
51
|
+
# http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable3-e.html
|
52
|
+
# http://web.archive.org/web/20110710094955/http://www.denso-wave.com/qrcode/vertable4-e.html
|
53
|
+
QRMAXBITS = {
|
54
|
+
l: [152, 272, 440, 640, 864, 1088, 1248, 1552, 1856, 2192, 2592, 2960, 3424, 3688, 4184,
|
55
|
+
4712, 5176, 5768, 6360, 6888, 7456, 8048, 8752, 9392, 10_208, 10_960, 11_744, 12_248,
|
56
|
+
13_048, 13_880, 14_744, 15_640, 16_568, 17_528, 18_448, 19_472, 20_528, 21_616, 22_496, 23_648],
|
57
|
+
m: [128, 224, 352, 512, 688, 864, 992, 1232, 1456, 1728, 2032, 2320, 2672, 2920, 3320, 3624,
|
58
|
+
4056, 4504, 5016, 5352, 5712, 6256, 6880, 7312, 8000, 8496, 9024, 9544, 10_136, 10_984,
|
59
|
+
11_640, 12_328, 13_048, 13_800, 14_496, 15_312, 15_936, 16_816, 17_728, 18_672],
|
60
|
+
q: [104, 176, 272, 384, 496, 608, 704, 880, 1056, 1232, 1440, 1648, 1952, 2088, 2360, 2600, 2936,
|
61
|
+
3176, 3560, 3880, 4096, 4544, 4912, 5312, 5744, 6032, 6464, 6968, 7288, 7880, 8264, 8920, 9368,
|
62
|
+
9848, 10288, 10832, 11408, 12016, 12656, 13328],
|
63
|
+
h: [72, 128, 208, 288, 368, 480, 528, 688, 800, 976, 1120, 1264, 1440, 1576, 1784,
|
64
|
+
2024, 2264, 2504, 2728, 3080, 3248, 3536, 3712, 4112, 4304, 4768, 5024, 5288, 5608, 5960,
|
65
|
+
6344, 6760, 7208, 7688, 7888, 8432, 8768, 9136, 9776, 10_208]
|
66
|
+
}.freeze
|
136
67
|
|
137
68
|
# StandardErrors
|
138
69
|
|
139
70
|
class QRCodeArgumentError < ArgumentError; end
|
71
|
+
|
140
72
|
class QRCodeRunTimeError < RuntimeError; end
|
141
73
|
|
142
74
|
# == Creation
|
@@ -151,72 +83,61 @@ module RQRCodeCore
|
|
151
83
|
class QRCode
|
152
84
|
attr_reader :modules, :module_count, :version
|
153
85
|
|
154
|
-
# Expects a string to be parsed in, other args are optional
|
86
|
+
# Expects a string or array (for multi-segment encoding) to be parsed in, other args are optional
|
155
87
|
#
|
156
|
-
# #
|
157
|
-
# # size
|
158
|
-
# #
|
88
|
+
# # data - the string, QRSegment or array of Hashes (with data:, mode: keys) you wish to encode
|
89
|
+
# # size - the size (Integer) of the QR Code (defaults to smallest size needed to encode the data)
|
90
|
+
# # max_size - the max_size (Integer) of the QR Code (default RQRCodeCore::QRUtil.max_size)
|
91
|
+
# # level - the error correction level, can be:
|
159
92
|
# * Level :l 7% of code can be restored
|
160
93
|
# * Level :m 15% of code can be restored
|
161
94
|
# * Level :q 25% of code can be restored
|
162
95
|
# * Level :h 30% of code can be restored (default :h)
|
163
|
-
# # mode
|
96
|
+
# # mode - the mode of the QR Code (defaults to alphanumeric or byte_8bit, depending on the input data, only used when data is a string):
|
164
97
|
# * :number
|
165
98
|
# * :alphanumeric
|
166
99
|
# * :byte_8bit
|
167
100
|
# * :kanji
|
168
101
|
#
|
169
102
|
# qr = RQRCodeCore::QRCode.new('hello world', size: 1, level: :m, mode: :alphanumeric)
|
170
|
-
#
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
103
|
+
# segment_qr = QRCodeCore::QRCode.new({ data: 'foo', mode: :byte_8bit })
|
104
|
+
# multi_qr = RQRCodeCore::QRCode.new([{ data: 'foo', mode: :byte_8bit }, { data: 'bar1', mode: :alphanumeric }])
|
105
|
+
|
106
|
+
def initialize(data, *args)
|
107
|
+
options = extract_options!(args)
|
108
|
+
|
109
|
+
level = (options[:level] || :h).to_sym
|
110
|
+
max_size = options[:max_size] || QRUtil.max_size
|
111
|
+
|
112
|
+
@data = case data
|
113
|
+
when String
|
114
|
+
QRSegment.new(data: data, mode: options[:mode])
|
115
|
+
when Array
|
116
|
+
raise QRCodeArgumentError, "Array must contain Hashes with :data and :mode keys" unless data.all? { |seg| seg.is_a?(Hash) && %i[data mode].all? { |s| seg.key? s } }
|
117
|
+
data.map { |seg| QRSegment.new(**seg) }
|
118
|
+
when QRSegment
|
119
|
+
data
|
120
|
+
else
|
121
|
+
raise QRCodeArgumentError, "data must be a String, QRSegment, or an Array"
|
175
122
|
end
|
123
|
+
@error_correct_level = QRERRORCORRECTLEVEL[level]
|
176
124
|
|
177
|
-
|
178
|
-
level = (options[:level] || :h).to_sym
|
179
|
-
|
180
|
-
if !QRERRORCORRECTLEVEL.has_key?(level)
|
125
|
+
unless @error_correct_level
|
181
126
|
raise QRCodeArgumentError, "Unknown error correction level `#{level.inspect}`"
|
182
127
|
end
|
183
128
|
|
184
|
-
|
185
|
-
|
186
|
-
mode = QRMODE_NAME[(options[:mode] || '').to_sym]
|
187
|
-
# If mode is not explicitely given choose mode according to data type
|
188
|
-
mode ||= case
|
189
|
-
when RQRCodeCore::QRNumeric.valid_data?(@data)
|
190
|
-
QRMODE_NAME[:number]
|
191
|
-
when QRAlphanumeric.valid_data?(@data)
|
192
|
-
QRMODE_NAME[:alphanumeric]
|
193
|
-
else
|
194
|
-
QRMODE_NAME[:byte_8bit]
|
195
|
-
end
|
196
|
-
|
197
|
-
max_size_array = QRMAXDIGITS[level][mode]
|
198
|
-
size = options[:size] || smallest_size_for(string, max_size_array)
|
129
|
+
size = options[:size] || minimum_version(limit: max_size)
|
199
130
|
|
200
|
-
if size >
|
131
|
+
if size > max_size
|
201
132
|
raise QRCodeArgumentError, "Given size greater than maximum possible size of #{QRUtil.max_size}"
|
202
133
|
end
|
203
134
|
|
204
|
-
@
|
205
|
-
@
|
206
|
-
@
|
207
|
-
@
|
208
|
-
@
|
209
|
-
|
210
|
-
when :mode_number
|
211
|
-
QRNumeric.new( @data )
|
212
|
-
when :mode_alpha_numk
|
213
|
-
QRAlphanumeric.new( @data )
|
214
|
-
else
|
215
|
-
QR8bitByte.new( @data )
|
216
|
-
end
|
217
|
-
|
218
|
-
@data_cache = nil
|
219
|
-
self.make
|
135
|
+
@version = size
|
136
|
+
@module_count = @version * 4 + QRPOSITIONPATTERNLENGTH
|
137
|
+
@modules = Array.new(@module_count)
|
138
|
+
@data_list = multi_segment? ? QRMulti.new(@data) : @data.writer
|
139
|
+
@data_cache = nil
|
140
|
+
make
|
220
141
|
end
|
221
142
|
|
222
143
|
# <tt>checked?</tt> is called with a +col+ and +row+ parameter. This will
|
@@ -227,7 +148,7 @@ module RQRCodeCore
|
|
227
148
|
# instance.checked?( 10, 10 ) => true
|
228
149
|
#
|
229
150
|
|
230
|
-
def checked?(
|
151
|
+
def checked?(row, col)
|
231
152
|
if !row.between?(0, @module_count - 1) || !col.between?(0, @module_count - 1)
|
232
153
|
raise QRCodeRunTimeError, "Invalid row/column pair: #{row}, #{col}"
|
233
154
|
end
|
@@ -241,7 +162,7 @@ module RQRCodeCore
|
|
241
162
|
# generated as a string. It will not be able to be read
|
242
163
|
# in this format by a QR Code reader, but will give you an
|
243
164
|
# idea if the final outout. It takes two optional args
|
244
|
-
# +:
|
165
|
+
# +:dark+ and +:light+ which are there for you to choose
|
245
166
|
# how the output looks. Here's an example of it's use:
|
246
167
|
#
|
247
168
|
# instance.to_s =>
|
@@ -255,11 +176,11 @@ module RQRCodeCore
|
|
255
176
|
# EQEEEQEQQEEEEEQEQQQQQQQEEQEQEEEQE
|
256
177
|
#
|
257
178
|
|
258
|
-
def to_s(
|
259
|
-
options
|
260
|
-
dark
|
261
|
-
light
|
262
|
-
quiet_zone_size
|
179
|
+
def to_s(*args)
|
180
|
+
options = extract_options!(args)
|
181
|
+
dark = options[:dark] || "x"
|
182
|
+
light = options[:light] || " "
|
183
|
+
quiet_zone_size = options[:quiet_zone_size] || 0
|
263
184
|
|
264
185
|
rows = []
|
265
186
|
|
@@ -293,6 +214,11 @@ module RQRCodeCore
|
|
293
214
|
QRERRORCORRECTLEVEL.invert[@error_correct_level]
|
294
215
|
end
|
295
216
|
|
217
|
+
# Return true if this QR Code includes multiple encoded segments
|
218
|
+
def multi_segment?
|
219
|
+
@data.is_a?(Array)
|
220
|
+
end
|
221
|
+
|
296
222
|
# Return a symbol in QRMODE.keys for current mode used
|
297
223
|
def mode
|
298
224
|
case @data_list
|
@@ -309,12 +235,12 @@ module RQRCodeCore
|
|
309
235
|
|
310
236
|
def make #:nodoc:
|
311
237
|
prepare_common_patterns
|
312
|
-
make_impl(
|
238
|
+
make_impl(false, get_best_mask_pattern)
|
313
239
|
end
|
314
240
|
|
315
241
|
private
|
316
242
|
|
317
|
-
def prepare_common_patterns
|
243
|
+
def prepare_common_patterns #:nodoc:
|
318
244
|
@modules.map! { |row| Array.new(@module_count) }
|
319
245
|
|
320
246
|
place_position_probe_pattern(0, 0)
|
@@ -326,7 +252,7 @@ module RQRCodeCore
|
|
326
252
|
@common_patterns = @modules.map(&:clone)
|
327
253
|
end
|
328
254
|
|
329
|
-
def make_impl(
|
255
|
+
def make_impl(test, mask_pattern) #:nodoc:
|
330
256
|
@modules = @common_patterns.map(&:clone)
|
331
257
|
|
332
258
|
place_format_info(test, mask_pattern)
|
@@ -338,20 +264,19 @@ module RQRCodeCore
|
|
338
264
|
)
|
339
265
|
end
|
340
266
|
|
341
|
-
map_data(
|
267
|
+
map_data(@data_cache, mask_pattern)
|
342
268
|
end
|
343
269
|
|
344
|
-
|
345
|
-
def place_position_probe_pattern( row, col ) #:nodoc:
|
270
|
+
def place_position_probe_pattern(row, col) #:nodoc:
|
346
271
|
(-1..7).each do |r|
|
347
|
-
next
|
272
|
+
next unless (row + r).between?(0, @module_count - 1)
|
348
273
|
|
349
274
|
(-1..7).each do |c|
|
350
|
-
next
|
275
|
+
next unless (col + c).between?(0, @module_count - 1)
|
351
276
|
|
352
277
|
is_vert_line = (r.between?(0, 6) && (c == 0 || c == 6))
|
353
278
|
is_horiz_line = (c.between?(0, 6) && (r == 0 || r == 6))
|
354
|
-
is_square = r.between?(2,4) && c.between?(2, 4)
|
279
|
+
is_square = r.between?(2, 4) && c.between?(2, 4)
|
355
280
|
|
356
281
|
is_part_of_probe = is_vert_line || is_horiz_line || is_square
|
357
282
|
@modules[row + r][col + c] = is_part_of_probe
|
@@ -359,14 +284,13 @@ module RQRCodeCore
|
|
359
284
|
end
|
360
285
|
end
|
361
286
|
|
362
|
-
|
363
287
|
def get_best_mask_pattern #:nodoc:
|
364
288
|
min_lost_point = 0
|
365
289
|
pattern = 0
|
366
290
|
|
367
|
-
(
|
368
|
-
make_impl(
|
369
|
-
lost_point = QRUtil.get_lost_points(
|
291
|
+
(0...8).each do |i|
|
292
|
+
make_impl(true, i)
|
293
|
+
lost_point = QRUtil.get_lost_points(modules)
|
370
294
|
|
371
295
|
if i == 0 || min_lost_point > lost_point
|
372
296
|
min_lost_point = lost_point
|
@@ -376,14 +300,12 @@ module RQRCodeCore
|
|
376
300
|
pattern
|
377
301
|
end
|
378
302
|
|
379
|
-
|
380
303
|
def place_timing_pattern #:nodoc:
|
381
|
-
(
|
304
|
+
(8...@module_count - 8).each do |i|
|
382
305
|
@modules[i][6] = @modules[6][i] = i % 2 == 0
|
383
306
|
end
|
384
307
|
end
|
385
308
|
|
386
|
-
|
387
309
|
def place_position_adjust_pattern #:nodoc:
|
388
310
|
positions = QRUtil.get_pattern_positions(@version)
|
389
311
|
|
@@ -391,9 +313,9 @@ module RQRCodeCore
|
|
391
313
|
positions.each do |col|
|
392
314
|
next unless @modules[row][col].nil?
|
393
315
|
|
394
|
-
(
|
395
|
-
(
|
396
|
-
is_part_of_pattern = (r.abs == 2 || c.abs == 2 || (
|
316
|
+
(-2..2).each do |r|
|
317
|
+
(-2..2).each do |c|
|
318
|
+
is_part_of_pattern = (r.abs == 2 || c.abs == 2 || (r == 0 && c == 0))
|
397
319
|
@modules[row + r][col + c] = is_part_of_pattern
|
398
320
|
end
|
399
321
|
end
|
@@ -401,69 +323,65 @@ module RQRCodeCore
|
|
401
323
|
end
|
402
324
|
end
|
403
325
|
|
404
|
-
|
405
326
|
def place_version_info(test) #:nodoc:
|
406
327
|
bits = QRUtil.get_bch_version(@version)
|
407
328
|
|
408
|
-
(
|
409
|
-
mod = (
|
410
|
-
@modules[
|
411
|
-
@modules[
|
329
|
+
(0...18).each do |i|
|
330
|
+
mod = (!test && ((bits >> i) & 1) == 1)
|
331
|
+
@modules[(i / 3).floor][ i % 3 + @module_count - 8 - 3 ] = mod
|
332
|
+
@modules[i % 3 + @module_count - 8 - 3][ (i / 3).floor ] = mod
|
412
333
|
end
|
413
334
|
end
|
414
335
|
|
415
|
-
|
416
336
|
def place_format_info(test, mask_pattern) #:nodoc:
|
417
337
|
data = (@error_correct_level << 3 | mask_pattern)
|
418
338
|
bits = QRUtil.get_bch_format_info(data)
|
419
339
|
|
420
340
|
QRFORMATINFOLENGTH.times do |i|
|
421
|
-
mod = (!test && (
|
341
|
+
mod = (!test && ((bits >> i) & 1) == 1)
|
422
342
|
|
423
343
|
# vertical
|
424
|
-
if i < 6
|
425
|
-
|
344
|
+
row = if i < 6
|
345
|
+
i
|
426
346
|
elsif i < 8
|
427
|
-
|
347
|
+
i + 1
|
428
348
|
else
|
429
|
-
|
349
|
+
@module_count - 15 + i
|
430
350
|
end
|
431
351
|
@modules[row][8] = mod
|
432
352
|
|
433
353
|
# horizontal
|
434
|
-
if i < 8
|
435
|
-
|
354
|
+
col = if i < 8
|
355
|
+
@module_count - i - 1
|
436
356
|
elsif i < 9
|
437
|
-
|
357
|
+
15 - i - 1 + 1
|
438
358
|
else
|
439
|
-
|
359
|
+
15 - i - 1
|
440
360
|
end
|
441
361
|
@modules[8][col] = mod
|
442
362
|
end
|
443
363
|
|
444
364
|
# fixed module
|
445
|
-
@modules[
|
365
|
+
@modules[@module_count - 8][8] = !test
|
446
366
|
end
|
447
367
|
|
448
|
-
|
449
|
-
def map_data( data, mask_pattern ) #:nodoc:
|
368
|
+
def map_data(data, mask_pattern) #:nodoc:
|
450
369
|
inc = -1
|
451
370
|
row = @module_count - 1
|
452
371
|
bit_index = 7
|
453
372
|
byte_index = 0
|
454
373
|
|
455
|
-
(
|
456
|
-
col
|
374
|
+
(@module_count - 1).step(1, -2) do |col|
|
375
|
+
col -= 1 if col <= 6
|
457
376
|
|
458
|
-
|
459
|
-
(
|
460
|
-
|
461
|
-
if @modules[row][ col - c ].nil?
|
377
|
+
loop do
|
378
|
+
(0...2).each do |c|
|
379
|
+
if @modules[row][col - c].nil?
|
462
380
|
dark = false
|
463
381
|
if byte_index < data.size && !data[byte_index].nil?
|
464
|
-
dark = ((
|
382
|
+
dark = ((QRUtil.rszf(data[byte_index], bit_index) & 1) == 1)
|
465
383
|
end
|
466
|
-
mask = QRUtil.get_mask(
|
384
|
+
mask = QRUtil.get_mask(mask_pattern, row, col - c)
|
467
385
|
dark = !dark if mask
|
468
386
|
@modules[row][ col - c ] = dark
|
469
387
|
bit_index -= 1
|
@@ -486,101 +404,107 @@ module RQRCodeCore
|
|
486
404
|
end
|
487
405
|
end
|
488
406
|
|
489
|
-
def
|
490
|
-
|
491
|
-
ver = max_size_array.index{|i| i >= l}
|
492
|
-
raise QRCodeRunTimeError,"code length overflow. (#{l} digits > any version capacity)" unless ver
|
493
|
-
ver + 1
|
494
|
-
end
|
407
|
+
def minimum_version(limit: QRUtil.max_size, version: 1)
|
408
|
+
raise QRCodeRunTimeError, "Data length exceed maximum capacity of version #{limit}" if version > limit
|
495
409
|
|
496
|
-
|
497
|
-
arr.last.is_a?(::Hash) ? arr.pop : {}
|
498
|
-
end
|
410
|
+
max_size_bits = QRMAXBITS[error_correction_level][version - 1]
|
499
411
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
end
|
412
|
+
size_bits = multi_segment? ? @data.sum { |seg| seg.size(version) } : @data.size(version)
|
413
|
+
|
414
|
+
return version if size_bits < max_size_bits
|
504
415
|
|
505
|
-
|
416
|
+
minimum_version(limit: limit, version: version + 1)
|
506
417
|
end
|
507
418
|
|
508
|
-
def
|
509
|
-
|
510
|
-
|
511
|
-
buffer = QRBitBuffer.new(version)
|
419
|
+
def extract_options!(arr) #:nodoc:
|
420
|
+
arr.last.is_a?(::Hash) ? arr.pop : {}
|
421
|
+
end
|
512
422
|
|
513
|
-
|
514
|
-
|
423
|
+
class << self
|
424
|
+
def count_max_data_bits(rs_blocks) #:nodoc:
|
425
|
+
max_data_bytes = rs_blocks.reduce(0) do |sum, rs_block|
|
426
|
+
sum + rs_block.data_count
|
427
|
+
end
|
515
428
|
|
516
|
-
|
517
|
-
raise QRCodeRunTimeError, "code length overflow. (#{buffer.get_length_in_bits}>#{max_data_bits}). (Try a larger size!)"
|
429
|
+
max_data_bytes * 8
|
518
430
|
end
|
519
431
|
|
520
|
-
|
432
|
+
def create_data(version, error_correct_level, data_list) #:nodoc:
|
433
|
+
rs_blocks = QRRSBlock.get_rs_blocks(version, error_correct_level)
|
434
|
+
max_data_bits = QRCode.count_max_data_bits(rs_blocks)
|
435
|
+
buffer = QRBitBuffer.new(version)
|
521
436
|
|
522
|
-
|
523
|
-
|
437
|
+
data_list.write(buffer)
|
438
|
+
buffer.end_of_message(max_data_bits)
|
524
439
|
|
440
|
+
if buffer.get_length_in_bits > max_data_bits
|
441
|
+
raise QRCodeRunTimeError, "code length overflow. (#{buffer.get_length_in_bits}>#{max_data_bits}). (Try a larger size!)"
|
442
|
+
end
|
525
443
|
|
526
|
-
|
527
|
-
offset = 0
|
528
|
-
max_dc_count = 0
|
529
|
-
max_ec_count = 0
|
530
|
-
dcdata = Array.new( rs_blocks.size )
|
531
|
-
ecdata = Array.new( rs_blocks.size )
|
444
|
+
buffer.pad_until(max_data_bits)
|
532
445
|
|
533
|
-
|
534
|
-
|
535
|
-
ec_count = rs_block.total_count - dc_count
|
536
|
-
max_dc_count = [ max_dc_count, dc_count ].max
|
537
|
-
max_ec_count = [ max_ec_count, ec_count ].max
|
446
|
+
QRCode.create_bytes(buffer, rs_blocks)
|
447
|
+
end
|
538
448
|
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
dcdata
|
449
|
+
def create_bytes(buffer, rs_blocks) #:nodoc:
|
450
|
+
offset = 0
|
451
|
+
max_dc_count = 0
|
452
|
+
max_ec_count = 0
|
453
|
+
dcdata = Array.new(rs_blocks.size)
|
454
|
+
ecdata = Array.new(rs_blocks.size)
|
455
|
+
|
456
|
+
rs_blocks.each_with_index do |rs_block, r|
|
457
|
+
dc_count = rs_block.data_count
|
458
|
+
ec_count = rs_block.total_count - dc_count
|
459
|
+
max_dc_count = [max_dc_count, dc_count].max
|
460
|
+
max_ec_count = [max_ec_count, ec_count].max
|
461
|
+
|
462
|
+
dcdata_block = Array.new(dc_count)
|
463
|
+
dcdata_block.size.times do |i|
|
464
|
+
dcdata_block[i] = 0xff & buffer.buffer[i + offset]
|
465
|
+
end
|
466
|
+
dcdata[r] = dcdata_block
|
544
467
|
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
468
|
+
offset += dc_count
|
469
|
+
rs_poly = QRUtil.get_error_correct_polynomial(ec_count)
|
470
|
+
raw_poly = QRPolynomial.new(dcdata[r], rs_poly.get_length - 1)
|
471
|
+
mod_poly = raw_poly.mod(rs_poly)
|
549
472
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
473
|
+
ecdata_block = Array.new(rs_poly.get_length - 1)
|
474
|
+
ecdata_block.size.times do |i|
|
475
|
+
mod_index = i + mod_poly.get_length - ecdata_block.size
|
476
|
+
ecdata_block[i] = mod_index >= 0 ? mod_poly.get(mod_index) : 0
|
477
|
+
end
|
478
|
+
ecdata[r] = ecdata_block
|
554
479
|
end
|
555
|
-
ecdata[r] = ecdata_block
|
556
|
-
end
|
557
480
|
|
558
|
-
|
559
|
-
|
560
|
-
|
481
|
+
total_code_count = rs_blocks.reduce(0) do |sum, rs_block|
|
482
|
+
sum + rs_block.total_count
|
483
|
+
end
|
561
484
|
|
562
|
-
|
563
|
-
|
485
|
+
data = Array.new(total_code_count)
|
486
|
+
index = 0
|
564
487
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
488
|
+
max_dc_count.times do |i|
|
489
|
+
rs_blocks.size.times do |r|
|
490
|
+
if i < dcdata[r].size
|
491
|
+
data[index] = dcdata[r][i]
|
492
|
+
index += 1
|
493
|
+
end
|
570
494
|
end
|
571
495
|
end
|
572
|
-
end
|
573
496
|
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
497
|
+
max_ec_count.times do |i|
|
498
|
+
rs_blocks.size.times do |r|
|
499
|
+
if i < ecdata[r].size
|
500
|
+
data[index] = ecdata[r][i]
|
501
|
+
index += 1
|
502
|
+
end
|
579
503
|
end
|
580
504
|
end
|
581
|
-
end
|
582
505
|
|
583
|
-
|
506
|
+
data
|
507
|
+
end
|
584
508
|
end
|
585
509
|
end
|
586
510
|
end
|