Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ultraviolet
GitHub Repository: ultraviolet/bitaddress.org
Path: blob/master/src/qrcode.js
248 views
1
//---------------------------------------------------------------------
2
// QRCode for JavaScript
3
//
4
// Copyright (c) 2009 Kazuhiko Arase
5
//
6
// URL: http://www.d-project.com/
7
//
8
// Licensed under the MIT license:
9
// http://www.opensource.org/licenses/mit-license.php
10
//
11
// The word "QR Code" is registered trademark of
12
// DENSO WAVE INCORPORATED
13
// http://www.denso-wave.com/qrcode/faqpatent-e.html
14
//
15
//---------------------------------------------------------------------
16
17
(function () {
18
//---------------------------------------------------------------------
19
// QRCode
20
//---------------------------------------------------------------------
21
22
var QRCode = window.QRCode = function (typeNumber, errorCorrectLevel) {
23
this.typeNumber = typeNumber;
24
this.errorCorrectLevel = errorCorrectLevel;
25
this.modules = null;
26
this.moduleCount = 0;
27
this.dataCache = null;
28
this.dataList = new Array();
29
}
30
31
QRCode.prototype = {
32
33
addData: function (data) {
34
var newData = new QRCode.QR8bitByte(data);
35
this.dataList.push(newData);
36
this.dataCache = null;
37
},
38
39
isDark: function (row, col) {
40
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
41
throw new Error(row + "," + col);
42
}
43
return this.modules[row][col];
44
},
45
46
getModuleCount: function () {
47
return this.moduleCount;
48
},
49
50
make: function () {
51
this.makeImpl(false, this.getBestMaskPattern());
52
},
53
54
makeImpl: function (test, maskPattern) {
55
56
this.moduleCount = this.typeNumber * 4 + 17;
57
this.modules = new Array(this.moduleCount);
58
59
for (var row = 0; row < this.moduleCount; row++) {
60
61
this.modules[row] = new Array(this.moduleCount);
62
63
for (var col = 0; col < this.moduleCount; col++) {
64
this.modules[row][col] = null; //(col + row) % 3;
65
}
66
}
67
68
this.setupPositionProbePattern(0, 0);
69
this.setupPositionProbePattern(this.moduleCount - 7, 0);
70
this.setupPositionProbePattern(0, this.moduleCount - 7);
71
this.setupPositionAdjustPattern();
72
this.setupTimingPattern();
73
this.setupTypeInfo(test, maskPattern);
74
75
if (this.typeNumber >= 7) {
76
this.setupTypeNumber(test);
77
}
78
79
if (this.dataCache == null) {
80
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
81
}
82
83
this.mapData(this.dataCache, maskPattern);
84
},
85
86
setupPositionProbePattern: function (row, col) {
87
88
for (var r = -1; r <= 7; r++) {
89
90
if (row + r <= -1 || this.moduleCount <= row + r) continue;
91
92
for (var c = -1; c <= 7; c++) {
93
94
if (col + c <= -1 || this.moduleCount <= col + c) continue;
95
96
if ((0 <= r && r <= 6 && (c == 0 || c == 6))
97
|| (0 <= c && c <= 6 && (r == 0 || r == 6))
98
|| (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
99
this.modules[row + r][col + c] = true;
100
} else {
101
this.modules[row + r][col + c] = false;
102
}
103
}
104
}
105
},
106
107
getBestMaskPattern: function () {
108
109
var minLostPoint = 0;
110
var pattern = 0;
111
112
for (var i = 0; i < 8; i++) {
113
114
this.makeImpl(true, i);
115
116
var lostPoint = QRCode.Util.getLostPoint(this);
117
118
if (i == 0 || minLostPoint > lostPoint) {
119
minLostPoint = lostPoint;
120
pattern = i;
121
}
122
}
123
124
return pattern;
125
},
126
127
createMovieClip: function (target_mc, instance_name, depth) {
128
129
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
130
var cs = 1;
131
132
this.make();
133
134
for (var row = 0; row < this.modules.length; row++) {
135
136
var y = row * cs;
137
138
for (var col = 0; col < this.modules[row].length; col++) {
139
140
var x = col * cs;
141
var dark = this.modules[row][col];
142
143
if (dark) {
144
qr_mc.beginFill(0, 100);
145
qr_mc.moveTo(x, y);
146
qr_mc.lineTo(x + cs, y);
147
qr_mc.lineTo(x + cs, y + cs);
148
qr_mc.lineTo(x, y + cs);
149
qr_mc.endFill();
150
}
151
}
152
}
153
154
return qr_mc;
155
},
156
157
setupTimingPattern: function () {
158
159
for (var r = 8; r < this.moduleCount - 8; r++) {
160
if (this.modules[r][6] != null) {
161
continue;
162
}
163
this.modules[r][6] = (r % 2 == 0);
164
}
165
166
for (var c = 8; c < this.moduleCount - 8; c++) {
167
if (this.modules[6][c] != null) {
168
continue;
169
}
170
this.modules[6][c] = (c % 2 == 0);
171
}
172
},
173
174
setupPositionAdjustPattern: function () {
175
176
var pos = QRCode.Util.getPatternPosition(this.typeNumber);
177
178
for (var i = 0; i < pos.length; i++) {
179
180
for (var j = 0; j < pos.length; j++) {
181
182
var row = pos[i];
183
var col = pos[j];
184
185
if (this.modules[row][col] != null) {
186
continue;
187
}
188
189
for (var r = -2; r <= 2; r++) {
190
191
for (var c = -2; c <= 2; c++) {
192
193
if (r == -2 || r == 2 || c == -2 || c == 2
194
|| (r == 0 && c == 0)) {
195
this.modules[row + r][col + c] = true;
196
} else {
197
this.modules[row + r][col + c] = false;
198
}
199
}
200
}
201
}
202
}
203
},
204
205
setupTypeNumber: function (test) {
206
207
var bits = QRCode.Util.getBCHTypeNumber(this.typeNumber);
208
209
for (var i = 0; i < 18; i++) {
210
var mod = (!test && ((bits >> i) & 1) == 1);
211
this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
212
}
213
214
for (var i = 0; i < 18; i++) {
215
var mod = (!test && ((bits >> i) & 1) == 1);
216
this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
217
}
218
},
219
220
setupTypeInfo: function (test, maskPattern) {
221
222
var data = (this.errorCorrectLevel << 3) | maskPattern;
223
var bits = QRCode.Util.getBCHTypeInfo(data);
224
225
// vertical
226
for (var i = 0; i < 15; i++) {
227
228
var mod = (!test && ((bits >> i) & 1) == 1);
229
230
if (i < 6) {
231
this.modules[i][8] = mod;
232
} else if (i < 8) {
233
this.modules[i + 1][8] = mod;
234
} else {
235
this.modules[this.moduleCount - 15 + i][8] = mod;
236
}
237
}
238
239
// horizontal
240
for (var i = 0; i < 15; i++) {
241
242
var mod = (!test && ((bits >> i) & 1) == 1);
243
244
if (i < 8) {
245
this.modules[8][this.moduleCount - i - 1] = mod;
246
} else if (i < 9) {
247
this.modules[8][15 - i - 1 + 1] = mod;
248
} else {
249
this.modules[8][15 - i - 1] = mod;
250
}
251
}
252
253
// fixed module
254
this.modules[this.moduleCount - 8][8] = (!test);
255
256
},
257
258
mapData: function (data, maskPattern) {
259
260
var inc = -1;
261
var row = this.moduleCount - 1;
262
var bitIndex = 7;
263
var byteIndex = 0;
264
265
for (var col = this.moduleCount - 1; col > 0; col -= 2) {
266
267
if (col == 6) col--;
268
269
while (true) {
270
271
for (var c = 0; c < 2; c++) {
272
273
if (this.modules[row][col - c] == null) {
274
275
var dark = false;
276
277
if (byteIndex < data.length) {
278
dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
279
}
280
281
var mask = QRCode.Util.getMask(maskPattern, row, col - c);
282
283
if (mask) {
284
dark = !dark;
285
}
286
287
this.modules[row][col - c] = dark;
288
bitIndex--;
289
290
if (bitIndex == -1) {
291
byteIndex++;
292
bitIndex = 7;
293
}
294
}
295
}
296
297
row += inc;
298
299
if (row < 0 || this.moduleCount <= row) {
300
row -= inc;
301
inc = -inc;
302
break;
303
}
304
}
305
}
306
307
}
308
309
};
310
311
QRCode.PAD0 = 0xEC;
312
QRCode.PAD1 = 0x11;
313
314
QRCode.createData = function (typeNumber, errorCorrectLevel, dataList) {
315
316
var rsBlocks = QRCode.RSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
317
318
var buffer = new QRCode.BitBuffer();
319
320
for (var i = 0; i < dataList.length; i++) {
321
var data = dataList[i];
322
buffer.put(data.mode, 4);
323
buffer.put(data.getLength(), QRCode.Util.getLengthInBits(data.mode, typeNumber));
324
data.write(buffer);
325
}
326
327
// calc num max data.
328
var totalDataCount = 0;
329
for (var i = 0; i < rsBlocks.length; i++) {
330
totalDataCount += rsBlocks[i].dataCount;
331
}
332
333
if (buffer.getLengthInBits() > totalDataCount * 8) {
334
throw new Error("code length overflow. ("
335
+ buffer.getLengthInBits()
336
+ ">"
337
+ totalDataCount * 8
338
+ ")");
339
}
340
341
// end code
342
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
343
buffer.put(0, 4);
344
}
345
346
// padding
347
while (buffer.getLengthInBits() % 8 != 0) {
348
buffer.putBit(false);
349
}
350
351
// padding
352
while (true) {
353
354
if (buffer.getLengthInBits() >= totalDataCount * 8) {
355
break;
356
}
357
buffer.put(QRCode.PAD0, 8);
358
359
if (buffer.getLengthInBits() >= totalDataCount * 8) {
360
break;
361
}
362
buffer.put(QRCode.PAD1, 8);
363
}
364
365
return QRCode.createBytes(buffer, rsBlocks);
366
};
367
368
QRCode.createBytes = function (buffer, rsBlocks) {
369
370
var offset = 0;
371
372
var maxDcCount = 0;
373
var maxEcCount = 0;
374
375
var dcdata = new Array(rsBlocks.length);
376
var ecdata = new Array(rsBlocks.length);
377
378
for (var r = 0; r < rsBlocks.length; r++) {
379
380
var dcCount = rsBlocks[r].dataCount;
381
var ecCount = rsBlocks[r].totalCount - dcCount;
382
383
maxDcCount = Math.max(maxDcCount, dcCount);
384
maxEcCount = Math.max(maxEcCount, ecCount);
385
386
dcdata[r] = new Array(dcCount);
387
388
for (var i = 0; i < dcdata[r].length; i++) {
389
dcdata[r][i] = 0xff & buffer.buffer[i + offset];
390
}
391
offset += dcCount;
392
393
var rsPoly = QRCode.Util.getErrorCorrectPolynomial(ecCount);
394
var rawPoly = new QRCode.Polynomial(dcdata[r], rsPoly.getLength() - 1);
395
396
var modPoly = rawPoly.mod(rsPoly);
397
ecdata[r] = new Array(rsPoly.getLength() - 1);
398
for (var i = 0; i < ecdata[r].length; i++) {
399
var modIndex = i + modPoly.getLength() - ecdata[r].length;
400
ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
401
}
402
403
}
404
405
var totalCodeCount = 0;
406
for (var i = 0; i < rsBlocks.length; i++) {
407
totalCodeCount += rsBlocks[i].totalCount;
408
}
409
410
var data = new Array(totalCodeCount);
411
var index = 0;
412
413
for (var i = 0; i < maxDcCount; i++) {
414
for (var r = 0; r < rsBlocks.length; r++) {
415
if (i < dcdata[r].length) {
416
data[index++] = dcdata[r][i];
417
}
418
}
419
}
420
421
for (var i = 0; i < maxEcCount; i++) {
422
for (var r = 0; r < rsBlocks.length; r++) {
423
if (i < ecdata[r].length) {
424
data[index++] = ecdata[r][i];
425
}
426
}
427
}
428
429
return data;
430
431
};
432
433
//---------------------------------------------------------------------
434
// QR8bitByte
435
//---------------------------------------------------------------------
436
QRCode.QR8bitByte = function (data) {
437
this.mode = QRCode.Mode.MODE_8BIT_BYTE;
438
this.data = data;
439
}
440
441
QRCode.QR8bitByte.prototype = {
442
getLength: function (buffer) {
443
return this.data.length;
444
},
445
446
write: function (buffer) {
447
for (var i = 0; i < this.data.length; i++) {
448
// not JIS ...
449
buffer.put(this.data.charCodeAt(i), 8);
450
}
451
}
452
};
453
454
455
//---------------------------------------------------------------------
456
// QRMode
457
//---------------------------------------------------------------------
458
QRCode.Mode = {
459
MODE_NUMBER: 1 << 0,
460
MODE_ALPHA_NUM: 1 << 1,
461
MODE_8BIT_BYTE: 1 << 2,
462
MODE_KANJI: 1 << 3
463
};
464
465
//---------------------------------------------------------------------
466
// QRErrorCorrectLevel
467
//---------------------------------------------------------------------
468
QRCode.ErrorCorrectLevel = {
469
L: 1,
470
M: 0,
471
Q: 3,
472
H: 2
473
};
474
475
476
//---------------------------------------------------------------------
477
// QRMaskPattern
478
//---------------------------------------------------------------------
479
QRCode.MaskPattern = {
480
PATTERN000: 0,
481
PATTERN001: 1,
482
PATTERN010: 2,
483
PATTERN011: 3,
484
PATTERN100: 4,
485
PATTERN101: 5,
486
PATTERN110: 6,
487
PATTERN111: 7
488
};
489
490
//---------------------------------------------------------------------
491
// QRUtil
492
//---------------------------------------------------------------------
493
494
QRCode.Util = {
495
496
PATTERN_POSITION_TABLE: [
497
[],
498
[6, 18],
499
[6, 22],
500
[6, 26],
501
[6, 30],
502
[6, 34],
503
[6, 22, 38],
504
[6, 24, 42],
505
[6, 26, 46],
506
[6, 28, 50],
507
[6, 30, 54],
508
[6, 32, 58],
509
[6, 34, 62],
510
[6, 26, 46, 66],
511
[6, 26, 48, 70],
512
[6, 26, 50, 74],
513
[6, 30, 54, 78],
514
[6, 30, 56, 82],
515
[6, 30, 58, 86],
516
[6, 34, 62, 90],
517
[6, 28, 50, 72, 94],
518
[6, 26, 50, 74, 98],
519
[6, 30, 54, 78, 102],
520
[6, 28, 54, 80, 106],
521
[6, 32, 58, 84, 110],
522
[6, 30, 58, 86, 114],
523
[6, 34, 62, 90, 118],
524
[6, 26, 50, 74, 98, 122],
525
[6, 30, 54, 78, 102, 126],
526
[6, 26, 52, 78, 104, 130],
527
[6, 30, 56, 82, 108, 134],
528
[6, 34, 60, 86, 112, 138],
529
[6, 30, 58, 86, 114, 142],
530
[6, 34, 62, 90, 118, 146],
531
[6, 30, 54, 78, 102, 126, 150],
532
[6, 24, 50, 76, 102, 128, 154],
533
[6, 28, 54, 80, 106, 132, 158],
534
[6, 32, 58, 84, 110, 136, 162],
535
[6, 26, 54, 82, 110, 138, 166],
536
[6, 30, 58, 86, 114, 142, 170]
537
],
538
539
G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
540
G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
541
G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
542
543
getBCHTypeInfo: function (data) {
544
var d = data << 10;
545
while (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G15) >= 0) {
546
d ^= (QRCode.Util.G15 << (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G15)));
547
}
548
return ((data << 10) | d) ^ QRCode.Util.G15_MASK;
549
},
550
551
getBCHTypeNumber: function (data) {
552
var d = data << 12;
553
while (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G18) >= 0) {
554
d ^= (QRCode.Util.G18 << (QRCode.Util.getBCHDigit(d) - QRCode.Util.getBCHDigit(QRCode.Util.G18)));
555
}
556
return (data << 12) | d;
557
},
558
559
getBCHDigit: function (data) {
560
561
var digit = 0;
562
563
while (data != 0) {
564
digit++;
565
data >>>= 1;
566
}
567
568
return digit;
569
},
570
571
getPatternPosition: function (typeNumber) {
572
return QRCode.Util.PATTERN_POSITION_TABLE[typeNumber - 1];
573
},
574
575
getMask: function (maskPattern, i, j) {
576
577
switch (maskPattern) {
578
579
case QRCode.MaskPattern.PATTERN000: return (i + j) % 2 == 0;
580
case QRCode.MaskPattern.PATTERN001: return i % 2 == 0;
581
case QRCode.MaskPattern.PATTERN010: return j % 3 == 0;
582
case QRCode.MaskPattern.PATTERN011: return (i + j) % 3 == 0;
583
case QRCode.MaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
584
case QRCode.MaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0;
585
case QRCode.MaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
586
case QRCode.MaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
587
588
default:
589
throw new Error("bad maskPattern:" + maskPattern);
590
}
591
},
592
593
getErrorCorrectPolynomial: function (errorCorrectLength) {
594
595
var a = new QRCode.Polynomial([1], 0);
596
597
for (var i = 0; i < errorCorrectLength; i++) {
598
a = a.multiply(new QRCode.Polynomial([1, QRCode.Math.gexp(i)], 0));
599
}
600
601
return a;
602
},
603
604
getLengthInBits: function (mode, type) {
605
606
if (1 <= type && type < 10) {
607
608
// 1 - 9
609
610
switch (mode) {
611
case QRCode.Mode.MODE_NUMBER: return 10;
612
case QRCode.Mode.MODE_ALPHA_NUM: return 9;
613
case QRCode.Mode.MODE_8BIT_BYTE: return 8;
614
case QRCode.Mode.MODE_KANJI: return 8;
615
default:
616
throw new Error("mode:" + mode);
617
}
618
619
} else if (type < 27) {
620
621
// 10 - 26
622
623
switch (mode) {
624
case QRCode.Mode.MODE_NUMBER: return 12;
625
case QRCode.Mode.MODE_ALPHA_NUM: return 11;
626
case QRCode.Mode.MODE_8BIT_BYTE: return 16;
627
case QRCode.Mode.MODE_KANJI: return 10;
628
default:
629
throw new Error("mode:" + mode);
630
}
631
632
} else if (type < 41) {
633
634
// 27 - 40
635
636
switch (mode) {
637
case QRCode.Mode.MODE_NUMBER: return 14;
638
case QRCode.Mode.MODE_ALPHA_NUM: return 13;
639
case QRCode.Mode.MODE_8BIT_BYTE: return 16;
640
case QRCode.Mode.MODE_KANJI: return 12;
641
default:
642
throw new Error("mode:" + mode);
643
}
644
645
} else {
646
throw new Error("type:" + type);
647
}
648
},
649
650
getLostPoint: function (qrCode) {
651
652
var moduleCount = qrCode.getModuleCount();
653
654
var lostPoint = 0;
655
656
// LEVEL1
657
658
for (var row = 0; row < moduleCount; row++) {
659
660
for (var col = 0; col < moduleCount; col++) {
661
662
var sameCount = 0;
663
var dark = qrCode.isDark(row, col);
664
665
for (var r = -1; r <= 1; r++) {
666
667
if (row + r < 0 || moduleCount <= row + r) {
668
continue;
669
}
670
671
for (var c = -1; c <= 1; c++) {
672
673
if (col + c < 0 || moduleCount <= col + c) {
674
continue;
675
}
676
677
if (r == 0 && c == 0) {
678
continue;
679
}
680
681
if (dark == qrCode.isDark(row + r, col + c)) {
682
sameCount++;
683
}
684
}
685
}
686
687
if (sameCount > 5) {
688
lostPoint += (3 + sameCount - 5);
689
}
690
}
691
}
692
693
// LEVEL2
694
695
for (var row = 0; row < moduleCount - 1; row++) {
696
for (var col = 0; col < moduleCount - 1; col++) {
697
var count = 0;
698
if (qrCode.isDark(row, col)) count++;
699
if (qrCode.isDark(row + 1, col)) count++;
700
if (qrCode.isDark(row, col + 1)) count++;
701
if (qrCode.isDark(row + 1, col + 1)) count++;
702
if (count == 0 || count == 4) {
703
lostPoint += 3;
704
}
705
}
706
}
707
708
// LEVEL3
709
710
for (var row = 0; row < moduleCount; row++) {
711
for (var col = 0; col < moduleCount - 6; col++) {
712
if (qrCode.isDark(row, col)
713
&& !qrCode.isDark(row, col + 1)
714
&& qrCode.isDark(row, col + 2)
715
&& qrCode.isDark(row, col + 3)
716
&& qrCode.isDark(row, col + 4)
717
&& !qrCode.isDark(row, col + 5)
718
&& qrCode.isDark(row, col + 6)) {
719
lostPoint += 40;
720
}
721
}
722
}
723
724
for (var col = 0; col < moduleCount; col++) {
725
for (var row = 0; row < moduleCount - 6; row++) {
726
if (qrCode.isDark(row, col)
727
&& !qrCode.isDark(row + 1, col)
728
&& qrCode.isDark(row + 2, col)
729
&& qrCode.isDark(row + 3, col)
730
&& qrCode.isDark(row + 4, col)
731
&& !qrCode.isDark(row + 5, col)
732
&& qrCode.isDark(row + 6, col)) {
733
lostPoint += 40;
734
}
735
}
736
}
737
738
// LEVEL4
739
740
var darkCount = 0;
741
742
for (var col = 0; col < moduleCount; col++) {
743
for (var row = 0; row < moduleCount; row++) {
744
if (qrCode.isDark(row, col)) {
745
darkCount++;
746
}
747
}
748
}
749
750
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
751
lostPoint += ratio * 10;
752
753
return lostPoint;
754
}
755
756
};
757
758
759
//---------------------------------------------------------------------
760
// QRMath
761
//---------------------------------------------------------------------
762
763
QRCode.Math = {
764
765
glog: function (n) {
766
767
if (n < 1) {
768
throw new Error("glog(" + n + ")");
769
}
770
771
return QRCode.Math.LOG_TABLE[n];
772
},
773
774
gexp: function (n) {
775
776
while (n < 0) {
777
n += 255;
778
}
779
780
while (n >= 256) {
781
n -= 255;
782
}
783
784
return QRCode.Math.EXP_TABLE[n];
785
},
786
787
EXP_TABLE: new Array(256),
788
789
LOG_TABLE: new Array(256)
790
791
};
792
793
for (var i = 0; i < 8; i++) {
794
QRCode.Math.EXP_TABLE[i] = 1 << i;
795
}
796
for (var i = 8; i < 256; i++) {
797
QRCode.Math.EXP_TABLE[i] = QRCode.Math.EXP_TABLE[i - 4]
798
^ QRCode.Math.EXP_TABLE[i - 5]
799
^ QRCode.Math.EXP_TABLE[i - 6]
800
^ QRCode.Math.EXP_TABLE[i - 8];
801
}
802
for (var i = 0; i < 255; i++) {
803
QRCode.Math.LOG_TABLE[QRCode.Math.EXP_TABLE[i]] = i;
804
}
805
806
//---------------------------------------------------------------------
807
// QRPolynomial
808
//---------------------------------------------------------------------
809
810
QRCode.Polynomial = function (num, shift) {
811
812
if (num.length == undefined) {
813
throw new Error(num.length + "/" + shift);
814
}
815
816
var offset = 0;
817
818
while (offset < num.length && num[offset] == 0) {
819
offset++;
820
}
821
822
this.num = new Array(num.length - offset + shift);
823
for (var i = 0; i < num.length - offset; i++) {
824
this.num[i] = num[i + offset];
825
}
826
}
827
828
QRCode.Polynomial.prototype = {
829
830
get: function (index) {
831
return this.num[index];
832
},
833
834
getLength: function () {
835
return this.num.length;
836
},
837
838
multiply: function (e) {
839
840
var num = new Array(this.getLength() + e.getLength() - 1);
841
842
for (var i = 0; i < this.getLength(); i++) {
843
for (var j = 0; j < e.getLength(); j++) {
844
num[i + j] ^= QRCode.Math.gexp(QRCode.Math.glog(this.get(i)) + QRCode.Math.glog(e.get(j)));
845
}
846
}
847
848
return new QRCode.Polynomial(num, 0);
849
},
850
851
mod: function (e) {
852
853
if (this.getLength() - e.getLength() < 0) {
854
return this;
855
}
856
857
var ratio = QRCode.Math.glog(this.get(0)) - QRCode.Math.glog(e.get(0));
858
859
var num = new Array(this.getLength());
860
861
for (var i = 0; i < this.getLength(); i++) {
862
num[i] = this.get(i);
863
}
864
865
for (var i = 0; i < e.getLength(); i++) {
866
num[i] ^= QRCode.Math.gexp(QRCode.Math.glog(e.get(i)) + ratio);
867
}
868
869
// recursive call
870
return new QRCode.Polynomial(num, 0).mod(e);
871
}
872
};
873
874
//---------------------------------------------------------------------
875
// QRRSBlock
876
//---------------------------------------------------------------------
877
878
QRCode.RSBlock = function (totalCount, dataCount) {
879
this.totalCount = totalCount;
880
this.dataCount = dataCount;
881
}
882
883
QRCode.RSBlock.RS_BLOCK_TABLE = [
884
885
// L
886
// M
887
// Q
888
// H
889
890
// 1
891
[1, 26, 19],
892
[1, 26, 16],
893
[1, 26, 13],
894
[1, 26, 9],
895
896
// 2
897
[1, 44, 34],
898
[1, 44, 28],
899
[1, 44, 22],
900
[1, 44, 16],
901
902
// 3
903
[1, 70, 55],
904
[1, 70, 44],
905
[2, 35, 17],
906
[2, 35, 13],
907
908
// 4
909
[1, 100, 80],
910
[2, 50, 32],
911
[2, 50, 24],
912
[4, 25, 9],
913
914
// 5
915
[1, 134, 108],
916
[2, 67, 43],
917
[2, 33, 15, 2, 34, 16],
918
[2, 33, 11, 2, 34, 12],
919
920
// 6
921
[2, 86, 68],
922
[4, 43, 27],
923
[4, 43, 19],
924
[4, 43, 15],
925
926
// 7
927
[2, 98, 78],
928
[4, 49, 31],
929
[2, 32, 14, 4, 33, 15],
930
[4, 39, 13, 1, 40, 14],
931
932
// 8
933
[2, 121, 97],
934
[2, 60, 38, 2, 61, 39],
935
[4, 40, 18, 2, 41, 19],
936
[4, 40, 14, 2, 41, 15],
937
938
// 9
939
[2, 146, 116],
940
[3, 58, 36, 2, 59, 37],
941
[4, 36, 16, 4, 37, 17],
942
[4, 36, 12, 4, 37, 13],
943
944
// 10
945
[2, 86, 68, 2, 87, 69],
946
[4, 69, 43, 1, 70, 44],
947
[6, 43, 19, 2, 44, 20],
948
[6, 43, 15, 2, 44, 16]
949
950
];
951
952
QRCode.RSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
953
954
var rsBlock = QRCode.RSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
955
956
if (rsBlock == undefined) {
957
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
958
}
959
960
var length = rsBlock.length / 3;
961
962
var list = new Array();
963
964
for (var i = 0; i < length; i++) {
965
966
var count = rsBlock[i * 3 + 0];
967
var totalCount = rsBlock[i * 3 + 1];
968
var dataCount = rsBlock[i * 3 + 2];
969
970
for (var j = 0; j < count; j++) {
971
list.push(new QRCode.RSBlock(totalCount, dataCount));
972
}
973
}
974
975
return list;
976
};
977
978
QRCode.RSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) {
979
980
switch (errorCorrectLevel) {
981
case QRCode.ErrorCorrectLevel.L:
982
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
983
case QRCode.ErrorCorrectLevel.M:
984
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
985
case QRCode.ErrorCorrectLevel.Q:
986
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
987
case QRCode.ErrorCorrectLevel.H:
988
return QRCode.RSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
989
default:
990
return undefined;
991
}
992
};
993
994
//---------------------------------------------------------------------
995
// QRBitBuffer
996
//---------------------------------------------------------------------
997
998
QRCode.BitBuffer = function () {
999
this.buffer = new Array();
1000
this.length = 0;
1001
}
1002
1003
QRCode.BitBuffer.prototype = {
1004
1005
get: function (index) {
1006
var bufIndex = Math.floor(index / 8);
1007
return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
1008
},
1009
1010
put: function (num, length) {
1011
for (var i = 0; i < length; i++) {
1012
this.putBit(((num >>> (length - i - 1)) & 1) == 1);
1013
}
1014
},
1015
1016
getLengthInBits: function () {
1017
return this.length;
1018
},
1019
1020
putBit: function (bit) {
1021
1022
var bufIndex = Math.floor(this.length / 8);
1023
if (this.buffer.length <= bufIndex) {
1024
this.buffer.push(0);
1025
}
1026
1027
if (bit) {
1028
this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
1029
}
1030
1031
this.length++;
1032
}
1033
};
1034
})();
1035