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.
@@ -2,141 +2,73 @@
2
2
 
3
3
  module RQRCodeCore
4
4
  QRMODE = {
5
- :mode_number => 1 << 0,
6
- :mode_alpha_numk => 1 << 1,
7
- :mode_8bit_byte => 1 << 2,
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
- :number => :mode_number,
12
- :alphanumeric => :mode_alpha_numk,
13
- :byte_8bit => :mode_8bit_byte
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
- :l => 1,
18
- :m => 0,
19
- :q => 3,
20
- :h => 2
21
- }
18
+ l: 1,
19
+ m: 0,
20
+ q: 3,
21
+ h: 2
22
+ }.freeze
22
23
 
23
24
  QRMASKPATTERN = {
24
- :pattern000 => 0,
25
- :pattern001 => 1,
26
- :pattern010 => 2,
27
- :pattern011 => 3,
28
- :pattern100 => 4,
29
- :pattern101 => 5,
30
- :pattern110 => 6,
31
- :pattern111 => 7
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
- Proc.new { |i,j| (i + j) % 2 == 0 },
36
- Proc.new { |i,j| i % 2 == 0 },
37
- Proc.new { |i,j| j % 3 == 0 },
38
- Proc.new { |i,j| (i + j) % 3 == 0 },
39
- Proc.new { |i,j| ((i / 2).floor + (j / 3).floor) % 2 == 0 },
40
- Proc.new { |i,j| (i * j) % 2 + (i * j) % 3 == 0 },
41
- Proc.new { |i,j| ((i * j) % 2 + (i * j) % 3) % 2 == 0 },
42
- Proc.new { |i,j| ((i * j) % 3 + (i + j) % 2) % 2 == 0 },
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
- # Each array contains levels max chars from level 1 to level 40
53
- QRMAXDIGITS = {
54
- l: {
55
- mode_number: [
56
- 41, 77, 127, 187, 255, 322, 370, 461, 552, 652, 772,
57
- 883, 1022, 1101, 1250, 1408, 1548, 1725, 1903, 2061,
58
- 2232, 2409, 2620, 2812, 3057, 3283, 3514, 3669, 3909, 4158,
59
- 4417, 4686, 4965, 5253, 5529, 5836, 6153, 6479, 6743, 7089
60
- ],
61
- mode_alpha_numk: [
62
- 25, 47, 77, 114, 154, 195, 224, 279, 335, 395,
63
- 468, 535, 619, 667, 758, 854, 938, 1046, 1153, 1249,
64
- 1352, 1460, 1588, 1704, 1853, 1990, 2132, 2223, 2369, 2520,
65
- 2677, 2840, 3009, 3183, 3351, 3537, 3729, 3927, 4087, 4296
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
- # # string - the string you wish to encode
157
- # # size - the size of the qrcode (default 4)
158
- # # level - the error correction level, can be:
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 - the mode of the qrcode (defaults to alphanumeric or byte_8bit, depending on the input data):
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
- def initialize( string, *args )
173
- if !string.is_a? String
174
- raise QRCodeArgumentError, "The passed data is #{string.class}, not String"
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
- options = extract_options!(args)
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
- @data = string
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 > QRUtil.max_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
- @error_correct_level = QRERRORCORRECTLEVEL[level]
205
- @version = size
206
- @module_count = @version * 4 + QRPOSITIONPATTERNLENGTH
207
- @modules = Array.new( @module_count )
208
- @data_list =
209
- case mode
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?( row, col )
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
- # +:true+ and +:false+ which are there for you to choose
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( *args )
259
- options = extract_options!(args)
260
- dark = options[:dark] || options[:true] || 'x'
261
- light = options[:light] || options[:false] || ' '
262
- quiet_zone_size = options[:quiet_zone_size] || 0
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( false, get_best_mask_pattern )
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( test, mask_pattern ) #:nodoc:
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( @data_cache, mask_pattern )
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 if !(row + r).between?(0, @module_count - 1)
272
+ next unless (row + r).between?(0, @module_count - 1)
348
273
 
349
274
  (-1..7).each do |c|
350
- next if !(col + c).between?(0, @module_count - 1)
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
- ( 0...8 ).each do |i|
368
- make_impl( true, i )
369
- lost_point = QRUtil.get_lost_points(self.modules)
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
- ( 8...@module_count - 8 ).each do |i|
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
- ( -2..2 ).each do |r|
395
- ( -2..2 ).each do |c|
396
- is_part_of_pattern = (r.abs == 2 || c.abs == 2 || ( r == 0 && c == 0 ))
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
- ( 0...18 ).each do |i|
409
- mod = ( !test && ( (bits >> i) & 1) == 1 )
410
- @modules[ (i / 3).floor ][ i % 3 + @module_count - 8 - 3 ] = mod
411
- @modules[ i % 3 + @module_count - 8 - 3 ][ (i / 3).floor ] = mod
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 && ( (bits >> i) & 1) == 1)
341
+ mod = (!test && ((bits >> i) & 1) == 1)
422
342
 
423
343
  # vertical
424
- if i < 6
425
- row = i
344
+ row = if i < 6
345
+ i
426
346
  elsif i < 8
427
- row = i + 1
347
+ i + 1
428
348
  else
429
- row = @module_count - 15 + i
349
+ @module_count - 15 + i
430
350
  end
431
351
  @modules[row][8] = mod
432
352
 
433
353
  # horizontal
434
- if i < 8
435
- col = @module_count - i - 1
354
+ col = if i < 8
355
+ @module_count - i - 1
436
356
  elsif i < 9
437
- col = 15 - i - 1 + 1
357
+ 15 - i - 1 + 1
438
358
  else
439
- col = 15 - i - 1
359
+ 15 - i - 1
440
360
  end
441
361
  @modules[8][col] = mod
442
362
  end
443
363
 
444
364
  # fixed module
445
- @modules[ @module_count - 8 ][8] = !test
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
- ( @module_count - 1 ).step( 1, -2 ) do |col|
456
- col = col - 1 if col <= 6
374
+ (@module_count - 1).step(1, -2) do |col|
375
+ col -= 1 if col <= 6
457
376
 
458
- while true do
459
- ( 0...2 ).each do |c|
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 = (( QRUtil.rszf(data[byte_index], bit_index) & 1) == 1 )
382
+ dark = ((QRUtil.rszf(data[byte_index], bit_index) & 1) == 1)
465
383
  end
466
- mask = QRUtil.get_mask( mask_pattern, row, col - c )
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 smallest_size_for(string, max_size_array) #:nodoc:
490
- l = string.bytesize
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
- def extract_options!(arr) #:nodoc:
497
- arr.last.is_a?(::Hash) ? arr.pop : {}
498
- end
410
+ max_size_bits = QRMAXBITS[error_correction_level][version - 1]
499
411
 
500
- def QRCode.count_max_data_bits(rs_blocks)
501
- max_data_bytes = rs_blocks.reduce(0) do |sum, rs_block|
502
- sum + rs_block.data_count
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
- return max_data_bytes * 8
416
+ minimum_version(limit: limit, version: version + 1)
506
417
  end
507
418
 
508
- def QRCode.create_data(version, error_correct_level, data_list) #:nodoc:
509
- rs_blocks = QRRSBlock.get_rs_blocks(version, error_correct_level)
510
- max_data_bits = QRCode.count_max_data_bits(rs_blocks)
511
- buffer = QRBitBuffer.new(version)
419
+ def extract_options!(arr) #:nodoc:
420
+ arr.last.is_a?(::Hash) ? arr.pop : {}
421
+ end
512
422
 
513
- data_list.write(buffer)
514
- buffer.end_of_message(max_data_bits)
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
- if buffer.get_length_in_bits > max_data_bits
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
- buffer.pad_until(max_data_bits)
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
- QRCode.create_bytes( buffer, rs_blocks )
523
- end
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
- def QRCode.create_bytes( buffer, rs_blocks ) #:nodoc:
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
- rs_blocks.each_with_index do |rs_block, r|
534
- dc_count = rs_block.data_count
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
- dcdata_block = Array.new(dc_count)
540
- dcdata_block.size.times do |i|
541
- dcdata_block[i] = 0xff & buffer.buffer[ i + offset ]
542
- end
543
- dcdata[r] = dcdata_block
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
- offset = offset + dc_count
546
- rs_poly = QRUtil.get_error_correct_polynomial( ec_count )
547
- raw_poly = QRPolynomial.new( dcdata[r], rs_poly.get_length - 1 )
548
- mod_poly = raw_poly.mod( rs_poly )
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
- ecdata_block = Array.new(rs_poly.get_length - 1)
551
- ecdata_block.size.times do |i|
552
- mod_index = i + mod_poly.get_length - ecdata_block.size
553
- ecdata_block[i] = mod_index >= 0 ? mod_poly.get( mod_index ) : 0
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
- total_code_count = rs_blocks.reduce(0) do |sum, rs_block|
559
- sum + rs_block.total_count
560
- end
481
+ total_code_count = rs_blocks.reduce(0) do |sum, rs_block|
482
+ sum + rs_block.total_count
483
+ end
561
484
 
562
- data = Array.new( total_code_count )
563
- index = 0
485
+ data = Array.new(total_code_count)
486
+ index = 0
564
487
 
565
- max_dc_count.times do |i|
566
- rs_blocks.size.times do |r|
567
- if i < dcdata[r].size
568
- data[index] = dcdata[r][i]
569
- index += 1
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
- max_ec_count.times do |i|
575
- rs_blocks.size.times do |r|
576
- if i < ecdata[r].size
577
- data[index] = ecdata[r][i]
578
- index += 1
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
- data
506
+ data
507
+ end
584
508
  end
585
509
  end
586
510
  end