@pjaudiomv/qrcode-svg 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/qrcode.js ADDED
@@ -0,0 +1,1672 @@
1
+ /**
2
+ * @fileoverview
3
+ * - modified davidshimjs/qrcodejs library for use in node.js
4
+ * - Using the 'QRCode for Javascript library'
5
+ * - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
6
+ * - this library has no dependencies.
7
+ *
8
+ * @version 0.9.1 (2016-02-12)
9
+ * @author davidshimjs, papnkukn
10
+ * @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
11
+ * @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
12
+ * @see <a href="https://github.com/davidshimjs/qrcodejs" target="_blank">https://github.com/davidshimjs/qrcodejs</a>
13
+ */
14
+
15
+ //---------------------------------------------------------------------
16
+ // QRCode for JavaScript
17
+ //
18
+ // Copyright (c) 2009 Kazuhiko Arase
19
+ //
20
+ // URL: http://www.d-project.com/
21
+ //
22
+ // Licensed under the MIT license:
23
+ // http://www.opensource.org/licenses/mit-license.php
24
+ //
25
+ // The word "QR Code" is registered trademark of
26
+ // DENSO WAVE INCORPORATED
27
+ // http://www.denso-wave.com/qrcode/faqpatent-e.html
28
+ //
29
+ //---------------------------------------------------------------------
30
+
31
+ //---------------------------------------------------------------------
32
+ // QR8bitByte
33
+ //---------------------------------------------------------------------
34
+
35
+ function QR8bitByte(data) {
36
+ this.mode = QRMode.MODE_8BIT_BYTE;
37
+ this.data = data;
38
+ this.parsedData = [];
39
+
40
+ // Added to support UTF-8 Characters
41
+ for (var i = 0, l = this.data.length; i < l; i++) {
42
+ var byteArray = [];
43
+ var code = this.data.charCodeAt(i);
44
+
45
+ if (code > 0x10000) {
46
+ byteArray[0] = 0xf0 | ((code & 0x1c0000) >>> 18);
47
+ byteArray[1] = 0x80 | ((code & 0x3f000) >>> 12);
48
+ byteArray[2] = 0x80 | ((code & 0xfc0) >>> 6);
49
+ byteArray[3] = 0x80 | (code & 0x3f);
50
+ } else if (code > 0x800) {
51
+ byteArray[0] = 0xe0 | ((code & 0xf000) >>> 12);
52
+ byteArray[1] = 0x80 | ((code & 0xfc0) >>> 6);
53
+ byteArray[2] = 0x80 | (code & 0x3f);
54
+ } else if (code > 0x80) {
55
+ byteArray[0] = 0xc0 | ((code & 0x7c0) >>> 6);
56
+ byteArray[1] = 0x80 | (code & 0x3f);
57
+ } else {
58
+ byteArray[0] = code;
59
+ }
60
+
61
+ this.parsedData.push(byteArray);
62
+ }
63
+
64
+ this.parsedData = Array.prototype.concat.apply([], this.parsedData);
65
+
66
+ if (this.parsedData.length != this.data.length) {
67
+ this.parsedData.unshift(191);
68
+ this.parsedData.unshift(187);
69
+ this.parsedData.unshift(239);
70
+ }
71
+ }
72
+
73
+ QR8bitByte.prototype = {
74
+ getLength: function (buffer) {
75
+ return this.parsedData.length;
76
+ },
77
+ write: function (buffer) {
78
+ for (var i = 0, l = this.parsedData.length; i < l; i++) {
79
+ buffer.put(this.parsedData[i], 8);
80
+ }
81
+ },
82
+ };
83
+
84
+ //---------------------------------------------------------------------
85
+ // QRCodeModel
86
+ //---------------------------------------------------------------------
87
+
88
+ function QRCodeModel(typeNumber, errorCorrectLevel) {
89
+ this.typeNumber = typeNumber;
90
+ this.errorCorrectLevel = errorCorrectLevel;
91
+ this.modules = null;
92
+ this.moduleCount = 0;
93
+ this.dataCache = null;
94
+ this.dataList = [];
95
+ }
96
+
97
+ QRCodeModel.prototype = {
98
+ addData: function (data) {
99
+ var newData = new QR8bitByte(data);
100
+ this.dataList.push(newData);
101
+ this.dataCache = null;
102
+ },
103
+
104
+ isDark: function (row, col) {
105
+ if (
106
+ row < 0 ||
107
+ this.moduleCount <= row ||
108
+ col < 0 ||
109
+ this.moduleCount <= col
110
+ ) {
111
+ throw new Error(row + "," + col);
112
+ }
113
+ return this.modules[row][col];
114
+ },
115
+
116
+ getModuleCount: function () {
117
+ return this.moduleCount;
118
+ },
119
+
120
+ make: function () {
121
+ // Calculate automatically typeNumber if provided is < 1
122
+ if (this.typeNumber < 1) {
123
+ var typeNumber = 1;
124
+ for (typeNumber = 1; typeNumber < 40; typeNumber++) {
125
+ var rsBlocks = QRRSBlock.getRSBlocks(
126
+ typeNumber,
127
+ this.errorCorrectLevel
128
+ );
129
+
130
+ var buffer = new QRBitBuffer();
131
+ var totalDataCount = 0;
132
+ for (var i = 0; i < rsBlocks.length; i++) {
133
+ totalDataCount += rsBlocks[i].dataCount;
134
+ }
135
+
136
+ for (var i = 0; i < this.dataList.length; i++) {
137
+ var data = this.dataList[i];
138
+ buffer.put(data.mode, 4);
139
+ buffer.put(
140
+ data.getLength(),
141
+ QRUtil.getLengthInBits(data.mode, typeNumber)
142
+ );
143
+ data.write(buffer);
144
+ }
145
+ if (buffer.getLengthInBits() <= totalDataCount * 8) break;
146
+ }
147
+ this.typeNumber = typeNumber;
148
+ }
149
+ this.makeImpl(false, this.getBestMaskPattern());
150
+ },
151
+
152
+ makeImpl: function (test, maskPattern) {
153
+ this.moduleCount = this.typeNumber * 4 + 17;
154
+ this.modules = new Array(this.moduleCount);
155
+
156
+ for (var row = 0; row < this.moduleCount; row++) {
157
+ this.modules[row] = new Array(this.moduleCount);
158
+
159
+ for (var col = 0; col < this.moduleCount; col++) {
160
+ this.modules[row][col] = null; //(col + row) % 3;
161
+ }
162
+ }
163
+
164
+ this.setupPositionProbePattern(0, 0);
165
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
166
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
167
+ this.setupPositionAdjustPattern();
168
+ this.setupTimingPattern();
169
+ this.setupTypeInfo(test, maskPattern);
170
+
171
+ if (this.typeNumber >= 7) {
172
+ this.setupTypeNumber(test);
173
+ }
174
+
175
+ if (this.dataCache == null) {
176
+ this.dataCache = QRCodeModel.createData(
177
+ this.typeNumber,
178
+ this.errorCorrectLevel,
179
+ this.dataList
180
+ );
181
+ }
182
+
183
+ this.mapData(this.dataCache, maskPattern);
184
+ },
185
+
186
+ setupPositionProbePattern: function (row, col) {
187
+ for (var r = -1; r <= 7; r++) {
188
+ if (row + r <= -1 || this.moduleCount <= row + r) continue;
189
+
190
+ for (var c = -1; c <= 7; c++) {
191
+ if (col + c <= -1 || this.moduleCount <= col + c) continue;
192
+
193
+ if (
194
+ (0 <= r && r <= 6 && (c == 0 || c == 6)) ||
195
+ (0 <= c && c <= 6 && (r == 0 || r == 6)) ||
196
+ (2 <= r && r <= 4 && 2 <= c && c <= 4)
197
+ ) {
198
+ this.modules[row + r][col + c] = true;
199
+ } else {
200
+ this.modules[row + r][col + c] = false;
201
+ }
202
+ }
203
+ }
204
+ },
205
+
206
+ getBestMaskPattern: function () {
207
+ var minLostPoint = 0;
208
+ var pattern = 0;
209
+
210
+ for (var i = 0; i < 8; i++) {
211
+ this.makeImpl(true, i);
212
+
213
+ var lostPoint = QRUtil.getLostPoint(this);
214
+
215
+ if (i == 0 || minLostPoint > lostPoint) {
216
+ minLostPoint = lostPoint;
217
+ pattern = i;
218
+ }
219
+ }
220
+
221
+ return pattern;
222
+ },
223
+
224
+ createMovieClip: function (target_mc, instance_name, depth) {
225
+ var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
226
+ var cs = 1;
227
+
228
+ this.make();
229
+
230
+ for (var row = 0; row < this.modules.length; row++) {
231
+ var y = row * cs;
232
+
233
+ for (var col = 0; col < this.modules[row].length; col++) {
234
+ var x = col * cs;
235
+ var dark = this.modules[row][col];
236
+
237
+ if (dark) {
238
+ qr_mc.beginFill(0, 100);
239
+ qr_mc.moveTo(x, y);
240
+ qr_mc.lineTo(x + cs, y);
241
+ qr_mc.lineTo(x + cs, y + cs);
242
+ qr_mc.lineTo(x, y + cs);
243
+ qr_mc.endFill();
244
+ }
245
+ }
246
+ }
247
+
248
+ return qr_mc;
249
+ },
250
+
251
+ setupTimingPattern: function () {
252
+ for (var r = 8; r < this.moduleCount - 8; r++) {
253
+ if (this.modules[r][6] != null) {
254
+ continue;
255
+ }
256
+ this.modules[r][6] = r % 2 == 0;
257
+ }
258
+
259
+ for (var c = 8; c < this.moduleCount - 8; c++) {
260
+ if (this.modules[6][c] != null) {
261
+ continue;
262
+ }
263
+ this.modules[6][c] = c % 2 == 0;
264
+ }
265
+ },
266
+
267
+ setupPositionAdjustPattern: function () {
268
+ var pos = QRUtil.getPatternPosition(this.typeNumber);
269
+
270
+ for (var i = 0; i < pos.length; i++) {
271
+ for (var j = 0; j < pos.length; j++) {
272
+ var row = pos[i];
273
+ var col = pos[j];
274
+
275
+ if (this.modules[row][col] != null) {
276
+ continue;
277
+ }
278
+
279
+ for (var r = -2; r <= 2; r++) {
280
+ for (var c = -2; c <= 2; c++) {
281
+ if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
282
+ this.modules[row + r][col + c] = true;
283
+ } else {
284
+ this.modules[row + r][col + c] = false;
285
+ }
286
+ }
287
+ }
288
+ }
289
+ }
290
+ },
291
+
292
+ setupTypeNumber: function (test) {
293
+ var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
294
+
295
+ for (var i = 0; i < 18; i++) {
296
+ var mod = !test && ((bits >> i) & 1) == 1;
297
+ this.modules[Math.floor(i / 3)][(i % 3) + this.moduleCount - 8 - 3] = mod;
298
+ }
299
+
300
+ for (var i = 0; i < 18; i++) {
301
+ var mod = !test && ((bits >> i) & 1) == 1;
302
+ this.modules[(i % 3) + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
303
+ }
304
+ },
305
+
306
+ setupTypeInfo: function (test, maskPattern) {
307
+ var data = (this.errorCorrectLevel << 3) | maskPattern;
308
+ var bits = QRUtil.getBCHTypeInfo(data);
309
+
310
+ // vertical
311
+ for (var i = 0; i < 15; i++) {
312
+ var mod = !test && ((bits >> i) & 1) == 1;
313
+
314
+ if (i < 6) {
315
+ this.modules[i][8] = mod;
316
+ } else if (i < 8) {
317
+ this.modules[i + 1][8] = mod;
318
+ } else {
319
+ this.modules[this.moduleCount - 15 + i][8] = mod;
320
+ }
321
+ }
322
+
323
+ // horizontal
324
+ for (var i = 0; i < 15; i++) {
325
+ var mod = !test && ((bits >> i) & 1) == 1;
326
+
327
+ if (i < 8) {
328
+ this.modules[8][this.moduleCount - i - 1] = mod;
329
+ } else if (i < 9) {
330
+ this.modules[8][15 - i - 1 + 1] = mod;
331
+ } else {
332
+ this.modules[8][15 - i - 1] = mod;
333
+ }
334
+ }
335
+
336
+ // fixed module
337
+ this.modules[this.moduleCount - 8][8] = !test;
338
+ },
339
+
340
+ mapData: function (data, maskPattern) {
341
+ var inc = -1;
342
+ var row = this.moduleCount - 1;
343
+ var bitIndex = 7;
344
+ var byteIndex = 0;
345
+
346
+ for (var col = this.moduleCount - 1; col > 0; col -= 2) {
347
+ if (col == 6) col--;
348
+
349
+ while (true) {
350
+ for (var c = 0; c < 2; c++) {
351
+ if (this.modules[row][col - c] == null) {
352
+ var dark = false;
353
+
354
+ if (byteIndex < data.length) {
355
+ dark = ((data[byteIndex] >>> bitIndex) & 1) == 1;
356
+ }
357
+
358
+ var mask = QRUtil.getMask(maskPattern, row, col - c);
359
+
360
+ if (mask) {
361
+ dark = !dark;
362
+ }
363
+
364
+ this.modules[row][col - c] = dark;
365
+ bitIndex--;
366
+
367
+ if (bitIndex == -1) {
368
+ byteIndex++;
369
+ bitIndex = 7;
370
+ }
371
+ }
372
+ }
373
+
374
+ row += inc;
375
+
376
+ if (row < 0 || this.moduleCount <= row) {
377
+ row -= inc;
378
+ inc = -inc;
379
+ break;
380
+ }
381
+ }
382
+ }
383
+ },
384
+ };
385
+
386
+ QRCodeModel.PAD0 = 0xec;
387
+ QRCodeModel.PAD1 = 0x11;
388
+
389
+ QRCodeModel.createData = function (typeNumber, errorCorrectLevel, dataList) {
390
+ var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
391
+
392
+ var buffer = new QRBitBuffer();
393
+
394
+ for (var i = 0; i < dataList.length; i++) {
395
+ var data = dataList[i];
396
+ buffer.put(data.mode, 4);
397
+ buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
398
+ data.write(buffer);
399
+ }
400
+
401
+ // calc num max data.
402
+ var totalDataCount = 0;
403
+ for (var i = 0; i < rsBlocks.length; i++) {
404
+ totalDataCount += rsBlocks[i].dataCount;
405
+ }
406
+
407
+ if (buffer.getLengthInBits() > totalDataCount * 8) {
408
+ throw new Error(
409
+ "code length overflow. (" +
410
+ buffer.getLengthInBits() +
411
+ ">" +
412
+ totalDataCount * 8 +
413
+ ")"
414
+ );
415
+ }
416
+
417
+ // end code
418
+ if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
419
+ buffer.put(0, 4);
420
+ }
421
+
422
+ // padding
423
+ while (buffer.getLengthInBits() % 8 != 0) {
424
+ buffer.putBit(false);
425
+ }
426
+
427
+ // padding
428
+ while (true) {
429
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
430
+ break;
431
+ }
432
+ buffer.put(QRCodeModel.PAD0, 8);
433
+
434
+ if (buffer.getLengthInBits() >= totalDataCount * 8) {
435
+ break;
436
+ }
437
+ buffer.put(QRCodeModel.PAD1, 8);
438
+ }
439
+
440
+ return QRCodeModel.createBytes(buffer, rsBlocks);
441
+ };
442
+
443
+ QRCodeModel.createBytes = function (buffer, rsBlocks) {
444
+ var offset = 0;
445
+
446
+ var maxDcCount = 0;
447
+ var maxEcCount = 0;
448
+
449
+ var dcdata = new Array(rsBlocks.length);
450
+ var ecdata = new Array(rsBlocks.length);
451
+
452
+ for (var r = 0; r < rsBlocks.length; r++) {
453
+ var dcCount = rsBlocks[r].dataCount;
454
+ var ecCount = rsBlocks[r].totalCount - dcCount;
455
+
456
+ maxDcCount = Math.max(maxDcCount, dcCount);
457
+ maxEcCount = Math.max(maxEcCount, ecCount);
458
+
459
+ dcdata[r] = new Array(dcCount);
460
+
461
+ for (var i = 0; i < dcdata[r].length; i++) {
462
+ dcdata[r][i] = 0xff & buffer.buffer[i + offset];
463
+ }
464
+ offset += dcCount;
465
+
466
+ var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
467
+ var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
468
+
469
+ var modPoly = rawPoly.mod(rsPoly);
470
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
471
+ for (var i = 0; i < ecdata[r].length; i++) {
472
+ var modIndex = i + modPoly.getLength() - ecdata[r].length;
473
+ ecdata[r][i] = modIndex >= 0 ? modPoly.get(modIndex) : 0;
474
+ }
475
+ }
476
+
477
+ var totalCodeCount = 0;
478
+ for (var i = 0; i < rsBlocks.length; i++) {
479
+ totalCodeCount += rsBlocks[i].totalCount;
480
+ }
481
+
482
+ var data = new Array(totalCodeCount);
483
+ var index = 0;
484
+
485
+ for (var i = 0; i < maxDcCount; i++) {
486
+ for (var r = 0; r < rsBlocks.length; r++) {
487
+ if (i < dcdata[r].length) {
488
+ data[index++] = dcdata[r][i];
489
+ }
490
+ }
491
+ }
492
+
493
+ for (var i = 0; i < maxEcCount; i++) {
494
+ for (var r = 0; r < rsBlocks.length; r++) {
495
+ if (i < ecdata[r].length) {
496
+ data[index++] = ecdata[r][i];
497
+ }
498
+ }
499
+ }
500
+
501
+ return data;
502
+ };
503
+
504
+ //---------------------------------------------------------------------
505
+ // QRMode
506
+ //---------------------------------------------------------------------
507
+
508
+ var QRMode = {
509
+ MODE_NUMBER: 1 << 0,
510
+ MODE_ALPHA_NUM: 1 << 1,
511
+ MODE_8BIT_BYTE: 1 << 2,
512
+ MODE_KANJI: 1 << 3,
513
+ };
514
+
515
+ //---------------------------------------------------------------------
516
+ // QRErrorCorrectLevel
517
+ //---------------------------------------------------------------------
518
+
519
+ var QRErrorCorrectLevel = {
520
+ L: 1,
521
+ M: 0,
522
+ Q: 3,
523
+ H: 2,
524
+ };
525
+
526
+ //---------------------------------------------------------------------
527
+ // QRMaskPattern
528
+ //---------------------------------------------------------------------
529
+
530
+ var QRMaskPattern = {
531
+ PATTERN000: 0,
532
+ PATTERN001: 1,
533
+ PATTERN010: 2,
534
+ PATTERN011: 3,
535
+ PATTERN100: 4,
536
+ PATTERN101: 5,
537
+ PATTERN110: 6,
538
+ PATTERN111: 7,
539
+ };
540
+
541
+ //---------------------------------------------------------------------
542
+ // QRUtil
543
+ //---------------------------------------------------------------------
544
+
545
+ var QRUtil = {
546
+ PATTERN_POSITION_TABLE: [
547
+ [],
548
+ [6, 18],
549
+ [6, 22],
550
+ [6, 26],
551
+ [6, 30],
552
+ [6, 34],
553
+ [6, 22, 38],
554
+ [6, 24, 42],
555
+ [6, 26, 46],
556
+ [6, 28, 50],
557
+ [6, 30, 54],
558
+ [6, 32, 58],
559
+ [6, 34, 62],
560
+ [6, 26, 46, 66],
561
+ [6, 26, 48, 70],
562
+ [6, 26, 50, 74],
563
+ [6, 30, 54, 78],
564
+ [6, 30, 56, 82],
565
+ [6, 30, 58, 86],
566
+ [6, 34, 62, 90],
567
+ [6, 28, 50, 72, 94],
568
+ [6, 26, 50, 74, 98],
569
+ [6, 30, 54, 78, 102],
570
+ [6, 28, 54, 80, 106],
571
+ [6, 32, 58, 84, 110],
572
+ [6, 30, 58, 86, 114],
573
+ [6, 34, 62, 90, 118],
574
+ [6, 26, 50, 74, 98, 122],
575
+ [6, 30, 54, 78, 102, 126],
576
+ [6, 26, 52, 78, 104, 130],
577
+ [6, 30, 56, 82, 108, 134],
578
+ [6, 34, 60, 86, 112, 138],
579
+ [6, 30, 58, 86, 114, 142],
580
+ [6, 34, 62, 90, 118, 146],
581
+ [6, 30, 54, 78, 102, 126, 150],
582
+ [6, 24, 50, 76, 102, 128, 154],
583
+ [6, 28, 54, 80, 106, 132, 158],
584
+ [6, 32, 58, 84, 110, 136, 162],
585
+ [6, 26, 54, 82, 110, 138, 166],
586
+ [6, 30, 58, 86, 114, 142, 170],
587
+ ],
588
+
589
+ G15:
590
+ (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
591
+ G18:
592
+ (1 << 12) |
593
+ (1 << 11) |
594
+ (1 << 10) |
595
+ (1 << 9) |
596
+ (1 << 8) |
597
+ (1 << 5) |
598
+ (1 << 2) |
599
+ (1 << 0),
600
+ G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
601
+
602
+ getBCHTypeInfo: function (data) {
603
+ var d = data << 10;
604
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
605
+ d ^=
606
+ QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15));
607
+ }
608
+ return ((data << 10) | d) ^ QRUtil.G15_MASK;
609
+ },
610
+
611
+ getBCHTypeNumber: function (data) {
612
+ var d = data << 12;
613
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
614
+ d ^=
615
+ QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18));
616
+ }
617
+ return (data << 12) | d;
618
+ },
619
+
620
+ getBCHDigit: function (data) {
621
+ var digit = 0;
622
+
623
+ while (data != 0) {
624
+ digit++;
625
+ data >>>= 1;
626
+ }
627
+
628
+ return digit;
629
+ },
630
+
631
+ getPatternPosition: function (typeNumber) {
632
+ return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
633
+ },
634
+
635
+ getMask: function (maskPattern, i, j) {
636
+ switch (maskPattern) {
637
+ case QRMaskPattern.PATTERN000:
638
+ return (i + j) % 2 == 0;
639
+ case QRMaskPattern.PATTERN001:
640
+ return i % 2 == 0;
641
+ case QRMaskPattern.PATTERN010:
642
+ return j % 3 == 0;
643
+ case QRMaskPattern.PATTERN011:
644
+ return (i + j) % 3 == 0;
645
+ case QRMaskPattern.PATTERN100:
646
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
647
+ case QRMaskPattern.PATTERN101:
648
+ return ((i * j) % 2) + ((i * j) % 3) == 0;
649
+ case QRMaskPattern.PATTERN110:
650
+ return (((i * j) % 2) + ((i * j) % 3)) % 2 == 0;
651
+ case QRMaskPattern.PATTERN111:
652
+ return (((i * j) % 3) + ((i + j) % 2)) % 2 == 0;
653
+
654
+ default:
655
+ throw new Error("bad maskPattern:" + maskPattern);
656
+ }
657
+ },
658
+
659
+ getErrorCorrectPolynomial: function (errorCorrectLength) {
660
+ var a = new QRPolynomial([1], 0);
661
+
662
+ for (var i = 0; i < errorCorrectLength; i++) {
663
+ a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
664
+ }
665
+
666
+ return a;
667
+ },
668
+
669
+ getLengthInBits: function (mode, type) {
670
+ if (1 <= type && type < 10) {
671
+ // 1 - 9
672
+
673
+ switch (mode) {
674
+ case QRMode.MODE_NUMBER:
675
+ return 10;
676
+ case QRMode.MODE_ALPHA_NUM:
677
+ return 9;
678
+ case QRMode.MODE_8BIT_BYTE:
679
+ return 8;
680
+ case QRMode.MODE_KANJI:
681
+ return 8;
682
+ default:
683
+ throw new Error("mode:" + mode);
684
+ }
685
+ } else if (type < 27) {
686
+ // 10 - 26
687
+
688
+ switch (mode) {
689
+ case QRMode.MODE_NUMBER:
690
+ return 12;
691
+ case QRMode.MODE_ALPHA_NUM:
692
+ return 11;
693
+ case QRMode.MODE_8BIT_BYTE:
694
+ return 16;
695
+ case QRMode.MODE_KANJI:
696
+ return 10;
697
+ default:
698
+ throw new Error("mode:" + mode);
699
+ }
700
+ } else if (type < 41) {
701
+ // 27 - 40
702
+
703
+ switch (mode) {
704
+ case QRMode.MODE_NUMBER:
705
+ return 14;
706
+ case QRMode.MODE_ALPHA_NUM:
707
+ return 13;
708
+ case QRMode.MODE_8BIT_BYTE:
709
+ return 16;
710
+ case QRMode.MODE_KANJI:
711
+ return 12;
712
+ default:
713
+ throw new Error("mode:" + mode);
714
+ }
715
+ } else {
716
+ throw new Error("type:" + type);
717
+ }
718
+ },
719
+
720
+ getLostPoint: function (qrCode) {
721
+ var moduleCount = qrCode.getModuleCount();
722
+
723
+ var lostPoint = 0;
724
+
725
+ // LEVEL1
726
+
727
+ for (var row = 0; row < moduleCount; row++) {
728
+ for (var col = 0; col < moduleCount; col++) {
729
+ var sameCount = 0;
730
+ var dark = qrCode.isDark(row, col);
731
+
732
+ for (var r = -1; r <= 1; r++) {
733
+ if (row + r < 0 || moduleCount <= row + r) {
734
+ continue;
735
+ }
736
+
737
+ for (var c = -1; c <= 1; c++) {
738
+ if (col + c < 0 || moduleCount <= col + c) {
739
+ continue;
740
+ }
741
+
742
+ if (r == 0 && c == 0) {
743
+ continue;
744
+ }
745
+
746
+ if (dark == qrCode.isDark(row + r, col + c)) {
747
+ sameCount++;
748
+ }
749
+ }
750
+ }
751
+
752
+ if (sameCount > 5) {
753
+ lostPoint += 3 + sameCount - 5;
754
+ }
755
+ }
756
+ }
757
+
758
+ // LEVEL2
759
+
760
+ for (var row = 0; row < moduleCount - 1; row++) {
761
+ for (var col = 0; col < moduleCount - 1; col++) {
762
+ var count = 0;
763
+ if (qrCode.isDark(row, col)) count++;
764
+ if (qrCode.isDark(row + 1, col)) count++;
765
+ if (qrCode.isDark(row, col + 1)) count++;
766
+ if (qrCode.isDark(row + 1, col + 1)) count++;
767
+ if (count == 0 || count == 4) {
768
+ lostPoint += 3;
769
+ }
770
+ }
771
+ }
772
+
773
+ // LEVEL3
774
+
775
+ for (var row = 0; row < moduleCount; row++) {
776
+ for (var col = 0; col < moduleCount - 6; col++) {
777
+ if (
778
+ qrCode.isDark(row, col) &&
779
+ !qrCode.isDark(row, col + 1) &&
780
+ qrCode.isDark(row, col + 2) &&
781
+ qrCode.isDark(row, col + 3) &&
782
+ qrCode.isDark(row, col + 4) &&
783
+ !qrCode.isDark(row, col + 5) &&
784
+ qrCode.isDark(row, col + 6)
785
+ ) {
786
+ lostPoint += 40;
787
+ }
788
+ }
789
+ }
790
+
791
+ for (var col = 0; col < moduleCount; col++) {
792
+ for (var row = 0; row < moduleCount - 6; row++) {
793
+ if (
794
+ qrCode.isDark(row, col) &&
795
+ !qrCode.isDark(row + 1, col) &&
796
+ qrCode.isDark(row + 2, col) &&
797
+ qrCode.isDark(row + 3, col) &&
798
+ qrCode.isDark(row + 4, col) &&
799
+ !qrCode.isDark(row + 5, col) &&
800
+ qrCode.isDark(row + 6, col)
801
+ ) {
802
+ lostPoint += 40;
803
+ }
804
+ }
805
+ }
806
+
807
+ // LEVEL4
808
+
809
+ var darkCount = 0;
810
+
811
+ for (var col = 0; col < moduleCount; col++) {
812
+ for (var row = 0; row < moduleCount; row++) {
813
+ if (qrCode.isDark(row, col)) {
814
+ darkCount++;
815
+ }
816
+ }
817
+ }
818
+
819
+ var ratio =
820
+ Math.abs((100 * darkCount) / moduleCount / moduleCount - 50) / 5;
821
+ lostPoint += ratio * 10;
822
+
823
+ return lostPoint;
824
+ },
825
+ };
826
+
827
+ //---------------------------------------------------------------------
828
+ // QRMath
829
+ //---------------------------------------------------------------------
830
+
831
+ var QRMath = {
832
+ glog: function (n) {
833
+ if (n < 1) {
834
+ throw new Error("glog(" + n + ")");
835
+ }
836
+
837
+ return QRMath.LOG_TABLE[n];
838
+ },
839
+
840
+ gexp: function (n) {
841
+ while (n < 0) {
842
+ n += 255;
843
+ }
844
+
845
+ while (n >= 256) {
846
+ n -= 255;
847
+ }
848
+
849
+ return QRMath.EXP_TABLE[n];
850
+ },
851
+
852
+ EXP_TABLE: new Array(256),
853
+
854
+ LOG_TABLE: new Array(256),
855
+ };
856
+
857
+ for (var i = 0; i < 8; i++) {
858
+ QRMath.EXP_TABLE[i] = 1 << i;
859
+ }
860
+ for (var i = 8; i < 256; i++) {
861
+ QRMath.EXP_TABLE[i] =
862
+ QRMath.EXP_TABLE[i - 4] ^
863
+ QRMath.EXP_TABLE[i - 5] ^
864
+ QRMath.EXP_TABLE[i - 6] ^
865
+ QRMath.EXP_TABLE[i - 8];
866
+ }
867
+ for (var i = 0; i < 255; i++) {
868
+ QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
869
+ }
870
+
871
+ //---------------------------------------------------------------------
872
+ // QRPolynomial
873
+ //---------------------------------------------------------------------
874
+
875
+ function QRPolynomial(num, shift) {
876
+ if (num.length == undefined) {
877
+ throw new Error(num.length + "/" + shift);
878
+ }
879
+
880
+ var offset = 0;
881
+
882
+ while (offset < num.length && num[offset] == 0) {
883
+ offset++;
884
+ }
885
+
886
+ this.num = new Array(num.length - offset + shift);
887
+ for (var i = 0; i < num.length - offset; i++) {
888
+ this.num[i] = num[i + offset];
889
+ }
890
+ }
891
+
892
+ QRPolynomial.prototype = {
893
+ get: function (index) {
894
+ return this.num[index];
895
+ },
896
+
897
+ getLength: function () {
898
+ return this.num.length;
899
+ },
900
+
901
+ multiply: function (e) {
902
+ var num = new Array(this.getLength() + e.getLength() - 1);
903
+
904
+ for (var i = 0; i < this.getLength(); i++) {
905
+ for (var j = 0; j < e.getLength(); j++) {
906
+ num[i + j] ^= QRMath.gexp(
907
+ QRMath.glog(this.get(i)) + QRMath.glog(e.get(j))
908
+ );
909
+ }
910
+ }
911
+
912
+ return new QRPolynomial(num, 0);
913
+ },
914
+
915
+ mod: function (e) {
916
+ if (this.getLength() - e.getLength() < 0) {
917
+ return this;
918
+ }
919
+
920
+ var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
921
+
922
+ var num = new Array(this.getLength());
923
+
924
+ for (var i = 0; i < this.getLength(); i++) {
925
+ num[i] = this.get(i);
926
+ }
927
+
928
+ for (var i = 0; i < e.getLength(); i++) {
929
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
930
+ }
931
+
932
+ // recursive call
933
+ return new QRPolynomial(num, 0).mod(e);
934
+ },
935
+ };
936
+
937
+ //---------------------------------------------------------------------
938
+ // QRRSBlock
939
+ //---------------------------------------------------------------------
940
+
941
+ function QRRSBlock(totalCount, dataCount) {
942
+ this.totalCount = totalCount;
943
+ this.dataCount = dataCount;
944
+ }
945
+
946
+ QRRSBlock.RS_BLOCK_TABLE = [
947
+ // L
948
+ // M
949
+ // Q
950
+ // H
951
+
952
+ // 1
953
+ [1, 26, 19],
954
+ [1, 26, 16],
955
+ [1, 26, 13],
956
+ [1, 26, 9],
957
+
958
+ // 2
959
+ [1, 44, 34],
960
+ [1, 44, 28],
961
+ [1, 44, 22],
962
+ [1, 44, 16],
963
+
964
+ // 3
965
+ [1, 70, 55],
966
+ [1, 70, 44],
967
+ [2, 35, 17],
968
+ [2, 35, 13],
969
+
970
+ // 4
971
+ [1, 100, 80],
972
+ [2, 50, 32],
973
+ [2, 50, 24],
974
+ [4, 25, 9],
975
+
976
+ // 5
977
+ [1, 134, 108],
978
+ [2, 67, 43],
979
+ [2, 33, 15, 2, 34, 16],
980
+ [2, 33, 11, 2, 34, 12],
981
+
982
+ // 6
983
+ [2, 86, 68],
984
+ [4, 43, 27],
985
+ [4, 43, 19],
986
+ [4, 43, 15],
987
+
988
+ // 7
989
+ [2, 98, 78],
990
+ [4, 49, 31],
991
+ [2, 32, 14, 4, 33, 15],
992
+ [4, 39, 13, 1, 40, 14],
993
+
994
+ // 8
995
+ [2, 121, 97],
996
+ [2, 60, 38, 2, 61, 39],
997
+ [4, 40, 18, 2, 41, 19],
998
+ [4, 40, 14, 2, 41, 15],
999
+
1000
+ // 9
1001
+ [2, 146, 116],
1002
+ [3, 58, 36, 2, 59, 37],
1003
+ [4, 36, 16, 4, 37, 17],
1004
+ [4, 36, 12, 4, 37, 13],
1005
+
1006
+ // 10
1007
+ [2, 86, 68, 2, 87, 69],
1008
+ [4, 69, 43, 1, 70, 44],
1009
+ [6, 43, 19, 2, 44, 20],
1010
+ [6, 43, 15, 2, 44, 16],
1011
+
1012
+ // 11
1013
+ [4, 101, 81],
1014
+ [1, 80, 50, 4, 81, 51],
1015
+ [4, 50, 22, 4, 51, 23],
1016
+ [3, 36, 12, 8, 37, 13],
1017
+
1018
+ // 12
1019
+ [2, 116, 92, 2, 117, 93],
1020
+ [6, 58, 36, 2, 59, 37],
1021
+ [4, 46, 20, 6, 47, 21],
1022
+ [7, 42, 14, 4, 43, 15],
1023
+
1024
+ // 13
1025
+ [4, 133, 107],
1026
+ [8, 59, 37, 1, 60, 38],
1027
+ [8, 44, 20, 4, 45, 21],
1028
+ [12, 33, 11, 4, 34, 12],
1029
+
1030
+ // 14
1031
+ [3, 145, 115, 1, 146, 116],
1032
+ [4, 64, 40, 5, 65, 41],
1033
+ [11, 36, 16, 5, 37, 17],
1034
+ [11, 36, 12, 5, 37, 13],
1035
+
1036
+ // 15
1037
+ [5, 109, 87, 1, 110, 88],
1038
+ [5, 65, 41, 5, 66, 42],
1039
+ [5, 54, 24, 7, 55, 25],
1040
+ [11, 36, 12],
1041
+
1042
+ // 16
1043
+ [5, 122, 98, 1, 123, 99],
1044
+ [7, 73, 45, 3, 74, 46],
1045
+ [15, 43, 19, 2, 44, 20],
1046
+ [3, 45, 15, 13, 46, 16],
1047
+
1048
+ // 17
1049
+ [1, 135, 107, 5, 136, 108],
1050
+ [10, 74, 46, 1, 75, 47],
1051
+ [1, 50, 22, 15, 51, 23],
1052
+ [2, 42, 14, 17, 43, 15],
1053
+
1054
+ // 18
1055
+ [5, 150, 120, 1, 151, 121],
1056
+ [9, 69, 43, 4, 70, 44],
1057
+ [17, 50, 22, 1, 51, 23],
1058
+ [2, 42, 14, 19, 43, 15],
1059
+
1060
+ // 19
1061
+ [3, 141, 113, 4, 142, 114],
1062
+ [3, 70, 44, 11, 71, 45],
1063
+ [17, 47, 21, 4, 48, 22],
1064
+ [9, 39, 13, 16, 40, 14],
1065
+
1066
+ // 20
1067
+ [3, 135, 107, 5, 136, 108],
1068
+ [3, 67, 41, 13, 68, 42],
1069
+ [15, 54, 24, 5, 55, 25],
1070
+ [15, 43, 15, 10, 44, 16],
1071
+
1072
+ // 21
1073
+ [4, 144, 116, 4, 145, 117],
1074
+ [17, 68, 42],
1075
+ [17, 50, 22, 6, 51, 23],
1076
+ [19, 46, 16, 6, 47, 17],
1077
+
1078
+ // 22
1079
+ [2, 139, 111, 7, 140, 112],
1080
+ [17, 74, 46],
1081
+ [7, 54, 24, 16, 55, 25],
1082
+ [34, 37, 13],
1083
+
1084
+ // 23
1085
+ [4, 151, 121, 5, 152, 122],
1086
+ [4, 75, 47, 14, 76, 48],
1087
+ [11, 54, 24, 14, 55, 25],
1088
+ [16, 45, 15, 14, 46, 16],
1089
+
1090
+ // 24
1091
+ [6, 147, 117, 4, 148, 118],
1092
+ [6, 73, 45, 14, 74, 46],
1093
+ [11, 54, 24, 16, 55, 25],
1094
+ [30, 46, 16, 2, 47, 17],
1095
+
1096
+ // 25
1097
+ [8, 132, 106, 4, 133, 107],
1098
+ [8, 75, 47, 13, 76, 48],
1099
+ [7, 54, 24, 22, 55, 25],
1100
+ [22, 45, 15, 13, 46, 16],
1101
+
1102
+ // 26
1103
+ [10, 142, 114, 2, 143, 115],
1104
+ [19, 74, 46, 4, 75, 47],
1105
+ [28, 50, 22, 6, 51, 23],
1106
+ [33, 46, 16, 4, 47, 17],
1107
+
1108
+ // 27
1109
+ [8, 152, 122, 4, 153, 123],
1110
+ [22, 73, 45, 3, 74, 46],
1111
+ [8, 53, 23, 26, 54, 24],
1112
+ [12, 45, 15, 28, 46, 16],
1113
+
1114
+ // 28
1115
+ [3, 147, 117, 10, 148, 118],
1116
+ [3, 73, 45, 23, 74, 46],
1117
+ [4, 54, 24, 31, 55, 25],
1118
+ [11, 45, 15, 31, 46, 16],
1119
+
1120
+ // 29
1121
+ [7, 146, 116, 7, 147, 117],
1122
+ [21, 73, 45, 7, 74, 46],
1123
+ [1, 53, 23, 37, 54, 24],
1124
+ [19, 45, 15, 26, 46, 16],
1125
+
1126
+ // 30
1127
+ [5, 145, 115, 10, 146, 116],
1128
+ [19, 75, 47, 10, 76, 48],
1129
+ [15, 54, 24, 25, 55, 25],
1130
+ [23, 45, 15, 25, 46, 16],
1131
+
1132
+ // 31
1133
+ [13, 145, 115, 3, 146, 116],
1134
+ [2, 74, 46, 29, 75, 47],
1135
+ [42, 54, 24, 1, 55, 25],
1136
+ [23, 45, 15, 28, 46, 16],
1137
+
1138
+ // 32
1139
+ [17, 145, 115],
1140
+ [10, 74, 46, 23, 75, 47],
1141
+ [10, 54, 24, 35, 55, 25],
1142
+ [19, 45, 15, 35, 46, 16],
1143
+
1144
+ // 33
1145
+ [17, 145, 115, 1, 146, 116],
1146
+ [14, 74, 46, 21, 75, 47],
1147
+ [29, 54, 24, 19, 55, 25],
1148
+ [11, 45, 15, 46, 46, 16],
1149
+
1150
+ // 34
1151
+ [13, 145, 115, 6, 146, 116],
1152
+ [14, 74, 46, 23, 75, 47],
1153
+ [44, 54, 24, 7, 55, 25],
1154
+ [59, 46, 16, 1, 47, 17],
1155
+
1156
+ // 35
1157
+ [12, 151, 121, 7, 152, 122],
1158
+ [12, 75, 47, 26, 76, 48],
1159
+ [39, 54, 24, 14, 55, 25],
1160
+ [22, 45, 15, 41, 46, 16],
1161
+
1162
+ // 36
1163
+ [6, 151, 121, 14, 152, 122],
1164
+ [6, 75, 47, 34, 76, 48],
1165
+ [46, 54, 24, 10, 55, 25],
1166
+ [2, 45, 15, 64, 46, 16],
1167
+
1168
+ // 37
1169
+ [17, 152, 122, 4, 153, 123],
1170
+ [29, 74, 46, 14, 75, 47],
1171
+ [49, 54, 24, 10, 55, 25],
1172
+ [24, 45, 15, 46, 46, 16],
1173
+
1174
+ // 38
1175
+ [4, 152, 122, 18, 153, 123],
1176
+ [13, 74, 46, 32, 75, 47],
1177
+ [48, 54, 24, 14, 55, 25],
1178
+ [42, 45, 15, 32, 46, 16],
1179
+
1180
+ // 39
1181
+ [20, 147, 117, 4, 148, 118],
1182
+ [40, 75, 47, 7, 76, 48],
1183
+ [43, 54, 24, 22, 55, 25],
1184
+ [10, 45, 15, 67, 46, 16],
1185
+
1186
+ // 40
1187
+ [19, 148, 118, 6, 149, 119],
1188
+ [18, 75, 47, 31, 76, 48],
1189
+ [34, 54, 24, 34, 55, 25],
1190
+ [20, 45, 15, 61, 46, 16],
1191
+ ];
1192
+
1193
+ QRRSBlock.getRSBlocks = function (typeNumber, errorCorrectLevel) {
1194
+ var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
1195
+
1196
+ if (rsBlock == undefined) {
1197
+ throw new Error(
1198
+ "bad rs block @ typeNumber:" +
1199
+ typeNumber +
1200
+ "/errorCorrectLevel:" +
1201
+ errorCorrectLevel
1202
+ );
1203
+ }
1204
+
1205
+ var length = rsBlock.length / 3;
1206
+
1207
+ var list = [];
1208
+
1209
+ for (var i = 0; i < length; i++) {
1210
+ var count = rsBlock[i * 3 + 0];
1211
+ var totalCount = rsBlock[i * 3 + 1];
1212
+ var dataCount = rsBlock[i * 3 + 2];
1213
+
1214
+ for (var j = 0; j < count; j++) {
1215
+ list.push(new QRRSBlock(totalCount, dataCount));
1216
+ }
1217
+ }
1218
+
1219
+ return list;
1220
+ };
1221
+
1222
+ QRRSBlock.getRsBlockTable = function (typeNumber, errorCorrectLevel) {
1223
+ switch (errorCorrectLevel) {
1224
+ case QRErrorCorrectLevel.L:
1225
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
1226
+ case QRErrorCorrectLevel.M:
1227
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
1228
+ case QRErrorCorrectLevel.Q:
1229
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
1230
+ case QRErrorCorrectLevel.H:
1231
+ return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
1232
+ default:
1233
+ return undefined;
1234
+ }
1235
+ };
1236
+
1237
+ //---------------------------------------------------------------------
1238
+ // QRBitBuffer
1239
+ //---------------------------------------------------------------------
1240
+
1241
+ function QRBitBuffer() {
1242
+ this.buffer = [];
1243
+ this.length = 0;
1244
+ }
1245
+
1246
+ QRBitBuffer.prototype = {
1247
+ get: function (index) {
1248
+ var bufIndex = Math.floor(index / 8);
1249
+ return ((this.buffer[bufIndex] >>> (7 - (index % 8))) & 1) == 1;
1250
+ },
1251
+
1252
+ put: function (num, length) {
1253
+ for (var i = 0; i < length; i++) {
1254
+ this.putBit(((num >>> (length - i - 1)) & 1) == 1);
1255
+ }
1256
+ },
1257
+
1258
+ getLengthInBits: function () {
1259
+ return this.length;
1260
+ },
1261
+
1262
+ putBit: function (bit) {
1263
+ var bufIndex = Math.floor(this.length / 8);
1264
+ if (this.buffer.length <= bufIndex) {
1265
+ this.buffer.push(0);
1266
+ }
1267
+
1268
+ if (bit) {
1269
+ this.buffer[bufIndex] |= 0x80 >>> this.length % 8;
1270
+ }
1271
+
1272
+ this.length++;
1273
+ },
1274
+ };
1275
+
1276
+ var QRCodeLimitLength = [
1277
+ [17, 14, 11, 7],
1278
+ [32, 26, 20, 14],
1279
+ [53, 42, 32, 24],
1280
+ [78, 62, 46, 34],
1281
+ [106, 84, 60, 44],
1282
+ [134, 106, 74, 58],
1283
+ [154, 122, 86, 64],
1284
+ [192, 152, 108, 84],
1285
+ [230, 180, 130, 98],
1286
+ [271, 213, 151, 119],
1287
+ [321, 251, 177, 137],
1288
+ [367, 287, 203, 155],
1289
+ [425, 331, 241, 177],
1290
+ [458, 362, 258, 194],
1291
+ [520, 412, 292, 220],
1292
+ [586, 450, 322, 250],
1293
+ [644, 504, 364, 280],
1294
+ [718, 560, 394, 310],
1295
+ [792, 624, 442, 338],
1296
+ [858, 666, 482, 382],
1297
+ [929, 711, 509, 403],
1298
+ [1003, 779, 565, 439],
1299
+ [1091, 857, 611, 461],
1300
+ [1171, 911, 661, 511],
1301
+ [1273, 997, 715, 535],
1302
+ [1367, 1059, 751, 593],
1303
+ [1465, 1125, 805, 625],
1304
+ [1528, 1190, 868, 658],
1305
+ [1628, 1264, 908, 698],
1306
+ [1732, 1370, 982, 742],
1307
+ [1840, 1452, 1030, 790],
1308
+ [1952, 1538, 1112, 842],
1309
+ [2068, 1628, 1168, 898],
1310
+ [2188, 1722, 1228, 958],
1311
+ [2303, 1809, 1283, 983],
1312
+ [2431, 1911, 1351, 1051],
1313
+ [2563, 1989, 1423, 1093],
1314
+ [2699, 2099, 1499, 1139],
1315
+ [2809, 2213, 1579, 1219],
1316
+ [2953, 2331, 1663, 1273],
1317
+ ];
1318
+
1319
+ /** Constructor */
1320
+ function QRCode(options) {
1321
+ var instance = this;
1322
+
1323
+ //Default options
1324
+ this.options = {
1325
+ padding: 4,
1326
+ width: 256,
1327
+ height: 256,
1328
+ typeNumber: 4,
1329
+ color: "#000000",
1330
+ background: "#ffffff",
1331
+ ecl: "M",
1332
+ };
1333
+
1334
+ //In case the options is string
1335
+ if (typeof options === "string") {
1336
+ options = {
1337
+ content: options,
1338
+ };
1339
+ }
1340
+
1341
+ //Merge options
1342
+ if (options) {
1343
+ for (var i in options) {
1344
+ this.options[i] = options[i];
1345
+ }
1346
+ }
1347
+
1348
+ if (typeof this.options.content !== "string") {
1349
+ throw new Error("Expected 'content' as string!");
1350
+ }
1351
+
1352
+ if (
1353
+ this.options.content.length ===
1354
+ 0 /* || this.options.content.length > 7089 */
1355
+ ) {
1356
+ throw new Error("Expected 'content' to be non-empty!");
1357
+ }
1358
+
1359
+ if (!(this.options.padding >= 0)) {
1360
+ throw new Error("Expected 'padding' value to be non-negative!");
1361
+ }
1362
+
1363
+ if (!(this.options.width > 0) || !(this.options.height > 0)) {
1364
+ throw new Error(
1365
+ "Expected 'width' or 'height' value to be higher than zero!"
1366
+ );
1367
+ }
1368
+
1369
+ //Gets the error correction level
1370
+ function _getErrorCorrectLevel(ecl) {
1371
+ switch (ecl) {
1372
+ case "L":
1373
+ return QRErrorCorrectLevel.L;
1374
+
1375
+ case "M":
1376
+ return QRErrorCorrectLevel.M;
1377
+
1378
+ case "Q":
1379
+ return QRErrorCorrectLevel.Q;
1380
+
1381
+ case "H":
1382
+ return QRErrorCorrectLevel.H;
1383
+
1384
+ default:
1385
+ throw new Error("Unknwon error correction level: " + ecl);
1386
+ }
1387
+ }
1388
+
1389
+ //Get type number
1390
+ function _getTypeNumber(content, ecl) {
1391
+ var length = _getUTF8Length(content);
1392
+
1393
+ var type = 1;
1394
+ var limit = 0;
1395
+ for (var i = 0, len = QRCodeLimitLength.length; i <= len; i++) {
1396
+ var table = QRCodeLimitLength[i];
1397
+ if (!table) {
1398
+ throw new Error(
1399
+ "Content too long: expected " + limit + " but got " + length
1400
+ );
1401
+ }
1402
+
1403
+ switch (ecl) {
1404
+ case "L":
1405
+ limit = table[0];
1406
+ break;
1407
+
1408
+ case "M":
1409
+ limit = table[1];
1410
+ break;
1411
+
1412
+ case "Q":
1413
+ limit = table[2];
1414
+ break;
1415
+
1416
+ case "H":
1417
+ limit = table[3];
1418
+ break;
1419
+
1420
+ default:
1421
+ throw new Error("Unknwon error correction level: " + ecl);
1422
+ }
1423
+
1424
+ if (length <= limit) {
1425
+ break;
1426
+ }
1427
+
1428
+ type++;
1429
+ }
1430
+
1431
+ if (type > QRCodeLimitLength.length) {
1432
+ throw new Error("Content too long");
1433
+ }
1434
+
1435
+ return type;
1436
+ }
1437
+
1438
+ //Gets text length
1439
+ function _getUTF8Length(content) {
1440
+ var result = encodeURI(content)
1441
+ .toString()
1442
+ .replace(/\%[0-9a-fA-F]{2}/g, "a");
1443
+ return result.length + (result.length != content ? 3 : 0);
1444
+ }
1445
+
1446
+ //Generate QR Code matrix
1447
+ var content = this.options.content;
1448
+ var type = _getTypeNumber(content, this.options.ecl);
1449
+ var ecl = _getErrorCorrectLevel(this.options.ecl);
1450
+ this.qrcode = new QRCodeModel(type, ecl);
1451
+ this.qrcode.addData(content);
1452
+ this.qrcode.make();
1453
+ }
1454
+
1455
+ /** Generates QR Code as SVG image */
1456
+ QRCode.prototype.svg = function (opt) {
1457
+ var options = this.options || {};
1458
+ var modules = this.qrcode.modules;
1459
+
1460
+ if (typeof opt == "undefined") {
1461
+ opt = { container: options.container || "svg" };
1462
+ }
1463
+
1464
+ //Apply new lines and indents in SVG?
1465
+ var pretty = typeof options.pretty != "undefined" ? !!options.pretty : true;
1466
+
1467
+ var indent = pretty ? " " : "";
1468
+ var EOL = pretty ? "\r\n" : "";
1469
+ var width = options.width;
1470
+ var height = options.height;
1471
+ var length = modules.length;
1472
+ var xsize = width / (length + 2 * options.padding);
1473
+ var ysize = height / (length + 2 * options.padding);
1474
+
1475
+ //Join (union, merge) rectangles into one shape?
1476
+ var join =
1477
+ opt.container == "path-data" ||
1478
+ (typeof options.join != "undefined" ? !!options.join : false);
1479
+
1480
+ //Swap the X and Y modules, pull request #2
1481
+ var swap = typeof options.swap != "undefined" ? !!options.swap : false;
1482
+
1483
+ //Apply <?xml...?> declaration in SVG?
1484
+ var xmlDeclaration =
1485
+ typeof options.xmlDeclaration != "undefined"
1486
+ ? !!options.xmlDeclaration
1487
+ : true;
1488
+
1489
+ //Populate with predefined shape instead of "rect" elements, thanks to @kkocdko
1490
+ var predefined =
1491
+ typeof options.predefined != "undefined" ? !!options.predefined : false;
1492
+ var defs = predefined
1493
+ ? indent +
1494
+ '<defs><path id="qrmodule" d="M0 0 h' +
1495
+ ysize +
1496
+ " v" +
1497
+ xsize +
1498
+ ' H0 z" style="fill:' +
1499
+ options.color +
1500
+ ';shape-rendering:crispEdges;" /></defs>' +
1501
+ EOL
1502
+ : "";
1503
+
1504
+ //Background rectangle
1505
+ var bgrect =
1506
+ indent +
1507
+ '<rect x="0" y="0" width="' +
1508
+ width +
1509
+ '" height="' +
1510
+ height +
1511
+ '" style="fill:' +
1512
+ options.background +
1513
+ ';shape-rendering:crispEdges;"/>' +
1514
+ EOL;
1515
+
1516
+ //Rectangles representing modules
1517
+ var modrect = "";
1518
+ var pathdata = "";
1519
+
1520
+ for (var y = 0; y < length; y++) {
1521
+ for (var x = 0; x < length; x++) {
1522
+ var module = modules[x][y];
1523
+ if (module) {
1524
+ var px = x * xsize + options.padding * xsize;
1525
+ var py = y * ysize + options.padding * ysize;
1526
+
1527
+ //Some users have had issues with the QR Code, thanks to @danioso for the solution
1528
+ if (swap) {
1529
+ var t = px;
1530
+ px = py;
1531
+ py = t;
1532
+ }
1533
+
1534
+ if (join) {
1535
+ //Module as a part of svg path data, thanks to @danioso
1536
+ var w = xsize + px;
1537
+ var h = ysize + py;
1538
+
1539
+ px = Number.isInteger(px) ? Number(px) : px.toFixed(2);
1540
+ py = Number.isInteger(py) ? Number(py) : py.toFixed(2);
1541
+ w = Number.isInteger(w) ? Number(w) : w.toFixed(2);
1542
+ h = Number.isInteger(h) ? Number(h) : h.toFixed(2);
1543
+
1544
+ pathdata +=
1545
+ "M" +
1546
+ px +
1547
+ "," +
1548
+ py +
1549
+ " V" +
1550
+ h +
1551
+ " H" +
1552
+ w +
1553
+ " V" +
1554
+ py +
1555
+ " H" +
1556
+ px +
1557
+ " Z ";
1558
+ } else if (predefined) {
1559
+ //Module as a predefined shape, thanks to @kkocdko
1560
+ modrect +=
1561
+ indent +
1562
+ '<use x="' +
1563
+ px.toString() +
1564
+ '" y="' +
1565
+ py.toString() +
1566
+ '" href="#qrmodule" />' +
1567
+ EOL;
1568
+ } else {
1569
+ //Module as rectangle element
1570
+ modrect +=
1571
+ indent +
1572
+ '<rect x="' +
1573
+ px.toString() +
1574
+ '" y="' +
1575
+ py.toString() +
1576
+ '" width="' +
1577
+ xsize +
1578
+ '" height="' +
1579
+ ysize +
1580
+ '" style="fill:' +
1581
+ options.color +
1582
+ ';shape-rendering:crispEdges;"/>' +
1583
+ EOL;
1584
+ }
1585
+ }
1586
+ }
1587
+ }
1588
+
1589
+ if (join) {
1590
+ modrect =
1591
+ indent +
1592
+ '<path x="0" y="0" style="fill:' +
1593
+ options.color +
1594
+ ';shape-rendering:crispEdges;" d="' +
1595
+ pathdata +
1596
+ '" />';
1597
+ }
1598
+
1599
+ var svg = "";
1600
+ switch (opt.container) {
1601
+ //Wrapped in SVG document
1602
+ case "svg":
1603
+ if (xmlDeclaration) {
1604
+ svg += '<?xml version="1.0" standalone="yes"?>' + EOL;
1605
+ }
1606
+ svg +=
1607
+ '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="' +
1608
+ width +
1609
+ '" height="' +
1610
+ height +
1611
+ '">' +
1612
+ EOL;
1613
+ svg += defs + bgrect + modrect;
1614
+ svg += "</svg>";
1615
+ break;
1616
+
1617
+ //Viewbox for responsive use in a browser, thanks to @danioso
1618
+ case "svg-viewbox":
1619
+ if (xmlDeclaration) {
1620
+ svg += '<?xml version="1.0" standalone="yes"?>' + EOL;
1621
+ }
1622
+ svg +=
1623
+ '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 ' +
1624
+ width +
1625
+ " " +
1626
+ height +
1627
+ '">' +
1628
+ EOL;
1629
+ svg += defs + bgrect + modrect;
1630
+ svg += "</svg>";
1631
+ break;
1632
+
1633
+ //Wrapped in group element
1634
+ case "g":
1635
+ svg += '<g width="' + width + '" height="' + height + '">' + EOL;
1636
+ svg += defs + bgrect + modrect;
1637
+ svg += "</g>";
1638
+ break;
1639
+
1640
+ //SVG path data only
1641
+ case "path-data":
1642
+ svg = pathdata;
1643
+ break;
1644
+
1645
+ //Without a container
1646
+ default: //Clear indents on each line
1647
+ svg += (defs + bgrect + modrect).replace(/^\s+/, "");
1648
+ break;
1649
+ }
1650
+
1651
+ return svg;
1652
+ };
1653
+
1654
+ /** Writes QR Code image to a file */
1655
+ QRCode.prototype.save = function (file, callback) {
1656
+ var data = this.svg();
1657
+ if (typeof callback != "function") {
1658
+ callback = function (error, result) {};
1659
+ }
1660
+ try {
1661
+ //Package 'fs' is available in node.js but not in a web browser
1662
+ var fs = require("fs");
1663
+ fs.writeFile(file, data, callback);
1664
+ } catch (e) {
1665
+ //Sorry, 'fs' is not available
1666
+ callback(e);
1667
+ }
1668
+ };
1669
+
1670
+ if (typeof module != "undefined") {
1671
+ module.exports = QRCode;
1672
+ }