blob: 099993fb63aca116b42ad6b83b10c3926cec1fcc [file] [log] [blame]
guangchao.xu070005a2020-12-07 09:56:40 +08001//---------------------------------------------------------------------
2// github https://github.com/Sansnn/uQRCode
3//---------------------------------------------------------------------
4
5let uQRCode = {};
6
7(function() {
8 //---------------------------------------------------------------------
9 // QRCode for JavaScript
10 //
11 // Copyright (c) 2009 Kazuhiko Arase
12 //
13 // URL: http://www.d-project.com/
14 //
15 // Licensed under the MIT license:
16 // http://www.opensource.org/licenses/mit-license.php
17 //
18 // The word "QR Code" is registered trademark of
19 // DENSO WAVE INCORPORATED
20 // http://www.denso-wave.com/qrcode/faqpatent-e.html
21 //
22 //---------------------------------------------------------------------
23
24 //---------------------------------------------------------------------
25 // QR8bitByte
26 //---------------------------------------------------------------------
27
28 function QR8bitByte(data) {
29 this.mode = QRMode.MODE_8BIT_BYTE;
30 this.data = data;
31 }
32
33 QR8bitByte.prototype = {
34
35 getLength: function(buffer) {
36 return this.data.length;
37 },
38
39 write: function(buffer) {
40 for (var i = 0; i < this.data.length; i++) {
41 // not JIS ...
42 buffer.put(this.data.charCodeAt(i), 8);
43 }
44 }
45 };
46
47 //---------------------------------------------------------------------
48 // QRCode
49 //---------------------------------------------------------------------
50
51 function QRCode(typeNumber, errorCorrectLevel) {
52 this.typeNumber = typeNumber;
53 this.errorCorrectLevel = errorCorrectLevel;
54 this.modules = null;
55 this.moduleCount = 0;
56 this.dataCache = null;
57 this.dataList = new Array();
58 }
59
60 QRCode.prototype = {
61
62 addData: function(data) {
63 var newData = new QR8bitByte(data);
64 this.dataList.push(newData);
65 this.dataCache = null;
66 },
67
68 isDark: function(row, col) {
69 if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
70 throw new Error(row + "," + col);
71 }
72 return this.modules[row][col];
73 },
74
75 getModuleCount: function() {
76 return this.moduleCount;
77 },
78
79 make: function() {
80 // Calculate automatically typeNumber if provided is < 1
81 if (this.typeNumber < 1) {
82 var typeNumber = 1;
83 for (typeNumber = 1; typeNumber < 40; typeNumber++) {
84 var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel);
85
86 var buffer = new QRBitBuffer();
87 var totalDataCount = 0;
88 for (var i = 0; i < rsBlocks.length; i++) {
89 totalDataCount += rsBlocks[i].dataCount;
90 }
91
92 for (var i = 0; i < this.dataList.length; i++) {
93 var data = this.dataList[i];
94 buffer.put(data.mode, 4);
95 buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
96 data.write(buffer);
97 }
98 if (buffer.getLengthInBits() <= totalDataCount * 8)
99 break;
100 }
101 this.typeNumber = typeNumber;
102 }
103 this.makeImpl(false, this.getBestMaskPattern());
104 },
105
106 makeImpl: function(test, maskPattern) {
107
108 this.moduleCount = this.typeNumber * 4 + 17;
109 this.modules = new Array(this.moduleCount);
110
111 for (var row = 0; row < this.moduleCount; row++) {
112
113 this.modules[row] = new Array(this.moduleCount);
114
115 for (var col = 0; col < this.moduleCount; col++) {
116 this.modules[row][col] = null; //(col + row) % 3;
117 }
118 }
119
120 this.setupPositionProbePattern(0, 0);
121 this.setupPositionProbePattern(this.moduleCount - 7, 0);
122 this.setupPositionProbePattern(0, this.moduleCount - 7);
123 this.setupPositionAdjustPattern();
124 this.setupTimingPattern();
125 this.setupTypeInfo(test, maskPattern);
126
127 if (this.typeNumber >= 7) {
128 this.setupTypeNumber(test);
129 }
130
131 if (this.dataCache == null) {
132 this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
133 }
134
135 this.mapData(this.dataCache, maskPattern);
136 },
137
138 setupPositionProbePattern: function(row, col) {
139
140 for (var r = -1; r <= 7; r++) {
141
142 if (row + r <= -1 || this.moduleCount <= row + r) continue;
143
144 for (var c = -1; c <= 7; c++) {
145
146 if (col + c <= -1 || this.moduleCount <= col + c) continue;
147
148 if ((0 <= r && r <= 6 && (c == 0 || c == 6)) ||
149 (0 <= c && c <= 6 && (r == 0 || r == 6)) ||
150 (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
151 this.modules[row + r][col + c] = true;
152 } else {
153 this.modules[row + r][col + c] = false;
154 }
155 }
156 }
157 },
158
159 getBestMaskPattern: function() {
160
161 var minLostPoint = 0;
162 var pattern = 0;
163
164 for (var i = 0; i < 8; i++) {
165
166 this.makeImpl(true, i);
167
168 var lostPoint = QRUtil.getLostPoint(this);
169
170 if (i == 0 || minLostPoint > lostPoint) {
171 minLostPoint = lostPoint;
172 pattern = i;
173 }
174 }
175
176 return pattern;
177 },
178
179 createMovieClip: function(target_mc, instance_name, depth) {
180
181 var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
182 var cs = 1;
183
184 this.make();
185
186 for (var row = 0; row < this.modules.length; row++) {
187
188 var y = row * cs;
189
190 for (var col = 0; col < this.modules[row].length; col++) {
191
192 var x = col * cs;
193 var dark = this.modules[row][col];
194
195 if (dark) {
196 qr_mc.beginFill(0, 100);
197 qr_mc.moveTo(x, y);
198 qr_mc.lineTo(x + cs, y);
199 qr_mc.lineTo(x + cs, y + cs);
200 qr_mc.lineTo(x, y + cs);
201 qr_mc.endFill();
202 }
203 }
204 }
205
206 return qr_mc;
207 },
208
209 setupTimingPattern: function() {
210
211 for (var r = 8; r < this.moduleCount - 8; r++) {
212 if (this.modules[r][6] != null) {
213 continue;
214 }
215 this.modules[r][6] = (r % 2 == 0);
216 }
217
218 for (var c = 8; c < this.moduleCount - 8; c++) {
219 if (this.modules[6][c] != null) {
220 continue;
221 }
222 this.modules[6][c] = (c % 2 == 0);
223 }
224 },
225
226 setupPositionAdjustPattern: function() {
227
228 var pos = QRUtil.getPatternPosition(this.typeNumber);
229
230 for (var i = 0; i < pos.length; i++) {
231
232 for (var j = 0; j < pos.length; j++) {
233
234 var row = pos[i];
235 var col = pos[j];
236
237 if (this.modules[row][col] != null) {
238 continue;
239 }
240
241 for (var r = -2; r <= 2; r++) {
242
243 for (var c = -2; c <= 2; c++) {
244
245 if (r == -2 || r == 2 || c == -2 || c == 2 ||
246 (r == 0 && c == 0)) {
247 this.modules[row + r][col + c] = true;
248 } else {
249 this.modules[row + r][col + c] = false;
250 }
251 }
252 }
253 }
254 }
255 },
256
257 setupTypeNumber: function(test) {
258
259 var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
260
261 for (var i = 0; i < 18; i++) {
262 var mod = (!test && ((bits >> i) & 1) == 1);
263 this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
264 }
265
266 for (var i = 0; i < 18; i++) {
267 var mod = (!test && ((bits >> i) & 1) == 1);
268 this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
269 }
270 },
271
272 setupTypeInfo: function(test, maskPattern) {
273
274 var data = (this.errorCorrectLevel << 3) | maskPattern;
275 var bits = QRUtil.getBCHTypeInfo(data);
276
277 // vertical
278 for (var i = 0; i < 15; i++) {
279
280 var mod = (!test && ((bits >> i) & 1) == 1);
281
282 if (i < 6) {
283 this.modules[i][8] = mod;
284 } else if (i < 8) {
285 this.modules[i + 1][8] = mod;
286 } else {
287 this.modules[this.moduleCount - 15 + i][8] = mod;
288 }
289 }
290
291 // horizontal
292 for (var i = 0; i < 15; i++) {
293
294 var mod = (!test && ((bits >> i) & 1) == 1);
295
296 if (i < 8) {
297 this.modules[8][this.moduleCount - i - 1] = mod;
298 } else if (i < 9) {
299 this.modules[8][15 - i - 1 + 1] = mod;
300 } else {
301 this.modules[8][15 - i - 1] = mod;
302 }
303 }
304
305 // fixed module
306 this.modules[this.moduleCount - 8][8] = (!test);
307
308 },
309
310 mapData: function(data, maskPattern) {
311
312 var inc = -1;
313 var row = this.moduleCount - 1;
314 var bitIndex = 7;
315 var byteIndex = 0;
316
317 for (var col = this.moduleCount - 1; col > 0; col -= 2) {
318
319 if (col == 6) col--;
320
321 while (true) {
322
323 for (var c = 0; c < 2; c++) {
324
325 if (this.modules[row][col - c] == null) {
326
327 var dark = false;
328
329 if (byteIndex < data.length) {
330 dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
331 }
332
333 var mask = QRUtil.getMask(maskPattern, row, col - c);
334
335 if (mask) {
336 dark = !dark;
337 }
338
339 this.modules[row][col - c] = dark;
340 bitIndex--;
341
342 if (bitIndex == -1) {
343 byteIndex++;
344 bitIndex = 7;
345 }
346 }
347 }
348
349 row += inc;
350
351 if (row < 0 || this.moduleCount <= row) {
352 row -= inc;
353 inc = -inc;
354 break;
355 }
356 }
357 }
358
359 }
360
361 };
362
363 QRCode.PAD0 = 0xEC;
364 QRCode.PAD1 = 0x11;
365
366 QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) {
367
368 var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
369
370 var buffer = new QRBitBuffer();
371
372 for (var i = 0; i < dataList.length; i++) {
373 var data = dataList[i];
374 buffer.put(data.mode, 4);
375 buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
376 data.write(buffer);
377 }
378
379 // calc num max data.
380 var totalDataCount = 0;
381 for (var i = 0; i < rsBlocks.length; i++) {
382 totalDataCount += rsBlocks[i].dataCount;
383 }
384
385 if (buffer.getLengthInBits() > totalDataCount * 8) {
386 throw new Error("code length overflow. (" +
387 buffer.getLengthInBits() +
388 ">" +
389 totalDataCount * 8 +
390 ")");
391 }
392
393 // end code
394 if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
395 buffer.put(0, 4);
396 }
397
398 // padding
399 while (buffer.getLengthInBits() % 8 != 0) {
400 buffer.putBit(false);
401 }
402
403 // padding
404 while (true) {
405
406 if (buffer.getLengthInBits() >= totalDataCount * 8) {
407 break;
408 }
409 buffer.put(QRCode.PAD0, 8);
410
411 if (buffer.getLengthInBits() >= totalDataCount * 8) {
412 break;
413 }
414 buffer.put(QRCode.PAD1, 8);
415 }
416
417 return QRCode.createBytes(buffer, rsBlocks);
418 }
419
420 QRCode.createBytes = function(buffer, rsBlocks) {
421
422 var offset = 0;
423
424 var maxDcCount = 0;
425 var maxEcCount = 0;
426
427 var dcdata = new Array(rsBlocks.length);
428 var ecdata = new Array(rsBlocks.length);
429
430 for (var r = 0; r < rsBlocks.length; r++) {
431
432 var dcCount = rsBlocks[r].dataCount;
433 var ecCount = rsBlocks[r].totalCount - dcCount;
434
435 maxDcCount = Math.max(maxDcCount, dcCount);
436 maxEcCount = Math.max(maxEcCount, ecCount);
437
438 dcdata[r] = new Array(dcCount);
439
440 for (var i = 0; i < dcdata[r].length; i++) {
441 dcdata[r][i] = 0xff & buffer.buffer[i + offset];
442 }
443 offset += dcCount;
444
445 var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
446 var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
447
448 var modPoly = rawPoly.mod(rsPoly);
449 ecdata[r] = new Array(rsPoly.getLength() - 1);
450 for (var i = 0; i < ecdata[r].length; i++) {
451 var modIndex = i + modPoly.getLength() - ecdata[r].length;
452 ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
453 }
454
455 }
456
457 var totalCodeCount = 0;
458 for (var i = 0; i < rsBlocks.length; i++) {
459 totalCodeCount += rsBlocks[i].totalCount;
460 }
461
462 var data = new Array(totalCodeCount);
463 var index = 0;
464
465 for (var i = 0; i < maxDcCount; i++) {
466 for (var r = 0; r < rsBlocks.length; r++) {
467 if (i < dcdata[r].length) {
468 data[index++] = dcdata[r][i];
469 }
470 }
471 }
472
473 for (var i = 0; i < maxEcCount; i++) {
474 for (var r = 0; r < rsBlocks.length; r++) {
475 if (i < ecdata[r].length) {
476 data[index++] = ecdata[r][i];
477 }
478 }
479 }
480
481 return data;
482
483 }
484
485 //---------------------------------------------------------------------
486 // QRMode
487 //---------------------------------------------------------------------
488
489 var QRMode = {
490 MODE_NUMBER: 1 << 0,
491 MODE_ALPHA_NUM: 1 << 1,
492 MODE_8BIT_BYTE: 1 << 2,
493 MODE_KANJI: 1 << 3
494 };
495
496 //---------------------------------------------------------------------
497 // QRErrorCorrectLevel
498 //---------------------------------------------------------------------
499
500 var QRErrorCorrectLevel = {
501 L: 1,
502 M: 0,
503 Q: 3,
504 H: 2
505 };
506
507 //---------------------------------------------------------------------
508 // QRMaskPattern
509 //---------------------------------------------------------------------
510
511 var QRMaskPattern = {
512 PATTERN000: 0,
513 PATTERN001: 1,
514 PATTERN010: 2,
515 PATTERN011: 3,
516 PATTERN100: 4,
517 PATTERN101: 5,
518 PATTERN110: 6,
519 PATTERN111: 7
520 };
521
522 //---------------------------------------------------------------------
523 // QRUtil
524 //---------------------------------------------------------------------
525
526 var QRUtil = {
527
528 PATTERN_POSITION_TABLE: [
529 [],
530 [6, 18],
531 [6, 22],
532 [6, 26],
533 [6, 30],
534 [6, 34],
535 [6, 22, 38],
536 [6, 24, 42],
537 [6, 26, 46],
538 [6, 28, 50],
539 [6, 30, 54],
540 [6, 32, 58],
541 [6, 34, 62],
542 [6, 26, 46, 66],
543 [6, 26, 48, 70],
544 [6, 26, 50, 74],
545 [6, 30, 54, 78],
546 [6, 30, 56, 82],
547 [6, 30, 58, 86],
548 [6, 34, 62, 90],
549 [6, 28, 50, 72, 94],
550 [6, 26, 50, 74, 98],
551 [6, 30, 54, 78, 102],
552 [6, 28, 54, 80, 106],
553 [6, 32, 58, 84, 110],
554 [6, 30, 58, 86, 114],
555 [6, 34, 62, 90, 118],
556 [6, 26, 50, 74, 98, 122],
557 [6, 30, 54, 78, 102, 126],
558 [6, 26, 52, 78, 104, 130],
559 [6, 30, 56, 82, 108, 134],
560 [6, 34, 60, 86, 112, 138],
561 [6, 30, 58, 86, 114, 142],
562 [6, 34, 62, 90, 118, 146],
563 [6, 30, 54, 78, 102, 126, 150],
564 [6, 24, 50, 76, 102, 128, 154],
565 [6, 28, 54, 80, 106, 132, 158],
566 [6, 32, 58, 84, 110, 136, 162],
567 [6, 26, 54, 82, 110, 138, 166],
568 [6, 30, 58, 86, 114, 142, 170]
569 ],
570
571 G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
572 G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
573 G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
574
575 getBCHTypeInfo: function(data) {
576 var d = data << 10;
577 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
578 d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
579 }
580 return ((data << 10) | d) ^ QRUtil.G15_MASK;
581 },
582
583 getBCHTypeNumber: function(data) {
584 var d = data << 12;
585 while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
586 d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
587 }
588 return (data << 12) | d;
589 },
590
591 getBCHDigit: function(data) {
592
593 var digit = 0;
594
595 while (data != 0) {
596 digit++;
597 data >>>= 1;
598 }
599
600 return digit;
601 },
602
603 getPatternPosition: function(typeNumber) {
604 return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
605 },
606
607 getMask: function(maskPattern, i, j) {
608
609 switch (maskPattern) {
610
611 case QRMaskPattern.PATTERN000:
612 return (i + j) % 2 == 0;
613 case QRMaskPattern.PATTERN001:
614 return i % 2 == 0;
615 case QRMaskPattern.PATTERN010:
616 return j % 3 == 0;
617 case QRMaskPattern.PATTERN011:
618 return (i + j) % 3 == 0;
619 case QRMaskPattern.PATTERN100:
620 return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
621 case QRMaskPattern.PATTERN101:
622 return (i * j) % 2 + (i * j) % 3 == 0;
623 case QRMaskPattern.PATTERN110:
624 return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
625 case QRMaskPattern.PATTERN111:
626 return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
627
628 default:
629 throw new Error("bad maskPattern:" + maskPattern);
630 }
631 },
632
633 getErrorCorrectPolynomial: function(errorCorrectLength) {
634
635 var a = new QRPolynomial([1], 0);
636
637 for (var i = 0; i < errorCorrectLength; i++) {
638 a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
639 }
640
641 return a;
642 },
643
644 getLengthInBits: function(mode, type) {
645
646 if (1 <= type && type < 10) {
647
648 // 1 - 9
649
650 switch (mode) {
651 case QRMode.MODE_NUMBER:
652 return 10;
653 case QRMode.MODE_ALPHA_NUM:
654 return 9;
655 case QRMode.MODE_8BIT_BYTE:
656 return 8;
657 case QRMode.MODE_KANJI:
658 return 8;
659 default:
660 throw new Error("mode:" + mode);
661 }
662
663 } else if (type < 27) {
664
665 // 10 - 26
666
667 switch (mode) {
668 case QRMode.MODE_NUMBER:
669 return 12;
670 case QRMode.MODE_ALPHA_NUM:
671 return 11;
672 case QRMode.MODE_8BIT_BYTE:
673 return 16;
674 case QRMode.MODE_KANJI:
675 return 10;
676 default:
677 throw new Error("mode:" + mode);
678 }
679
680 } else if (type < 41) {
681
682 // 27 - 40
683
684 switch (mode) {
685 case QRMode.MODE_NUMBER:
686 return 14;
687 case QRMode.MODE_ALPHA_NUM:
688 return 13;
689 case QRMode.MODE_8BIT_BYTE:
690 return 16;
691 case QRMode.MODE_KANJI:
692 return 12;
693 default:
694 throw new Error("mode:" + mode);
695 }
696
697 } else {
698 throw new Error("type:" + type);
699 }
700 },
701
702 getLostPoint: function(qrCode) {
703
704 var moduleCount = qrCode.getModuleCount();
705
706 var lostPoint = 0;
707
708 // LEVEL1
709
710 for (var row = 0; row < moduleCount; row++) {
711
712 for (var col = 0; col < moduleCount; col++) {
713
714 var sameCount = 0;
715 var dark = qrCode.isDark(row, col);
716
717 for (var r = -1; r <= 1; r++) {
718
719 if (row + r < 0 || moduleCount <= row + r) {
720 continue;
721 }
722
723 for (var c = -1; c <= 1; c++) {
724
725 if (col + c < 0 || moduleCount <= col + c) {
726 continue;
727 }
728
729 if (r == 0 && c == 0) {
730 continue;
731 }
732
733 if (dark == qrCode.isDark(row + r, col + c)) {
734 sameCount++;
735 }
736 }
737 }
738
739 if (sameCount > 5) {
740 lostPoint += (3 + sameCount - 5);
741 }
742 }
743 }
744
745 // LEVEL2
746
747 for (var row = 0; row < moduleCount - 1; row++) {
748 for (var col = 0; col < moduleCount - 1; col++) {
749 var count = 0;
750 if (qrCode.isDark(row, col)) count++;
751 if (qrCode.isDark(row + 1, col)) count++;
752 if (qrCode.isDark(row, col + 1)) count++;
753 if (qrCode.isDark(row + 1, col + 1)) count++;
754 if (count == 0 || count == 4) {
755 lostPoint += 3;
756 }
757 }
758 }
759
760 // LEVEL3
761
762 for (var row = 0; row < moduleCount; row++) {
763 for (var col = 0; col < moduleCount - 6; col++) {
764 if (qrCode.isDark(row, col) &&
765 !qrCode.isDark(row, col + 1) &&
766 qrCode.isDark(row, col + 2) &&
767 qrCode.isDark(row, col + 3) &&
768 qrCode.isDark(row, col + 4) &&
769 !qrCode.isDark(row, col + 5) &&
770 qrCode.isDark(row, col + 6)) {
771 lostPoint += 40;
772 }
773 }
774 }
775
776 for (var col = 0; col < moduleCount; col++) {
777 for (var row = 0; row < moduleCount - 6; row++) {
778 if (qrCode.isDark(row, col) &&
779 !qrCode.isDark(row + 1, col) &&
780 qrCode.isDark(row + 2, col) &&
781 qrCode.isDark(row + 3, col) &&
782 qrCode.isDark(row + 4, col) &&
783 !qrCode.isDark(row + 5, col) &&
784 qrCode.isDark(row + 6, col)) {
785 lostPoint += 40;
786 }
787 }
788 }
789
790 // LEVEL4
791
792 var darkCount = 0;
793
794 for (var col = 0; col < moduleCount; col++) {
795 for (var row = 0; row < moduleCount; row++) {
796 if (qrCode.isDark(row, col)) {
797 darkCount++;
798 }
799 }
800 }
801
802 var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
803 lostPoint += ratio * 10;
804
805 return lostPoint;
806 }
807
808 };
809
810
811 //---------------------------------------------------------------------
812 // QRMath
813 //---------------------------------------------------------------------
814
815 var QRMath = {
816
817 glog: function(n) {
818
819 if (n < 1) {
820 throw new Error("glog(" + n + ")");
821 }
822
823 return QRMath.LOG_TABLE[n];
824 },
825
826 gexp: function(n) {
827
828 while (n < 0) {
829 n += 255;
830 }
831
832 while (n >= 256) {
833 n -= 255;
834 }
835
836 return QRMath.EXP_TABLE[n];
837 },
838
839 EXP_TABLE: new Array(256),
840
841 LOG_TABLE: new Array(256)
842
843 };
844
845 for (var i = 0; i < 8; i++) {
846 QRMath.EXP_TABLE[i] = 1 << i;
847 }
848 for (var i = 8; i < 256; i++) {
849 QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^
850 QRMath.EXP_TABLE[i - 5] ^
851 QRMath.EXP_TABLE[i - 6] ^
852 QRMath.EXP_TABLE[i - 8];
853 }
854 for (var i = 0; i < 255; i++) {
855 QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
856 }
857
858 //---------------------------------------------------------------------
859 // QRPolynomial
860 //---------------------------------------------------------------------
861
862 function QRPolynomial(num, shift) {
863
864 if (num.length == undefined) {
865 throw new Error(num.length + "/" + shift);
866 }
867
868 var offset = 0;
869
870 while (offset < num.length && num[offset] == 0) {
871 offset++;
872 }
873
874 this.num = new Array(num.length - offset + shift);
875 for (var i = 0; i < num.length - offset; i++) {
876 this.num[i] = num[i + offset];
877 }
878 }
879
880 QRPolynomial.prototype = {
881
882 get: function(index) {
883 return this.num[index];
884 },
885
886 getLength: function() {
887 return this.num.length;
888 },
889
890 multiply: function(e) {
891
892 var num = new Array(this.getLength() + e.getLength() - 1);
893
894 for (var i = 0; i < this.getLength(); i++) {
895 for (var j = 0; j < e.getLength(); j++) {
896 num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
897 }
898 }
899
900 return new QRPolynomial(num, 0);
901 },
902
903 mod: function(e) {
904
905 if (this.getLength() - e.getLength() < 0) {
906 return this;
907 }
908
909 var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
910
911 var num = new Array(this.getLength());
912
913 for (var i = 0; i < this.getLength(); i++) {
914 num[i] = this.get(i);
915 }
916
917 for (var i = 0; i < e.getLength(); i++) {
918 num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
919 }
920
921 // recursive call
922 return new QRPolynomial(num, 0).mod(e);
923 }
924 };
925
926 //---------------------------------------------------------------------
927 // QRRSBlock
928 //---------------------------------------------------------------------
929
930 function QRRSBlock(totalCount, dataCount) {
931 this.totalCount = totalCount;
932 this.dataCount = dataCount;
933 }
934
935 QRRSBlock.RS_BLOCK_TABLE = [
936
937 // L
938 // M
939 // Q
940 // H
941
942 // 1
943 [1, 26, 19],
944 [1, 26, 16],
945 [1, 26, 13],
946 [1, 26, 9],
947
948 // 2
949 [1, 44, 34],
950 [1, 44, 28],
951 [1, 44, 22],
952 [1, 44, 16],
953
954 // 3
955 [1, 70, 55],
956 [1, 70, 44],
957 [2, 35, 17],
958 [2, 35, 13],
959
960 // 4
961 [1, 100, 80],
962 [2, 50, 32],
963 [2, 50, 24],
964 [4, 25, 9],
965
966 // 5
967 [1, 134, 108],
968 [2, 67, 43],
969 [2, 33, 15, 2, 34, 16],
970 [2, 33, 11, 2, 34, 12],
971
972 // 6
973 [2, 86, 68],
974 [4, 43, 27],
975 [4, 43, 19],
976 [4, 43, 15],
977
978 // 7
979 [2, 98, 78],
980 [4, 49, 31],
981 [2, 32, 14, 4, 33, 15],
982 [4, 39, 13, 1, 40, 14],
983
984 // 8
985 [2, 121, 97],
986 [2, 60, 38, 2, 61, 39],
987 [4, 40, 18, 2, 41, 19],
988 [4, 40, 14, 2, 41, 15],
989
990 // 9
991 [2, 146, 116],
992 [3, 58, 36, 2, 59, 37],
993 [4, 36, 16, 4, 37, 17],
994 [4, 36, 12, 4, 37, 13],
995
996 // 10
997 [2, 86, 68, 2, 87, 69],
998 [4, 69, 43, 1, 70, 44],
999 [6, 43, 19, 2, 44, 20],
1000 [6, 43, 15, 2, 44, 16],
1001
1002 // 11
1003 [4, 101, 81],
1004 [1, 80, 50, 4, 81, 51],
1005 [4, 50, 22, 4, 51, 23],
1006 [3, 36, 12, 8, 37, 13],
1007
1008 // 12
1009 [2, 116, 92, 2, 117, 93],
1010 [6, 58, 36, 2, 59, 37],
1011 [4, 46, 20, 6, 47, 21],
1012 [7, 42, 14, 4, 43, 15],
1013
1014 // 13
1015 [4, 133, 107],
1016 [8, 59, 37, 1, 60, 38],
1017 [8, 44, 20, 4, 45, 21],
1018 [12, 33, 11, 4, 34, 12],
1019
1020 // 14
1021 [3, 145, 115, 1, 146, 116],
1022 [4, 64, 40, 5, 65, 41],
1023 [11, 36, 16, 5, 37, 17],
1024 [11, 36, 12, 5, 37, 13],
1025
1026 // 15
1027 [5, 109, 87, 1, 110, 88],
1028 [5, 65, 41, 5, 66, 42],
1029 [5, 54, 24, 7, 55, 25],
1030 [11, 36, 12],
1031
1032 // 16
1033 [5, 122, 98, 1, 123, 99],
1034 [7, 73, 45, 3, 74, 46],
1035 [15, 43, 19, 2, 44, 20],
1036 [3, 45, 15, 13, 46, 16],
1037
1038 // 17
1039 [1, 135, 107, 5, 136, 108],
1040 [10, 74, 46, 1, 75, 47],
1041 [1, 50, 22, 15, 51, 23],
1042 [2, 42, 14, 17, 43, 15],
1043
1044 // 18
1045 [5, 150, 120, 1, 151, 121],
1046 [9, 69, 43, 4, 70, 44],
1047 [17, 50, 22, 1, 51, 23],
1048 [2, 42, 14, 19, 43, 15],
1049
1050 // 19
1051 [3, 141, 113, 4, 142, 114],
1052 [3, 70, 44, 11, 71, 45],
1053 [17, 47, 21, 4, 48, 22],
1054 [9, 39, 13, 16, 40, 14],
1055
1056 // 20
1057 [3, 135, 107, 5, 136, 108],
1058 [3, 67, 41, 13, 68, 42],
1059 [15, 54, 24, 5, 55, 25],
1060 [15, 43, 15, 10, 44, 16],
1061
1062 // 21
1063 [4, 144, 116, 4, 145, 117],
1064 [17, 68, 42],
1065 [17, 50, 22, 6, 51, 23],
1066 [19, 46, 16, 6, 47, 17],
1067
1068 // 22
1069 [2, 139, 111, 7, 140, 112],
1070 [17, 74, 46],
1071 [7, 54, 24, 16, 55, 25],
1072 [34, 37, 13],
1073
1074 // 23
1075 [4, 151, 121, 5, 152, 122],
1076 [4, 75, 47, 14, 76, 48],
1077 [11, 54, 24, 14, 55, 25],
1078 [16, 45, 15, 14, 46, 16],
1079
1080 // 24
1081 [6, 147, 117, 4, 148, 118],
1082 [6, 73, 45, 14, 74, 46],
1083 [11, 54, 24, 16, 55, 25],
1084 [30, 46, 16, 2, 47, 17],
1085
1086 // 25
1087 [8, 132, 106, 4, 133, 107],
1088 [8, 75, 47, 13, 76, 48],
1089 [7, 54, 24, 22, 55, 25],
1090 [22, 45, 15, 13, 46, 16],
1091
1092 // 26
1093 [10, 142, 114, 2, 143, 115],
1094 [19, 74, 46, 4, 75, 47],
1095 [28, 50, 22, 6, 51, 23],
1096 [33, 46, 16, 4, 47, 17],
1097
1098 // 27
1099 [8, 152, 122, 4, 153, 123],
1100 [22, 73, 45, 3, 74, 46],
1101 [8, 53, 23, 26, 54, 24],
1102 [12, 45, 15, 28, 46, 16],
1103
1104 // 28
1105 [3, 147, 117, 10, 148, 118],
1106 [3, 73, 45, 23, 74, 46],
1107 [4, 54, 24, 31, 55, 25],
1108 [11, 45, 15, 31, 46, 16],
1109
1110 // 29
1111 [7, 146, 116, 7, 147, 117],
1112 [21, 73, 45, 7, 74, 46],
1113 [1, 53, 23, 37, 54, 24],
1114 [19, 45, 15, 26, 46, 16],
1115
1116 // 30
1117 [5, 145, 115, 10, 146, 116],
1118 [19, 75, 47, 10, 76, 48],
1119 [15, 54, 24, 25, 55, 25],
1120 [23, 45, 15, 25, 46, 16],
1121
1122 // 31
1123 [13, 145, 115, 3, 146, 116],
1124 [2, 74, 46, 29, 75, 47],
1125 [42, 54, 24, 1, 55, 25],
1126 [23, 45, 15, 28, 46, 16],
1127
1128 // 32
1129 [17, 145, 115],
1130 [10, 74, 46, 23, 75, 47],
1131 [10, 54, 24, 35, 55, 25],
1132 [19, 45, 15, 35, 46, 16],
1133
1134 // 33
1135 [17, 145, 115, 1, 146, 116],
1136 [14, 74, 46, 21, 75, 47],
1137 [29, 54, 24, 19, 55, 25],
1138 [11, 45, 15, 46, 46, 16],
1139
1140 // 34
1141 [13, 145, 115, 6, 146, 116],
1142 [14, 74, 46, 23, 75, 47],
1143 [44, 54, 24, 7, 55, 25],
1144 [59, 46, 16, 1, 47, 17],
1145
1146 // 35
1147 [12, 151, 121, 7, 152, 122],
1148 [12, 75, 47, 26, 76, 48],
1149 [39, 54, 24, 14, 55, 25],
1150 [22, 45, 15, 41, 46, 16],
1151
1152 // 36
1153 [6, 151, 121, 14, 152, 122],
1154 [6, 75, 47, 34, 76, 48],
1155 [46, 54, 24, 10, 55, 25],
1156 [2, 45, 15, 64, 46, 16],
1157
1158 // 37
1159 [17, 152, 122, 4, 153, 123],
1160 [29, 74, 46, 14, 75, 47],
1161 [49, 54, 24, 10, 55, 25],
1162 [24, 45, 15, 46, 46, 16],
1163
1164 // 38
1165 [4, 152, 122, 18, 153, 123],
1166 [13, 74, 46, 32, 75, 47],
1167 [48, 54, 24, 14, 55, 25],
1168 [42, 45, 15, 32, 46, 16],
1169
1170 // 39
1171 [20, 147, 117, 4, 148, 118],
1172 [40, 75, 47, 7, 76, 48],
1173 [43, 54, 24, 22, 55, 25],
1174 [10, 45, 15, 67, 46, 16],
1175
1176 // 40
1177 [19, 148, 118, 6, 149, 119],
1178 [18, 75, 47, 31, 76, 48],
1179 [34, 54, 24, 34, 55, 25],
1180 [20, 45, 15, 61, 46, 16]
1181 ];
1182
1183 QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
1184
1185 var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
1186
1187 if (rsBlock == undefined) {
1188 throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
1189 }
1190
1191 var length = rsBlock.length / 3;
1192
1193 var list = new Array();
1194
1195 for (var i = 0; i < length; i++) {
1196
1197 var count = rsBlock[i * 3 + 0];
1198 var totalCount = rsBlock[i * 3 + 1];
1199 var dataCount = rsBlock[i * 3 + 2];
1200
1201 for (var j = 0; j < count; j++) {
1202 list.push(new QRRSBlock(totalCount, dataCount));
1203 }
1204 }
1205
1206 return list;
1207 }
1208
1209 QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
1210
1211 switch (errorCorrectLevel) {
1212 case QRErrorCorrectLevel.L:
1213 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
1214 case QRErrorCorrectLevel.M:
1215 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
1216 case QRErrorCorrectLevel.Q:
1217 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
1218 case QRErrorCorrectLevel.H:
1219 return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
1220 default:
1221 return undefined;
1222 }
1223 }
1224
1225 //---------------------------------------------------------------------
1226 // QRBitBuffer
1227 //---------------------------------------------------------------------
1228
1229 function QRBitBuffer() {
1230 this.buffer = new Array();
1231 this.length = 0;
1232 }
1233
1234 QRBitBuffer.prototype = {
1235
1236 get: function(index) {
1237 var bufIndex = Math.floor(index / 8);
1238 return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
1239 },
1240
1241 put: function(num, length) {
1242 for (var i = 0; i < length; i++) {
1243 this.putBit(((num >>> (length - i - 1)) & 1) == 1);
1244 }
1245 },
1246
1247 getLengthInBits: function() {
1248 return this.length;
1249 },
1250
1251 putBit: function(bit) {
1252
1253 var bufIndex = Math.floor(this.length / 8);
1254 if (this.buffer.length <= bufIndex) {
1255 this.buffer.push(0);
1256 }
1257
1258 if (bit) {
1259 this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
1260 }
1261
1262 this.length++;
1263 }
1264 };
1265
1266 //---------------------------------------------------------------------
1267 // Support Chinese
1268 //---------------------------------------------------------------------
1269 function utf16To8(text) {
1270 var result = '';
1271 var c;
1272 for (var i = 0; i < text.length; i++) {
1273 c = text.charCodeAt(i);
1274 if (c >= 0x0001 && c <= 0x007F) {
1275 result += text.charAt(i);
1276 } else if (c > 0x07FF) {
1277 result += String.fromCharCode(0xE0 | c >> 12 & 0x0F);
1278 result += String.fromCharCode(0x80 | c >> 6 & 0x3F);
1279 result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
1280 } else {
1281 result += String.fromCharCode(0xC0 | c >> 6 & 0x1F);
1282 result += String.fromCharCode(0x80 | c >> 0 & 0x3F);
1283 }
1284 }
1285 return result;
1286 }
1287
1288 uQRCode = {
1289
1290 errorCorrectLevel: QRErrorCorrectLevel,
1291
1292 defaults: {
1293 size: 354,
1294 margin: 0,
1295 backgroundColor: '#ffffff',
1296 foregroundColor: '#000000',
1297 fileType: 'png', // 'jpg', 'png'
1298 errorCorrectLevel: QRErrorCorrectLevel.H,
1299 typeNumber: -1
1300 },
1301
1302 make: function(options) {
1303 var defaultOptions = {
1304 canvasId: options.canvasId,
1305 componentInstance: options.componentInstance,
1306 text: options.text,
1307 size: this.defaults.size,
1308 margin: this.defaults.margin,
1309 backgroundColor: this.defaults.backgroundColor,
1310 foregroundColor: this.defaults.foregroundColor,
1311 fileType: this.defaults.fileType,
1312 errorCorrectLevel: this.defaults.errorCorrectLevel,
1313 typeNumber: this.defaults.typeNumber
1314 };
1315 if (options) {
1316 for (var i in options) {
1317 defaultOptions[i] = options[i];
1318 }
1319 }
1320 options = defaultOptions;
1321 if (!options.canvasId) {
1322 console.error('uQRCode: Please set canvasId!');
1323 return;
1324 }
1325
1326 function createCanvas() {
1327 var qrcode = new QRCode(options.typeNumber, options.errorCorrectLevel);
1328 qrcode.addData(utf16To8(options.text));
1329 qrcode.make();
1330
1331 var ctx = uni.createCanvasContext(options.canvasId, options.componentInstance);
1332 ctx.setFillStyle(options.backgroundColor);
1333 ctx.fillRect(0, 0, options.size, options.size);
1334
1335 var tileW = (options.size - options.margin * 2) / qrcode.getModuleCount();
1336 var tileH = tileW;
1337
1338 for (var row = 0; row < qrcode.getModuleCount(); row++) {
1339 for (var col = 0; col < qrcode.getModuleCount(); col++) {
1340 var style = qrcode.isDark(row, col) ? options.foregroundColor : options.backgroundColor;
1341 ctx.setFillStyle(style);
1342 var x = Math.round(col * tileW) + options.margin;
1343 var y = Math.round(row * tileH) + options.margin;
1344 var w = Math.ceil((col + 1) * tileW) - Math.floor(col * tileW);
1345 var h = Math.ceil((row + 1) * tileW) - Math.floor(row * tileW);
1346 ctx.fillRect(x, y, w, h);
1347 }
1348 }
1349
1350 setTimeout(function() {
1351 ctx.draw(false, (function() {
1352 setTimeout(function() {
1353 uni.canvasToTempFilePath({
1354 canvasId: options.canvasId,
1355 fileType: options.fileType,
1356 width: options.size,
1357 height: options.size,
1358 destWidth: options.size,
1359 destHeight: options.size,
1360 success: function(res) {
1361 options.success && options.success(res.tempFilePath);
1362 },
1363 fail: function(error) {
1364 options.fail && options.fail(error);
1365 },
1366 complete: function(res) {
1367 options.complete && options.complete(res);
1368 }
1369 }, options.componentInstance);
1370 }, options.text.length + 100);
1371 })());
1372 }, 150);
1373 }
1374
1375 createCanvas();
1376 }
1377
1378 }
1379
1380})()
1381
1382// export default uQRCode
1383module.exports = uQRCode