uview-plus 3.1.49 → 3.1.51

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.
@@ -0,0 +1,1206 @@
1
+ let QRCode = {};
2
+ (function () {
3
+ /**
4
+ * 获取单个字符的utf8编码
5
+ * unicode BMP平面约65535个字符
6
+ * @param {num} code
7
+ * return {array}
8
+ */
9
+ function unicodeFormat8(code) {
10
+ // 1 byte
11
+ var c0, c1, c2;
12
+ if (code < 128) {
13
+ return [code];
14
+ // 2 bytes
15
+ } else if (code < 2048) {
16
+ c0 = 192 + (code >> 6);
17
+ c1 = 128 + (code & 63);
18
+ return [c0, c1];
19
+ // 3 bytes
20
+ } else {
21
+ c0 = 224 + (code >> 12);
22
+ c1 = 128 + (code >> 6 & 63);
23
+ c2 = 128 + (code & 63);
24
+ return [c0, c1, c2];
25
+ }
26
+ }
27
+ /**
28
+ * 获取字符串的utf8编码字节串
29
+ * @param {string} string
30
+ * @return {array}
31
+ */
32
+ function getUTF8Bytes(string) {
33
+ var utf8codes = [];
34
+ for (var i = 0; i < string.length; i++) {
35
+ var code = string.charCodeAt(i);
36
+ var utf8 = unicodeFormat8(code);
37
+ for (var j = 0; j < utf8.length; j++) {
38
+ utf8codes.push(utf8[j]);
39
+ }
40
+ }
41
+ return utf8codes;
42
+ }
43
+ /**
44
+ * 二维码算法实现
45
+ * @param {string} data 要编码的信息字符串
46
+ * @param {num} errorCorrectLevel 纠错等级
47
+ */
48
+ function QRCodeAlg(data, errorCorrectLevel) {
49
+ this.typeNumber = -1; //版本
50
+ this.errorCorrectLevel = errorCorrectLevel;
51
+ this.modules = null; //二维矩阵,存放最终结果
52
+ this.moduleCount = 0; //矩阵大小
53
+ this.dataCache = null; //数据缓存
54
+ this.rsBlocks = null; //版本数据信息
55
+ this.totalDataCount = -1; //可使用的数据量
56
+ this.data = data;
57
+ this.utf8bytes = getUTF8Bytes(data);
58
+ this.make();
59
+ }
60
+ QRCodeAlg.prototype = {
61
+ constructor: QRCodeAlg,
62
+ /**
63
+ * 获取二维码矩阵大小
64
+ * @return {num} 矩阵大小
65
+ */
66
+ getModuleCount: function () {
67
+ return this.moduleCount;
68
+ },
69
+ /**
70
+ * 编码
71
+ */
72
+ make: function () {
73
+ this.getRightType();
74
+ this.dataCache = this.createData();
75
+ this.createQrcode();
76
+ },
77
+ /**
78
+ * 设置二位矩阵功能图形
79
+ * @param {bool} test 表示是否在寻找最好掩膜阶段
80
+ * @param {num} maskPattern 掩膜的版本
81
+ */
82
+ makeImpl: function (maskPattern) {
83
+ this.moduleCount = this.typeNumber * 4 + 17;
84
+ this.modules = new Array(this.moduleCount);
85
+ for (var row = 0; row < this.moduleCount; row++) {
86
+ this.modules[row] = new Array(this.moduleCount);
87
+ }
88
+ this.setupPositionProbePattern(0, 0);
89
+ this.setupPositionProbePattern(this.moduleCount - 7, 0);
90
+ this.setupPositionProbePattern(0, this.moduleCount - 7);
91
+ this.setupPositionAdjustPattern();
92
+ this.setupTimingPattern();
93
+ this.setupTypeInfo(true, maskPattern);
94
+ if (this.typeNumber >= 7) {
95
+ this.setupTypeNumber(true);
96
+ }
97
+ this.mapData(this.dataCache, maskPattern);
98
+ },
99
+ /**
100
+ * 设置二维码的位置探测图形
101
+ * @param {num} row 探测图形的中心横坐标
102
+ * @param {num} col 探测图形的中心纵坐标
103
+ */
104
+ setupPositionProbePattern: function (row, col) {
105
+ for (var r = -1; r <= 7; r++) {
106
+ if (row + r <= -1 || this.moduleCount <= row + r) continue;
107
+ for (var c = -1; c <= 7; c++) {
108
+ if (col + c <= -1 || this.moduleCount <= col + c) continue;
109
+ if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {
110
+ this.modules[row + r][col + c] = true;
111
+ } else {
112
+ this.modules[row + r][col + c] = false;
113
+ }
114
+ }
115
+ }
116
+ },
117
+ /**
118
+ * 创建二维码
119
+ * @return {[type]} [description]
120
+ */
121
+ createQrcode: function () {
122
+ var minLostPoint = 0;
123
+ var pattern = 0;
124
+ var bestModules = null;
125
+ for (var i = 0; i < 8; i++) {
126
+ this.makeImpl(i);
127
+ var lostPoint = QRUtil.getLostPoint(this);
128
+ if (i == 0 || minLostPoint > lostPoint) {
129
+ minLostPoint = lostPoint;
130
+ pattern = i;
131
+ bestModules = this.modules;
132
+ }
133
+ }
134
+ this.modules = bestModules;
135
+ this.setupTypeInfo(false, pattern);
136
+ if (this.typeNumber >= 7) {
137
+ this.setupTypeNumber(false);
138
+ }
139
+ },
140
+ /**
141
+ * 设置定位图形
142
+ * @return {[type]} [description]
143
+ */
144
+ setupTimingPattern: function () {
145
+ for (var r = 8; r < this.moduleCount - 8; r++) {
146
+ if (this.modules[r][6] != null) {
147
+ continue;
148
+ }
149
+ this.modules[r][6] = (r % 2 == 0);
150
+ if (this.modules[6][r] != null) {
151
+ continue;
152
+ }
153
+ this.modules[6][r] = (r % 2 == 0);
154
+ }
155
+ },
156
+ /**
157
+ * 设置矫正图形
158
+ * @return {[type]} [description]
159
+ */
160
+ setupPositionAdjustPattern: function () {
161
+ var pos = QRUtil.getPatternPosition(this.typeNumber);
162
+ for (var i = 0; i < pos.length; i++) {
163
+ for (var j = 0; j < pos.length; j++) {
164
+ var row = pos[i];
165
+ var col = pos[j];
166
+ if (this.modules[row][col] != null) {
167
+ continue;
168
+ }
169
+ for (var r = -2; r <= 2; r++) {
170
+ for (var c = -2; c <= 2; c++) {
171
+ if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) {
172
+ this.modules[row + r][col + c] = true;
173
+ } else {
174
+ this.modules[row + r][col + c] = false;
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+ },
181
+ /**
182
+ * 设置版本信息(7以上版本才有)
183
+ * @param {bool} test 是否处于判断最佳掩膜阶段
184
+ * @return {[type]} [description]
185
+ */
186
+ setupTypeNumber: function (test) {
187
+ var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
188
+ for (var i = 0; i < 18; i++) {
189
+ var mod = (!test && ((bits >> i) & 1) == 1);
190
+ this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
191
+ this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
192
+ }
193
+ },
194
+ /**
195
+ * 设置格式信息(纠错等级和掩膜版本)
196
+ * @param {bool} test
197
+ * @param {num} maskPattern 掩膜版本
198
+ * @return {}
199
+ */
200
+ setupTypeInfo: function (test, maskPattern) {
201
+ var data = (QRErrorCorrectLevel[this.errorCorrectLevel] << 3) | maskPattern;
202
+ var bits = QRUtil.getBCHTypeInfo(data);
203
+ // vertical
204
+ for (var i = 0; i < 15; i++) {
205
+ var mod = (!test && ((bits >> i) & 1) == 1);
206
+ if (i < 6) {
207
+ this.modules[i][8] = mod;
208
+ } else if (i < 8) {
209
+ this.modules[i + 1][8] = mod;
210
+ } else {
211
+ this.modules[this.moduleCount - 15 + i][8] = mod;
212
+ }
213
+ // horizontal
214
+ var mod = (!test && ((bits >> i) & 1) == 1);
215
+ if (i < 8) {
216
+ this.modules[8][this.moduleCount - i - 1] = mod;
217
+ } else if (i < 9) {
218
+ this.modules[8][15 - i - 1 + 1] = mod;
219
+ } else {
220
+ this.modules[8][15 - i - 1] = mod;
221
+ }
222
+ }
223
+ // fixed module
224
+ this.modules[this.moduleCount - 8][8] = (!test);
225
+ },
226
+ /**
227
+ * 数据编码
228
+ * @return {[type]} [description]
229
+ */
230
+ createData: function () {
231
+ var buffer = new QRBitBuffer();
232
+ var lengthBits = this.typeNumber > 9 ? 16 : 8;
233
+ buffer.put(4, 4); //添加模式
234
+ buffer.put(this.utf8bytes.length, lengthBits);
235
+ for (var i = 0, l = this.utf8bytes.length; i < l; i++) {
236
+ buffer.put(this.utf8bytes[i], 8);
237
+ }
238
+ if (buffer.length + 4 <= this.totalDataCount * 8) {
239
+ buffer.put(0, 4);
240
+ }
241
+ // padding
242
+ while (buffer.length % 8 != 0) {
243
+ buffer.putBit(false);
244
+ }
245
+ // padding
246
+ while (true) {
247
+ if (buffer.length >= this.totalDataCount * 8) {
248
+ break;
249
+ }
250
+ buffer.put(QRCodeAlg.PAD0, 8);
251
+ if (buffer.length >= this.totalDataCount * 8) {
252
+ break;
253
+ }
254
+ buffer.put(QRCodeAlg.PAD1, 8);
255
+ }
256
+ return this.createBytes(buffer);
257
+ },
258
+ /**
259
+ * 纠错码编码
260
+ * @param {buffer} buffer 数据编码
261
+ * @return {[type]}
262
+ */
263
+ createBytes: function (buffer) {
264
+ var offset = 0;
265
+ var maxDcCount = 0;
266
+ var maxEcCount = 0;
267
+ var length = this.rsBlock.length / 3;
268
+ var rsBlocks = new Array();
269
+ for (var i = 0; i < length; i++) {
270
+ var count = this.rsBlock[i * 3 + 0];
271
+ var totalCount = this.rsBlock[i * 3 + 1];
272
+ var dataCount = this.rsBlock[i * 3 + 2];
273
+ for (var j = 0; j < count; j++) {
274
+ rsBlocks.push([dataCount, totalCount]);
275
+ }
276
+ }
277
+ var dcdata = new Array(rsBlocks.length);
278
+ var ecdata = new Array(rsBlocks.length);
279
+ for (var r = 0; r < rsBlocks.length; r++) {
280
+ var dcCount = rsBlocks[r][0];
281
+ var ecCount = rsBlocks[r][1] - dcCount;
282
+ maxDcCount = Math.max(maxDcCount, dcCount);
283
+ maxEcCount = Math.max(maxEcCount, ecCount);
284
+ dcdata[r] = new Array(dcCount);
285
+ for (var i = 0; i < dcdata[r].length; i++) {
286
+ dcdata[r][i] = 0xff & buffer.buffer[i + offset];
287
+ }
288
+ offset += dcCount;
289
+ var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
290
+ var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
291
+ var modPoly = rawPoly.mod(rsPoly);
292
+ ecdata[r] = new Array(rsPoly.getLength() - 1);
293
+ for (var i = 0; i < ecdata[r].length; i++) {
294
+ var modIndex = i + modPoly.getLength() - ecdata[r].length;
295
+ ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0;
296
+ }
297
+ }
298
+ var data = new Array(this.totalDataCount);
299
+ var index = 0;
300
+ for (var i = 0; i < maxDcCount; i++) {
301
+ for (var r = 0; r < rsBlocks.length; r++) {
302
+ if (i < dcdata[r].length) {
303
+ data[index++] = dcdata[r][i];
304
+ }
305
+ }
306
+ }
307
+ for (var i = 0; i < maxEcCount; i++) {
308
+ for (var r = 0; r < rsBlocks.length; r++) {
309
+ if (i < ecdata[r].length) {
310
+ data[index++] = ecdata[r][i];
311
+ }
312
+ }
313
+ }
314
+ return data;
315
+
316
+ },
317
+ /**
318
+ * 布置模块,构建最终信息
319
+ * @param {} data
320
+ * @param {} maskPattern
321
+ * @return {}
322
+ */
323
+ mapData: function (data, maskPattern) {
324
+ var inc = -1;
325
+ var row = this.moduleCount - 1;
326
+ var bitIndex = 7;
327
+ var byteIndex = 0;
328
+ for (var col = this.moduleCount - 1; col > 0; col -= 2) {
329
+ if (col == 6) col--;
330
+ while (true) {
331
+ for (var c = 0; c < 2; c++) {
332
+ if (this.modules[row][col - c] == null) {
333
+ var dark = false;
334
+ if (byteIndex < data.length) {
335
+ dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
336
+ }
337
+ var mask = QRUtil.getMask(maskPattern, row, col - c);
338
+ if (mask) {
339
+ dark = !dark;
340
+ }
341
+ this.modules[row][col - c] = dark;
342
+ bitIndex--;
343
+ if (bitIndex == -1) {
344
+ byteIndex++;
345
+ bitIndex = 7;
346
+ }
347
+ }
348
+ }
349
+ row += inc;
350
+ if (row < 0 || this.moduleCount <= row) {
351
+ row -= inc;
352
+ inc = -inc;
353
+ break;
354
+ }
355
+ }
356
+ }
357
+ }
358
+ };
359
+ /**
360
+ * 填充字段
361
+ */
362
+ QRCodeAlg.PAD0 = 0xEC;
363
+ QRCodeAlg.PAD1 = 0x11;
364
+ //---------------------------------------------------------------------
365
+ // 纠错等级对应的编码
366
+ //---------------------------------------------------------------------
367
+ var QRErrorCorrectLevel = [1, 0, 3, 2];
368
+ //---------------------------------------------------------------------
369
+ // 掩膜版本
370
+ //---------------------------------------------------------------------
371
+ var QRMaskPattern = {
372
+ PATTERN000: 0,
373
+ PATTERN001: 1,
374
+ PATTERN010: 2,
375
+ PATTERN011: 3,
376
+ PATTERN100: 4,
377
+ PATTERN101: 5,
378
+ PATTERN110: 6,
379
+ PATTERN111: 7
380
+ };
381
+ //---------------------------------------------------------------------
382
+ // 工具类
383
+ //---------------------------------------------------------------------
384
+ var QRUtil = {
385
+ /*
386
+ 每个版本矫正图形的位置
387
+ */
388
+ PATTERN_POSITION_TABLE: [
389
+ [],
390
+ [6, 18],
391
+ [6, 22],
392
+ [6, 26],
393
+ [6, 30],
394
+ [6, 34],
395
+ [6, 22, 38],
396
+ [6, 24, 42],
397
+ [6, 26, 46],
398
+ [6, 28, 50],
399
+ [6, 30, 54],
400
+ [6, 32, 58],
401
+ [6, 34, 62],
402
+ [6, 26, 46, 66],
403
+ [6, 26, 48, 70],
404
+ [6, 26, 50, 74],
405
+ [6, 30, 54, 78],
406
+ [6, 30, 56, 82],
407
+ [6, 30, 58, 86],
408
+ [6, 34, 62, 90],
409
+ [6, 28, 50, 72, 94],
410
+ [6, 26, 50, 74, 98],
411
+ [6, 30, 54, 78, 102],
412
+ [6, 28, 54, 80, 106],
413
+ [6, 32, 58, 84, 110],
414
+ [6, 30, 58, 86, 114],
415
+ [6, 34, 62, 90, 118],
416
+ [6, 26, 50, 74, 98, 122],
417
+ [6, 30, 54, 78, 102, 126],
418
+ [6, 26, 52, 78, 104, 130],
419
+ [6, 30, 56, 82, 108, 134],
420
+ [6, 34, 60, 86, 112, 138],
421
+ [6, 30, 58, 86, 114, 142],
422
+ [6, 34, 62, 90, 118, 146],
423
+ [6, 30, 54, 78, 102, 126, 150],
424
+ [6, 24, 50, 76, 102, 128, 154],
425
+ [6, 28, 54, 80, 106, 132, 158],
426
+ [6, 32, 58, 84, 110, 136, 162],
427
+ [6, 26, 54, 82, 110, 138, 166],
428
+ [6, 30, 58, 86, 114, 142, 170]
429
+ ],
430
+ G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0),
431
+ G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0),
432
+ G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1),
433
+ /*
434
+ BCH编码格式信息
435
+ */
436
+ getBCHTypeInfo: function (data) {
437
+ var d = data << 10;
438
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
439
+ d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15)));
440
+ }
441
+ return ((data << 10) | d) ^ QRUtil.G15_MASK;
442
+ },
443
+ /*
444
+ BCH编码版本信息
445
+ */
446
+ getBCHTypeNumber: function (data) {
447
+ var d = data << 12;
448
+ while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
449
+ d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18)));
450
+ }
451
+ return (data << 12) | d;
452
+ },
453
+ /*
454
+ 获取BCH位信息
455
+ */
456
+ getBCHDigit: function (data) {
457
+ var digit = 0;
458
+ while (data != 0) {
459
+ digit++;
460
+ data >>>= 1;
461
+ }
462
+ return digit;
463
+ },
464
+ /*
465
+ 获取版本对应的矫正图形位置
466
+ */
467
+ getPatternPosition: function (typeNumber) {
468
+ return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
469
+ },
470
+ /*
471
+ 掩膜算法
472
+ */
473
+ getMask: function (maskPattern, i, j) {
474
+ switch (maskPattern) {
475
+ case QRMaskPattern.PATTERN000:
476
+ return (i + j) % 2 == 0;
477
+ case QRMaskPattern.PATTERN001:
478
+ return i % 2 == 0;
479
+ case QRMaskPattern.PATTERN010:
480
+ return j % 3 == 0;
481
+ case QRMaskPattern.PATTERN011:
482
+ return (i + j) % 3 == 0;
483
+ case QRMaskPattern.PATTERN100:
484
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
485
+ case QRMaskPattern.PATTERN101:
486
+ return (i * j) % 2 + (i * j) % 3 == 0;
487
+ case QRMaskPattern.PATTERN110:
488
+ return ((i * j) % 2 + (i * j) % 3) % 2 == 0;
489
+ case QRMaskPattern.PATTERN111:
490
+ return ((i * j) % 3 + (i + j) % 2) % 2 == 0;
491
+ default:
492
+ throw new Error("bad maskPattern:" + maskPattern);
493
+ }
494
+ },
495
+ /*
496
+ 获取RS的纠错多项式
497
+ */
498
+ getErrorCorrectPolynomial: function (errorCorrectLength) {
499
+ var a = new QRPolynomial([1], 0);
500
+ for (var i = 0; i < errorCorrectLength; i++) {
501
+ a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
502
+ }
503
+ return a;
504
+ },
505
+ /*
506
+ 获取评价
507
+ */
508
+ getLostPoint: function (qrCode) {
509
+ var moduleCount = qrCode.getModuleCount(),
510
+ lostPoint = 0,
511
+ darkCount = 0;
512
+ for (var row = 0; row < moduleCount; row++) {
513
+ var sameCount = 0;
514
+ var head = qrCode.modules[row][0];
515
+ for (var col = 0; col < moduleCount; col++) {
516
+ var current = qrCode.modules[row][col];
517
+ //level 3 评价
518
+ if (col < moduleCount - 6) {
519
+ if (current && !qrCode.modules[row][col + 1] && qrCode.modules[row][col + 2] && qrCode.modules[row][col + 3] && qrCode.modules[row][col + 4] && !qrCode.modules[row][col + 5] && qrCode.modules[row][col + 6]) {
520
+ if (col < moduleCount - 10) {
521
+ if (qrCode.modules[row][col + 7] && qrCode.modules[row][col + 8] && qrCode.modules[row][col + 9] && qrCode.modules[row][col + 10]) {
522
+ lostPoint += 40;
523
+ }
524
+ } else if (col > 3) {
525
+ if (qrCode.modules[row][col - 1] && qrCode.modules[row][col - 2] && qrCode.modules[row][col - 3] && qrCode.modules[row][col - 4]) {
526
+ lostPoint += 40;
527
+ }
528
+ }
529
+ }
530
+ }
531
+ //level 2 评价
532
+ if ((row < moduleCount - 1) && (col < moduleCount - 1)) {
533
+ var count = 0;
534
+ if (current) count++;
535
+ if (qrCode.modules[row + 1][col]) count++;
536
+ if (qrCode.modules[row][col + 1]) count++;
537
+ if (qrCode.modules[row + 1][col + 1]) count++;
538
+ if (count == 0 || count == 4) {
539
+ lostPoint += 3;
540
+ }
541
+ }
542
+ //level 1 评价
543
+ if (head ^ current) {
544
+ sameCount++;
545
+ } else {
546
+ head = current;
547
+ if (sameCount >= 5) {
548
+ lostPoint += (3 + sameCount - 5);
549
+ }
550
+ sameCount = 1;
551
+ }
552
+ //level 4 评价
553
+ if (current) {
554
+ darkCount++;
555
+ }
556
+ }
557
+ }
558
+ for (var col = 0; col < moduleCount; col++) {
559
+ var sameCount = 0;
560
+ var head = qrCode.modules[0][col];
561
+ for (var row = 0; row < moduleCount; row++) {
562
+ var current = qrCode.modules[row][col];
563
+ //level 3 评价
564
+ if (row < moduleCount - 6) {
565
+ if (current && !qrCode.modules[row + 1][col] && qrCode.modules[row + 2][col] && qrCode.modules[row + 3][col] && qrCode.modules[row + 4][col] && !qrCode.modules[row + 5][col] && qrCode.modules[row + 6][col]) {
566
+ if (row < moduleCount - 10) {
567
+ if (qrCode.modules[row + 7][col] && qrCode.modules[row + 8][col] && qrCode.modules[row + 9][col] && qrCode.modules[row + 10][col]) {
568
+ lostPoint += 40;
569
+ }
570
+ } else if (row > 3) {
571
+ if (qrCode.modules[row - 1][col] && qrCode.modules[row - 2][col] && qrCode.modules[row - 3][col] && qrCode.modules[row - 4][col]) {
572
+ lostPoint += 40;
573
+ }
574
+ }
575
+ }
576
+ }
577
+ //level 1 评价
578
+ if (head ^ current) {
579
+ sameCount++;
580
+ } else {
581
+ head = current;
582
+ if (sameCount >= 5) {
583
+ lostPoint += (3 + sameCount - 5);
584
+ }
585
+ sameCount = 1;
586
+ }
587
+ }
588
+ }
589
+ // LEVEL4
590
+ var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
591
+ lostPoint += ratio * 10;
592
+ return lostPoint;
593
+ }
594
+
595
+ };
596
+ //---------------------------------------------------------------------
597
+ // QRMath使用的数学工具
598
+ //---------------------------------------------------------------------
599
+ var QRMath = {
600
+ /*
601
+ 将n转化为a^m
602
+ */
603
+ glog: function (n) {
604
+ if (n < 1) {
605
+ throw new Error("glog(" + n + ")");
606
+ }
607
+ return QRMath.LOG_TABLE[n];
608
+ },
609
+ /*
610
+ 将a^m转化为n
611
+ */
612
+ gexp: function (n) {
613
+ while (n < 0) {
614
+ n += 255;
615
+ }
616
+ while (n >= 256) {
617
+ n -= 255;
618
+ }
619
+ return QRMath.EXP_TABLE[n];
620
+ },
621
+ EXP_TABLE: new Array(256),
622
+ LOG_TABLE: new Array(256)
623
+
624
+ };
625
+ for (var i = 0; i < 8; i++) {
626
+ QRMath.EXP_TABLE[i] = 1 << i;
627
+ }
628
+ for (var i = 8; i < 256; i++) {
629
+ QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
630
+ }
631
+ for (var i = 0; i < 255; i++) {
632
+ QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
633
+ }
634
+ //---------------------------------------------------------------------
635
+ // QRPolynomial 多项式
636
+ //---------------------------------------------------------------------
637
+ /**
638
+ * 多项式类
639
+ * @param {Array} num 系数
640
+ * @param {num} shift a^shift
641
+ */
642
+ function QRPolynomial(num, shift) {
643
+ if (num.length == undefined) {
644
+ throw new Error(num.length + "/" + shift);
645
+ }
646
+ var offset = 0;
647
+ while (offset < num.length && num[offset] == 0) {
648
+ offset++;
649
+ }
650
+ this.num = new Array(num.length - offset + shift);
651
+ for (var i = 0; i < num.length - offset; i++) {
652
+ this.num[i] = num[i + offset];
653
+ }
654
+ }
655
+ QRPolynomial.prototype = {
656
+ get: function (index) {
657
+ return this.num[index];
658
+ },
659
+ getLength: function () {
660
+ return this.num.length;
661
+ },
662
+ /**
663
+ * 多项式乘法
664
+ * @param {QRPolynomial} e 被乘多项式
665
+ * @return {[type]} [description]
666
+ */
667
+ multiply: function (e) {
668
+ var num = new Array(this.getLength() + e.getLength() - 1);
669
+ for (var i = 0; i < this.getLength(); i++) {
670
+ for (var j = 0; j < e.getLength(); j++) {
671
+ num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
672
+ }
673
+ }
674
+ return new QRPolynomial(num, 0);
675
+ },
676
+ /**
677
+ * 多项式模运算
678
+ * @param {QRPolynomial} e 模多项式
679
+ * @return {}
680
+ */
681
+ mod: function (e) {
682
+ var tl = this.getLength(),
683
+ el = e.getLength();
684
+ if (tl - el < 0) {
685
+ return this;
686
+ }
687
+ var num = new Array(tl);
688
+ for (var i = 0; i < tl; i++) {
689
+ num[i] = this.get(i);
690
+ }
691
+ while (num.length >= el) {
692
+ var ratio = QRMath.glog(num[0]) - QRMath.glog(e.get(0));
693
+
694
+ for (var i = 0; i < e.getLength(); i++) {
695
+ num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
696
+ }
697
+ while (num[0] == 0) {
698
+ num.shift();
699
+ }
700
+ }
701
+ return new QRPolynomial(num, 0);
702
+ }
703
+ };
704
+
705
+ //---------------------------------------------------------------------
706
+ // RS_BLOCK_TABLE
707
+ //---------------------------------------------------------------------
708
+ /*
709
+ 二维码各个版本信息[块数, 每块中的数据块数, 每块中的信息块数]
710
+ */
711
+ var RS_BLOCK_TABLE = [
712
+ // L
713
+ // M
714
+ // Q
715
+ // H
716
+ // 1
717
+ [1, 26, 19],
718
+ [1, 26, 16],
719
+ [1, 26, 13],
720
+ [1, 26, 9],
721
+
722
+ // 2
723
+ [1, 44, 34],
724
+ [1, 44, 28],
725
+ [1, 44, 22],
726
+ [1, 44, 16],
727
+
728
+ // 3
729
+ [1, 70, 55],
730
+ [1, 70, 44],
731
+ [2, 35, 17],
732
+ [2, 35, 13],
733
+
734
+ // 4
735
+ [1, 100, 80],
736
+ [2, 50, 32],
737
+ [2, 50, 24],
738
+ [4, 25, 9],
739
+
740
+ // 5
741
+ [1, 134, 108],
742
+ [2, 67, 43],
743
+ [2, 33, 15, 2, 34, 16],
744
+ [2, 33, 11, 2, 34, 12],
745
+
746
+ // 6
747
+ [2, 86, 68],
748
+ [4, 43, 27],
749
+ [4, 43, 19],
750
+ [4, 43, 15],
751
+
752
+ // 7
753
+ [2, 98, 78],
754
+ [4, 49, 31],
755
+ [2, 32, 14, 4, 33, 15],
756
+ [4, 39, 13, 1, 40, 14],
757
+
758
+ // 8
759
+ [2, 121, 97],
760
+ [2, 60, 38, 2, 61, 39],
761
+ [4, 40, 18, 2, 41, 19],
762
+ [4, 40, 14, 2, 41, 15],
763
+
764
+ // 9
765
+ [2, 146, 116],
766
+ [3, 58, 36, 2, 59, 37],
767
+ [4, 36, 16, 4, 37, 17],
768
+ [4, 36, 12, 4, 37, 13],
769
+
770
+ // 10
771
+ [2, 86, 68, 2, 87, 69],
772
+ [4, 69, 43, 1, 70, 44],
773
+ [6, 43, 19, 2, 44, 20],
774
+ [6, 43, 15, 2, 44, 16],
775
+
776
+ // 11
777
+ [4, 101, 81],
778
+ [1, 80, 50, 4, 81, 51],
779
+ [4, 50, 22, 4, 51, 23],
780
+ [3, 36, 12, 8, 37, 13],
781
+
782
+ // 12
783
+ [2, 116, 92, 2, 117, 93],
784
+ [6, 58, 36, 2, 59, 37],
785
+ [4, 46, 20, 6, 47, 21],
786
+ [7, 42, 14, 4, 43, 15],
787
+
788
+ // 13
789
+ [4, 133, 107],
790
+ [8, 59, 37, 1, 60, 38],
791
+ [8, 44, 20, 4, 45, 21],
792
+ [12, 33, 11, 4, 34, 12],
793
+
794
+ // 14
795
+ [3, 145, 115, 1, 146, 116],
796
+ [4, 64, 40, 5, 65, 41],
797
+ [11, 36, 16, 5, 37, 17],
798
+ [11, 36, 12, 5, 37, 13],
799
+
800
+ // 15
801
+ [5, 109, 87, 1, 110, 88],
802
+ [5, 65, 41, 5, 66, 42],
803
+ [5, 54, 24, 7, 55, 25],
804
+ [11, 36, 12],
805
+
806
+ // 16
807
+ [5, 122, 98, 1, 123, 99],
808
+ [7, 73, 45, 3, 74, 46],
809
+ [15, 43, 19, 2, 44, 20],
810
+ [3, 45, 15, 13, 46, 16],
811
+
812
+ // 17
813
+ [1, 135, 107, 5, 136, 108],
814
+ [10, 74, 46, 1, 75, 47],
815
+ [1, 50, 22, 15, 51, 23],
816
+ [2, 42, 14, 17, 43, 15],
817
+
818
+ // 18
819
+ [5, 150, 120, 1, 151, 121],
820
+ [9, 69, 43, 4, 70, 44],
821
+ [17, 50, 22, 1, 51, 23],
822
+ [2, 42, 14, 19, 43, 15],
823
+
824
+ // 19
825
+ [3, 141, 113, 4, 142, 114],
826
+ [3, 70, 44, 11, 71, 45],
827
+ [17, 47, 21, 4, 48, 22],
828
+ [9, 39, 13, 16, 40, 14],
829
+
830
+ // 20
831
+ [3, 135, 107, 5, 136, 108],
832
+ [3, 67, 41, 13, 68, 42],
833
+ [15, 54, 24, 5, 55, 25],
834
+ [15, 43, 15, 10, 44, 16],
835
+
836
+ // 21
837
+ [4, 144, 116, 4, 145, 117],
838
+ [17, 68, 42],
839
+ [17, 50, 22, 6, 51, 23],
840
+ [19, 46, 16, 6, 47, 17],
841
+
842
+ // 22
843
+ [2, 139, 111, 7, 140, 112],
844
+ [17, 74, 46],
845
+ [7, 54, 24, 16, 55, 25],
846
+ [34, 37, 13],
847
+
848
+ // 23
849
+ [4, 151, 121, 5, 152, 122],
850
+ [4, 75, 47, 14, 76, 48],
851
+ [11, 54, 24, 14, 55, 25],
852
+ [16, 45, 15, 14, 46, 16],
853
+
854
+ // 24
855
+ [6, 147, 117, 4, 148, 118],
856
+ [6, 73, 45, 14, 74, 46],
857
+ [11, 54, 24, 16, 55, 25],
858
+ [30, 46, 16, 2, 47, 17],
859
+
860
+ // 25
861
+ [8, 132, 106, 4, 133, 107],
862
+ [8, 75, 47, 13, 76, 48],
863
+ [7, 54, 24, 22, 55, 25],
864
+ [22, 45, 15, 13, 46, 16],
865
+
866
+ // 26
867
+ [10, 142, 114, 2, 143, 115],
868
+ [19, 74, 46, 4, 75, 47],
869
+ [28, 50, 22, 6, 51, 23],
870
+ [33, 46, 16, 4, 47, 17],
871
+
872
+ // 27
873
+ [8, 152, 122, 4, 153, 123],
874
+ [22, 73, 45, 3, 74, 46],
875
+ [8, 53, 23, 26, 54, 24],
876
+ [12, 45, 15, 28, 46, 16],
877
+
878
+ // 28
879
+ [3, 147, 117, 10, 148, 118],
880
+ [3, 73, 45, 23, 74, 46],
881
+ [4, 54, 24, 31, 55, 25],
882
+ [11, 45, 15, 31, 46, 16],
883
+
884
+ // 29
885
+ [7, 146, 116, 7, 147, 117],
886
+ [21, 73, 45, 7, 74, 46],
887
+ [1, 53, 23, 37, 54, 24],
888
+ [19, 45, 15, 26, 46, 16],
889
+
890
+ // 30
891
+ [5, 145, 115, 10, 146, 116],
892
+ [19, 75, 47, 10, 76, 48],
893
+ [15, 54, 24, 25, 55, 25],
894
+ [23, 45, 15, 25, 46, 16],
895
+
896
+ // 31
897
+ [13, 145, 115, 3, 146, 116],
898
+ [2, 74, 46, 29, 75, 47],
899
+ [42, 54, 24, 1, 55, 25],
900
+ [23, 45, 15, 28, 46, 16],
901
+
902
+ // 32
903
+ [17, 145, 115],
904
+ [10, 74, 46, 23, 75, 47],
905
+ [10, 54, 24, 35, 55, 25],
906
+ [19, 45, 15, 35, 46, 16],
907
+
908
+ // 33
909
+ [17, 145, 115, 1, 146, 116],
910
+ [14, 74, 46, 21, 75, 47],
911
+ [29, 54, 24, 19, 55, 25],
912
+ [11, 45, 15, 46, 46, 16],
913
+
914
+ // 34
915
+ [13, 145, 115, 6, 146, 116],
916
+ [14, 74, 46, 23, 75, 47],
917
+ [44, 54, 24, 7, 55, 25],
918
+ [59, 46, 16, 1, 47, 17],
919
+
920
+ // 35
921
+ [12, 151, 121, 7, 152, 122],
922
+ [12, 75, 47, 26, 76, 48],
923
+ [39, 54, 24, 14, 55, 25],
924
+ [22, 45, 15, 41, 46, 16],
925
+
926
+ // 36
927
+ [6, 151, 121, 14, 152, 122],
928
+ [6, 75, 47, 34, 76, 48],
929
+ [46, 54, 24, 10, 55, 25],
930
+ [2, 45, 15, 64, 46, 16],
931
+
932
+ // 37
933
+ [17, 152, 122, 4, 153, 123],
934
+ [29, 74, 46, 14, 75, 47],
935
+ [49, 54, 24, 10, 55, 25],
936
+ [24, 45, 15, 46, 46, 16],
937
+
938
+ // 38
939
+ [4, 152, 122, 18, 153, 123],
940
+ [13, 74, 46, 32, 75, 47],
941
+ [48, 54, 24, 14, 55, 25],
942
+ [42, 45, 15, 32, 46, 16],
943
+
944
+ // 39
945
+ [20, 147, 117, 4, 148, 118],
946
+ [40, 75, 47, 7, 76, 48],
947
+ [43, 54, 24, 22, 55, 25],
948
+ [10, 45, 15, 67, 46, 16],
949
+
950
+ // 40
951
+ [19, 148, 118, 6, 149, 119],
952
+ [18, 75, 47, 31, 76, 48],
953
+ [34, 54, 24, 34, 55, 25],
954
+ [20, 45, 15, 61, 46, 16]
955
+ ];
956
+
957
+ /**
958
+ * 根据数据获取对应版本
959
+ * @return {[type]} [description]
960
+ */
961
+ QRCodeAlg.prototype.getRightType = function () {
962
+ for (var typeNumber = 1; typeNumber < 41; typeNumber++) {
963
+ var rsBlock = RS_BLOCK_TABLE[(typeNumber - 1) * 4 + this.errorCorrectLevel];
964
+ if (rsBlock == undefined) {
965
+ throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + this.errorCorrectLevel);
966
+ }
967
+ var length = rsBlock.length / 3;
968
+ var totalDataCount = 0;
969
+ for (var i = 0; i < length; i++) {
970
+ var count = rsBlock[i * 3 + 0];
971
+ var dataCount = rsBlock[i * 3 + 2];
972
+ totalDataCount += dataCount * count;
973
+ }
974
+ var lengthBytes = typeNumber > 9 ? 2 : 1;
975
+ if (this.utf8bytes.length + lengthBytes < totalDataCount || typeNumber == 40) {
976
+ this.typeNumber = typeNumber;
977
+ this.rsBlock = rsBlock;
978
+ this.totalDataCount = totalDataCount;
979
+ break;
980
+ }
981
+ }
982
+ };
983
+
984
+ //---------------------------------------------------------------------
985
+ // QRBitBuffer
986
+ //---------------------------------------------------------------------
987
+ function QRBitBuffer() {
988
+ this.buffer = new Array();
989
+ this.length = 0;
990
+ }
991
+ QRBitBuffer.prototype = {
992
+ get: function (index) {
993
+ var bufIndex = Math.floor(index / 8);
994
+ return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1);
995
+ },
996
+ put: function (num, length) {
997
+ for (var i = 0; i < length; i++) {
998
+ this.putBit(((num >>> (length - i - 1)) & 1));
999
+ }
1000
+ },
1001
+ putBit: function (bit) {
1002
+ var bufIndex = Math.floor(this.length / 8);
1003
+ if (this.buffer.length <= bufIndex) {
1004
+ this.buffer.push(0);
1005
+ }
1006
+ if (bit) {
1007
+ this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
1008
+ }
1009
+ this.length++;
1010
+ }
1011
+ };
1012
+
1013
+
1014
+
1015
+ // xzedit
1016
+ let qrcodeAlgObjCache = [];
1017
+ /**
1018
+ * 二维码构造函数,主要用于绘制
1019
+ * @param {参数列表} opt 传递参数
1020
+ * @return {}
1021
+ */
1022
+ QRCode = function (opt) {
1023
+ //设置默认参数
1024
+ this.options = {
1025
+ text: '',
1026
+ size: 256,
1027
+ correctLevel: 3,
1028
+ background: '#ffffff',
1029
+ foreground: '#000000',
1030
+ pdground: '#000000',
1031
+ image: '',
1032
+ imageSize: 30,
1033
+ canvasId: opt.canvasId,
1034
+ context: opt.context,
1035
+ usingComponents: opt.usingComponents,
1036
+ showLoading: opt.showLoading,
1037
+ loadingText: opt.loadingText,
1038
+ };
1039
+ if (typeof opt === 'string') { // 只编码ASCII字符串
1040
+ opt = {
1041
+ text: opt
1042
+ };
1043
+ }
1044
+ if (opt) {
1045
+ for (var i in opt) {
1046
+ this.options[i] = opt[i];
1047
+ }
1048
+ }
1049
+ //使用QRCodeAlg创建二维码结构
1050
+ var qrCodeAlg = null;
1051
+ for (var i = 0, l = qrcodeAlgObjCache.length; i < l; i++) {
1052
+ if (qrcodeAlgObjCache[i].text == this.options.text && qrcodeAlgObjCache[i].text.correctLevel == this.options.correctLevel) {
1053
+ qrCodeAlg = qrcodeAlgObjCache[i].obj;
1054
+ break;
1055
+ }
1056
+ }
1057
+ if (i == l) {
1058
+ qrCodeAlg = new QRCodeAlg(this.options.text, this.options.correctLevel);
1059
+ qrcodeAlgObjCache.push({
1060
+ text: this.options.text,
1061
+ correctLevel: this.options.correctLevel,
1062
+ obj: qrCodeAlg
1063
+ });
1064
+ }
1065
+ /**
1066
+ * 计算矩阵点的前景色
1067
+ * @param {Obj} config
1068
+ * @param {Number} config.row 点x坐标
1069
+ * @param {Number} config.col 点y坐标
1070
+ * @param {Number} config.count 矩阵大小
1071
+ * @param {Number} config.options 组件的options
1072
+ * @return {String}
1073
+ */
1074
+ let getForeGround = function (config) {
1075
+ var options = config.options;
1076
+ if (options.pdground && (
1077
+ (config.row > 1 && config.row < 5 && config.col > 1 && config.col < 5) ||
1078
+ (config.row > (config.count - 6) && config.row < (config.count - 2) && config.col > 1 && config.col < 5) ||
1079
+ (config.row > 1 && config.row < 5 && config.col > (config.count - 6) && config.col < (config.count - 2))
1080
+ )) {
1081
+ return options.pdground;
1082
+ }
1083
+ return options.foreground;
1084
+ }
1085
+ // 创建canvas
1086
+ let createCanvas = function (options) {
1087
+ if(options.showLoading){
1088
+ uni.showLoading({
1089
+ title: options.loadingText,
1090
+ mask: true
1091
+ });
1092
+ }
1093
+ var ctx = uni.createCanvasContext(options.canvasId, options.context);
1094
+ var count = qrCodeAlg.getModuleCount();
1095
+ var ratioSize = options.size;
1096
+ var ratioImgSize = options.imageSize;
1097
+ //计算每个点的长宽
1098
+ var tileW = (ratioSize / count).toPrecision(4);
1099
+ var tileH = (ratioSize / count).toPrecision(4);
1100
+ //绘制
1101
+ for (var row = 0; row < count; row++) {
1102
+ for (var col = 0; col < count; col++) {
1103
+ var w = (Math.ceil((col + 1) * tileW) - Math.floor(col * tileW));
1104
+ var h = (Math.ceil((row + 1) * tileW) - Math.floor(row * tileW));
1105
+ var foreground = getForeGround({
1106
+ row: row,
1107
+ col: col,
1108
+ count: count,
1109
+ options: options
1110
+ });
1111
+ ctx.setFillStyle(qrCodeAlg.modules[row][col] ? foreground : options.background);
1112
+ ctx.fillRect(Math.round(col * tileW), Math.round(row * tileH), w, h);
1113
+ }
1114
+ }
1115
+ if (options.image) {
1116
+ var x = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
1117
+ var y = Number(((ratioSize - ratioImgSize) / 2).toFixed(2));
1118
+ drawRoundedRect(ctx, x, y, ratioImgSize, ratioImgSize, 2, 6, true, true)
1119
+ ctx.drawImage(options.image, x, y, ratioImgSize, ratioImgSize);
1120
+ // 画圆角矩形
1121
+ function drawRoundedRect(ctxi, x, y, width, height, r, lineWidth, fill, stroke) {
1122
+ ctxi.setLineWidth(lineWidth);
1123
+ ctxi.setFillStyle(options.background);
1124
+ ctxi.setStrokeStyle(options.background);
1125
+ ctxi.beginPath(); // draw top and top right corner
1126
+ ctxi.moveTo(x + r, y);
1127
+ ctxi.arcTo(x + width, y, x + width, y + r, r); // draw right side and bottom right corner
1128
+ ctxi.arcTo(x + width, y + height, x + width - r, y + height, r); // draw bottom and bottom left corner
1129
+ ctxi.arcTo(x, y + height, x, y + height - r, r); // draw left and top left corner
1130
+ ctxi.arcTo(x, y, x + r, y, r);
1131
+ ctxi.closePath();
1132
+ if (fill) {
1133
+ ctxi.fill();
1134
+ }
1135
+ if (stroke) {
1136
+ ctxi.stroke();
1137
+ }
1138
+ }
1139
+ }
1140
+ setTimeout(() => {
1141
+ ctx.draw(true, () => {
1142
+ // 保存到临时区域
1143
+ setTimeout(() => {
1144
+ uni.canvasToTempFilePath({
1145
+ width: options.width,
1146
+ height: options.height,
1147
+ destWidth: options.width,
1148
+ destHeight: options.height,
1149
+ canvasId: options.canvasId,
1150
+ quality: Number(1),
1151
+ success: function (res) {
1152
+ if (options.cbResult) {
1153
+ // 由于官方还没有统一此接口的输出字段,所以先判定下 支付宝为 res.apFilePath
1154
+ if (!empty(res.tempFilePath)) {
1155
+ options.cbResult(res.tempFilePath)
1156
+ } else if (!empty(res.apFilePath)) {
1157
+ options.cbResult(res.apFilePath)
1158
+ } else {
1159
+ options.cbResult(res.tempFilePath)
1160
+ }
1161
+ }
1162
+ },
1163
+ fail: function (res) {
1164
+ if (options.cbResult) {
1165
+ options.cbResult(res)
1166
+ }
1167
+ },
1168
+ complete: function () {
1169
+ uni.hideLoading();
1170
+ },
1171
+ }, options.context);
1172
+ }, options.text.length + 100);
1173
+ });
1174
+ }, options.usingComponents ? 0 : 150);
1175
+ }
1176
+ createCanvas(this.options);
1177
+ // 空判定
1178
+ let empty = function (v) {
1179
+ let tp = typeof v,
1180
+ rt = false;
1181
+ if (tp == "number" && String(v) == "") {
1182
+ rt = true
1183
+ } else if (tp == "undefined") {
1184
+ rt = true
1185
+ } else if (tp == "object") {
1186
+ if (JSON.stringify(v) == "{}" || JSON.stringify(v) == "[]" || v == null) rt = true
1187
+ } else if (tp == "string") {
1188
+ if (v == "" || v == "undefined" || v == "null" || v == "{}" || v == "[]") rt = true
1189
+ } else if (tp == "function") {
1190
+ rt = false
1191
+ }
1192
+ return rt
1193
+ }
1194
+ };
1195
+ QRCode.prototype.clear = function (fn) {
1196
+ var ctx = uni.createCanvasContext(this.options.canvasId, this.options.context)
1197
+ ctx.clearRect(0, 0, this.options.size, this.options.size)
1198
+ ctx.draw(false, () => {
1199
+ if (fn) {
1200
+ fn()
1201
+ }
1202
+ })
1203
+ };
1204
+ })()
1205
+
1206
+ export default QRCode