@liquid-js/qr-code-styling 3.0.0-1 → 3.0.0-3
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/README.md +1 -2
- package/lib/core/{QRCodeStyling.d.ts → qr-code-styling.d.ts} +16 -22
- package/lib/core/qr-svg.d.ts +31 -0
- package/lib/figures/corner-dot.d.ts +24 -0
- package/lib/figures/corner-square.d.ts +22 -0
- package/lib/figures/dot.d.ts +28 -0
- package/lib/index.d.ts +9 -5
- package/lib/node.d.ts +13 -6
- package/lib/qr-code-styling-node.js +455 -441
- package/lib/qr-code-styling-node.js.map +1 -1
- package/lib/qr-code-styling.js +1 -1
- package/lib/qr-code-styling.js.map +1 -1
- package/lib/tools/{browserImageTools.d.ts → browser-image-tools.d.ts} +1 -2
- package/lib/tools/browser-utils.d.ts +18 -0
- package/lib/types/helper.d.ts +23 -0
- package/lib/types/qrcode.d.ts +64 -0
- package/lib/utils/canvas-options.d.ts +7 -0
- package/lib/utils/gradient.d.ts +26 -0
- package/lib/{tools → utils}/merge.d.ts +3 -1
- package/lib/{types/index.d.ts → utils/options.d.ts} +29 -151
- package/lib/{constants/errorCorrectionPercents.d.ts → utils/qrcode.d.ts} +2 -0
- package/package.json +1 -1
- package/lib/core/QROptions.d.ts +0 -32
- package/lib/core/QRSVG.d.ts +0 -58
- package/lib/figures/cornerDot/QRCornerDot.d.ts +0 -27
- package/lib/figures/cornerSquare/QRCornerSquare.d.ts +0 -25
- package/lib/figures/dot/QRDot.d.ts +0 -31
- package/lib/tools/browserUtils.d.ts +0 -11
- package/lib/tools/getMode.d.ts +0 -2
- package/lib/tools/sanitizeOptions.d.ts +0 -3
- /package/lib/{tools/calculateImageSize.d.ts → utils/image.d.ts} +0 -0
|
@@ -3,49 +3,6 @@ import { fileTypeFromBuffer } from 'file-type';
|
|
|
3
3
|
import sharp from 'sharp';
|
|
4
4
|
import qrcode from 'qrcode-generator';
|
|
5
5
|
|
|
6
|
-
var DotType;
|
|
7
|
-
(function (DotType) {
|
|
8
|
-
DotType["dots"] = "dots";
|
|
9
|
-
DotType["randomDots"] = "random-dots";
|
|
10
|
-
DotType["rounded"] = "rounded";
|
|
11
|
-
DotType["verticalLines"] = "vertical-lines";
|
|
12
|
-
DotType["horizontalLines"] = "horizontal-lines";
|
|
13
|
-
DotType["classy"] = "classy";
|
|
14
|
-
DotType["classyRounded"] = "classy-rounded";
|
|
15
|
-
DotType["square"] = "square";
|
|
16
|
-
DotType["smallSquare"] = "small-square";
|
|
17
|
-
DotType["extraRounded"] = "extra-rounded";
|
|
18
|
-
DotType["diamond"] = "diamond";
|
|
19
|
-
})(DotType || (DotType = {}));
|
|
20
|
-
var CornerDotType;
|
|
21
|
-
(function (CornerDotType) {
|
|
22
|
-
CornerDotType["dot"] = "dot";
|
|
23
|
-
CornerDotType["square"] = "square";
|
|
24
|
-
CornerDotType["heart"] = "heart";
|
|
25
|
-
CornerDotType["extraRounded"] = "extra-rounded";
|
|
26
|
-
CornerDotType["classy"] = "classy";
|
|
27
|
-
CornerDotType["outpoint"] = "outpoint";
|
|
28
|
-
CornerDotType["inpoint"] = "inpoint";
|
|
29
|
-
})(CornerDotType || (CornerDotType = {}));
|
|
30
|
-
var CornerSquareType;
|
|
31
|
-
(function (CornerSquareType) {
|
|
32
|
-
CornerSquareType["dot"] = "dot";
|
|
33
|
-
CornerSquareType["square"] = "square";
|
|
34
|
-
CornerSquareType["extraRounded"] = "extra-rounded";
|
|
35
|
-
CornerSquareType["classy"] = "classy";
|
|
36
|
-
CornerSquareType["outpoint"] = "outpoint";
|
|
37
|
-
CornerSquareType["inpoint"] = "inpoint";
|
|
38
|
-
})(CornerSquareType || (CornerSquareType = {}));
|
|
39
|
-
var GradientType;
|
|
40
|
-
(function (GradientType) {
|
|
41
|
-
GradientType["radial"] = "radial";
|
|
42
|
-
GradientType["linear"] = "linear";
|
|
43
|
-
})(GradientType || (GradientType = {}));
|
|
44
|
-
var ShapeType;
|
|
45
|
-
(function (ShapeType) {
|
|
46
|
-
ShapeType["square"] = "square";
|
|
47
|
-
ShapeType["circle"] = "circle";
|
|
48
|
-
})(ShapeType || (ShapeType = {}));
|
|
49
6
|
const TypeNumber = Array(41)
|
|
50
7
|
.fill(0)
|
|
51
8
|
.map((_, i) => i);
|
|
@@ -64,34 +21,6 @@ var Mode;
|
|
|
64
21
|
Mode["kanji"] = "Kanji";
|
|
65
22
|
Mode["unicode"] = "Unicode";
|
|
66
23
|
})(Mode || (Mode = {}));
|
|
67
|
-
var FileExtension;
|
|
68
|
-
(function (FileExtension) {
|
|
69
|
-
FileExtension["svg"] = "svg";
|
|
70
|
-
FileExtension["png"] = "png";
|
|
71
|
-
FileExtension["jpeg"] = "jpeg";
|
|
72
|
-
FileExtension["webp"] = "webp";
|
|
73
|
-
})(FileExtension || (FileExtension = {}));
|
|
74
|
-
|
|
75
|
-
const ErrorCorrectionPercents = {
|
|
76
|
-
[ErrorCorrectionLevel.L]: 0.07,
|
|
77
|
-
[ErrorCorrectionLevel.M]: 0.15,
|
|
78
|
-
[ErrorCorrectionLevel.Q]: 0.25,
|
|
79
|
-
[ErrorCorrectionLevel.H]: 0.3
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
function getMode(data) {
|
|
83
|
-
switch (true) {
|
|
84
|
-
case /^[0-9]*$/.test(data):
|
|
85
|
-
return Mode.numeric;
|
|
86
|
-
case /^[0-9A-Z $%*+\-./:]*$/.test(data):
|
|
87
|
-
return Mode.alphanumeric;
|
|
88
|
-
// eslint-disable-next-line no-control-regex
|
|
89
|
-
case /[^\u0000-\u00ff]/.test(data):
|
|
90
|
-
return Mode.unicode;
|
|
91
|
-
default:
|
|
92
|
-
return Mode.byte;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
24
|
|
|
96
25
|
const isObject = (obj) => !!obj && typeof obj === "object" && !Array.isArray(obj);
|
|
97
26
|
function mergeDeep(target, ...sources) {
|
|
@@ -117,6 +46,11 @@ function mergeDeep(target, ...sources) {
|
|
|
117
46
|
return mergeDeep(target, ...sources);
|
|
118
47
|
}
|
|
119
48
|
|
|
49
|
+
var GradientType;
|
|
50
|
+
(function (GradientType) {
|
|
51
|
+
GradientType["radial"] = "radial";
|
|
52
|
+
GradientType["linear"] = "linear";
|
|
53
|
+
})(GradientType || (GradientType = {}));
|
|
120
54
|
function sanitizeGradient(gradient) {
|
|
121
55
|
const newGradient = { ...gradient };
|
|
122
56
|
if (!newGradient.colorStops || !newGradient.colorStops.length) {
|
|
@@ -134,6 +68,68 @@ function sanitizeGradient(gradient) {
|
|
|
134
68
|
}));
|
|
135
69
|
return newGradient;
|
|
136
70
|
}
|
|
71
|
+
|
|
72
|
+
var DotType;
|
|
73
|
+
(function (DotType) {
|
|
74
|
+
DotType["dot"] = "dot";
|
|
75
|
+
DotType["randomDot"] = "random-dot";
|
|
76
|
+
DotType["rounded"] = "rounded";
|
|
77
|
+
DotType["verticalLine"] = "vertical-line";
|
|
78
|
+
DotType["horizontalLine"] = "horizontal-line";
|
|
79
|
+
DotType["classy"] = "classy";
|
|
80
|
+
DotType["classyRounded"] = "classy-rounded";
|
|
81
|
+
DotType["square"] = "square";
|
|
82
|
+
DotType["smallSquare"] = "small-square";
|
|
83
|
+
DotType["extraRounded"] = "extra-rounded";
|
|
84
|
+
DotType["diamond"] = "diamond";
|
|
85
|
+
})(DotType || (DotType = {}));
|
|
86
|
+
var CornerDotType;
|
|
87
|
+
(function (CornerDotType) {
|
|
88
|
+
CornerDotType["dot"] = "dot";
|
|
89
|
+
CornerDotType["square"] = "square";
|
|
90
|
+
CornerDotType["heart"] = "heart";
|
|
91
|
+
CornerDotType["extraRounded"] = "extra-rounded";
|
|
92
|
+
CornerDotType["classy"] = "classy";
|
|
93
|
+
CornerDotType["outpoint"] = "outpoint";
|
|
94
|
+
CornerDotType["inpoint"] = "inpoint";
|
|
95
|
+
})(CornerDotType || (CornerDotType = {}));
|
|
96
|
+
var CornerSquareType;
|
|
97
|
+
(function (CornerSquareType) {
|
|
98
|
+
CornerSquareType["dot"] = "dot";
|
|
99
|
+
CornerSquareType["square"] = "square";
|
|
100
|
+
CornerSquareType["extraRounded"] = "extra-rounded";
|
|
101
|
+
CornerSquareType["classy"] = "classy";
|
|
102
|
+
CornerSquareType["outpoint"] = "outpoint";
|
|
103
|
+
CornerSquareType["inpoint"] = "inpoint";
|
|
104
|
+
})(CornerSquareType || (CornerSquareType = {}));
|
|
105
|
+
var ShapeType;
|
|
106
|
+
(function (ShapeType) {
|
|
107
|
+
ShapeType["square"] = "square";
|
|
108
|
+
ShapeType["circle"] = "circle";
|
|
109
|
+
})(ShapeType || (ShapeType = {}));
|
|
110
|
+
const defaultOptions = {
|
|
111
|
+
document: undefined,
|
|
112
|
+
shape: ShapeType.square,
|
|
113
|
+
width: undefined,
|
|
114
|
+
height: undefined,
|
|
115
|
+
data: "",
|
|
116
|
+
qrOptions: {
|
|
117
|
+
typeNumber: TypeNumber[0],
|
|
118
|
+
mode: undefined,
|
|
119
|
+
errorCorrectionLevel: ErrorCorrectionLevel.Q
|
|
120
|
+
},
|
|
121
|
+
imageOptions: {
|
|
122
|
+
hideBackgroundDots: true,
|
|
123
|
+
imageSize: 0.4,
|
|
124
|
+
crossOrigin: undefined,
|
|
125
|
+
margin: 0
|
|
126
|
+
},
|
|
127
|
+
dotsOptions: {
|
|
128
|
+
type: DotType.square,
|
|
129
|
+
color: "#000",
|
|
130
|
+
size: 10
|
|
131
|
+
}
|
|
132
|
+
};
|
|
137
133
|
function sanitizeOptions(options) {
|
|
138
134
|
const newOptions = { ...options };
|
|
139
135
|
newOptions.imageOptions = {
|
|
@@ -179,88 +175,86 @@ function sanitizeOptions(options) {
|
|
|
179
175
|
return newOptions;
|
|
180
176
|
}
|
|
181
177
|
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
data: "",
|
|
188
|
-
qrOptions: {
|
|
189
|
-
typeNumber: TypeNumber[0],
|
|
190
|
-
mode: undefined,
|
|
191
|
-
errorCorrectionLevel: ErrorCorrectionLevel.Q
|
|
192
|
-
},
|
|
193
|
-
imageOptions: {
|
|
194
|
-
hideBackgroundDots: true,
|
|
195
|
-
imageSize: 0.4,
|
|
196
|
-
crossOrigin: undefined,
|
|
197
|
-
margin: 0
|
|
198
|
-
},
|
|
199
|
-
dotsOptions: {
|
|
200
|
-
type: DotType.square,
|
|
201
|
-
color: "#000",
|
|
202
|
-
size: 10
|
|
203
|
-
}
|
|
178
|
+
const ErrorCorrectionPercents = {
|
|
179
|
+
[ErrorCorrectionLevel.L]: 0.07,
|
|
180
|
+
[ErrorCorrectionLevel.M]: 0.15,
|
|
181
|
+
[ErrorCorrectionLevel.Q]: 0.25,
|
|
182
|
+
[ErrorCorrectionLevel.H]: 0.3
|
|
204
183
|
};
|
|
184
|
+
function getMode(data) {
|
|
185
|
+
switch (true) {
|
|
186
|
+
case /^[0-9]*$/.test(data):
|
|
187
|
+
return Mode.numeric;
|
|
188
|
+
case /^[0-9A-Z $%*+\-./:]*$/.test(data):
|
|
189
|
+
return Mode.alphanumeric;
|
|
190
|
+
// eslint-disable-next-line no-control-regex
|
|
191
|
+
case /[^\u0000-\u00ff]/.test(data):
|
|
192
|
+
return Mode.unicode;
|
|
193
|
+
default:
|
|
194
|
+
return Mode.byte;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
205
197
|
|
|
206
198
|
class QRCornerDot {
|
|
207
|
-
|
|
208
|
-
this.
|
|
209
|
-
|
|
210
|
-
|
|
199
|
+
get element() {
|
|
200
|
+
return this._element;
|
|
201
|
+
}
|
|
202
|
+
constructor(type, document) {
|
|
203
|
+
this.type = type;
|
|
204
|
+
this.document = document;
|
|
211
205
|
}
|
|
212
|
-
draw(
|
|
213
|
-
const type = this.
|
|
206
|
+
draw(args) {
|
|
207
|
+
const type = this.type;
|
|
214
208
|
let drawFunction;
|
|
215
209
|
switch (type) {
|
|
216
210
|
case CornerDotType.square:
|
|
217
|
-
drawFunction = this.
|
|
211
|
+
drawFunction = this.drawSquare;
|
|
218
212
|
break;
|
|
219
213
|
case CornerDotType.heart:
|
|
220
|
-
drawFunction = this.
|
|
214
|
+
drawFunction = this.drawHeart;
|
|
221
215
|
break;
|
|
222
216
|
case CornerDotType.extraRounded:
|
|
223
|
-
drawFunction = this.
|
|
217
|
+
drawFunction = this.drawRounded;
|
|
224
218
|
break;
|
|
225
219
|
case CornerDotType.classy:
|
|
226
|
-
drawFunction = this.
|
|
220
|
+
drawFunction = this.drawClassy;
|
|
227
221
|
break;
|
|
228
222
|
case CornerDotType.inpoint:
|
|
229
|
-
drawFunction = this.
|
|
223
|
+
drawFunction = this.drawInpoint;
|
|
230
224
|
break;
|
|
231
225
|
case CornerDotType.outpoint:
|
|
232
|
-
drawFunction = this.
|
|
226
|
+
drawFunction = this.drawOutpoint;
|
|
233
227
|
break;
|
|
234
228
|
case CornerDotType.dot:
|
|
235
229
|
default:
|
|
236
|
-
drawFunction = this.
|
|
230
|
+
drawFunction = this.drawDot;
|
|
237
231
|
}
|
|
238
|
-
drawFunction.call(this,
|
|
232
|
+
drawFunction.call(this, args);
|
|
239
233
|
}
|
|
240
|
-
|
|
234
|
+
rotateFigure({ x, y, size, rotation = 0, draw }) {
|
|
241
235
|
const cx = x + size / 2;
|
|
242
236
|
const cy = y + size / 2;
|
|
243
237
|
draw();
|
|
244
238
|
this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`);
|
|
245
239
|
}
|
|
246
|
-
|
|
240
|
+
basicDot(args) {
|
|
247
241
|
const { size, x, y } = args;
|
|
248
|
-
this.
|
|
242
|
+
this.rotateFigure({
|
|
249
243
|
...args,
|
|
250
244
|
draw: () => {
|
|
251
|
-
this._element = this.
|
|
245
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
252
246
|
this._element.setAttribute("cx", String(x + size / 2));
|
|
253
247
|
this._element.setAttribute("cy", String(y + size / 2));
|
|
254
248
|
this._element.setAttribute("r", String(size / 2));
|
|
255
249
|
}
|
|
256
250
|
});
|
|
257
251
|
}
|
|
258
|
-
|
|
252
|
+
basicSquare(args) {
|
|
259
253
|
const { size, x, y } = args;
|
|
260
|
-
this.
|
|
254
|
+
this.rotateFigure({
|
|
261
255
|
...args,
|
|
262
256
|
draw: () => {
|
|
263
|
-
this._element = this.
|
|
257
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
264
258
|
this._element.setAttribute("x", String(x));
|
|
265
259
|
this._element.setAttribute("y", String(y));
|
|
266
260
|
this._element.setAttribute("width", String(size));
|
|
@@ -268,9 +262,9 @@ class QRCornerDot {
|
|
|
268
262
|
}
|
|
269
263
|
});
|
|
270
264
|
}
|
|
271
|
-
|
|
265
|
+
basicHeart(args) {
|
|
272
266
|
const { size, x, y } = args;
|
|
273
|
-
this._element = this.
|
|
267
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
274
268
|
const path = [
|
|
275
269
|
"M",
|
|
276
270
|
0.925,
|
|
@@ -397,12 +391,12 @@ class QRCornerDot {
|
|
|
397
391
|
})
|
|
398
392
|
.join(" "));
|
|
399
393
|
}
|
|
400
|
-
|
|
394
|
+
basicRounded(args) {
|
|
401
395
|
const { size, x, y } = args;
|
|
402
|
-
this.
|
|
396
|
+
this.rotateFigure({
|
|
403
397
|
...args,
|
|
404
398
|
draw: () => {
|
|
405
|
-
this._element = this.
|
|
399
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
406
400
|
this._element.setAttribute("x", String(x));
|
|
407
401
|
this._element.setAttribute("y", String(y));
|
|
408
402
|
this._element.setAttribute("width", String(size));
|
|
@@ -412,13 +406,13 @@ class QRCornerDot {
|
|
|
412
406
|
}
|
|
413
407
|
});
|
|
414
408
|
}
|
|
415
|
-
|
|
409
|
+
basicClassy(args) {
|
|
416
410
|
const { size, x, y } = args;
|
|
417
411
|
const dotSize = size / 7;
|
|
418
|
-
this.
|
|
412
|
+
this.rotateFigure({
|
|
419
413
|
...args,
|
|
420
414
|
draw: () => {
|
|
421
|
-
this._element = this.
|
|
415
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
422
416
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
423
417
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
424
418
|
`v ${2 * dotSize}` +
|
|
@@ -432,13 +426,13 @@ class QRCornerDot {
|
|
|
432
426
|
}
|
|
433
427
|
});
|
|
434
428
|
}
|
|
435
|
-
|
|
429
|
+
basicInpoint(args) {
|
|
436
430
|
const { size, x, y } = args;
|
|
437
431
|
const dotSize = size;
|
|
438
|
-
this.
|
|
432
|
+
this.rotateFigure({
|
|
439
433
|
...args,
|
|
440
434
|
draw: () => {
|
|
441
|
-
this._element = this.
|
|
435
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
442
436
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
443
437
|
this._element.setAttribute("d", `M ${x} ${y + dotSize / 2}` +
|
|
444
438
|
`v ${dotSize / 4}` +
|
|
@@ -452,79 +446,81 @@ class QRCornerDot {
|
|
|
452
446
|
}
|
|
453
447
|
});
|
|
454
448
|
}
|
|
455
|
-
|
|
456
|
-
this.
|
|
449
|
+
drawDot({ x, y, size, rotation }) {
|
|
450
|
+
this.basicDot({ x, y, size, rotation });
|
|
457
451
|
}
|
|
458
|
-
|
|
459
|
-
this.
|
|
452
|
+
drawSquare({ x, y, size, rotation }) {
|
|
453
|
+
this.basicSquare({ x, y, size, rotation });
|
|
460
454
|
}
|
|
461
|
-
|
|
455
|
+
drawHeart({ x, y, size, rotation }) {
|
|
462
456
|
const scaleFactor = 0.2;
|
|
463
|
-
this.
|
|
457
|
+
this.basicHeart({
|
|
464
458
|
x: x - (scaleFactor * size) / 2,
|
|
465
459
|
y: y - (scaleFactor * size) / 2,
|
|
466
460
|
size: size * (1 + scaleFactor),
|
|
467
461
|
rotation
|
|
468
462
|
});
|
|
469
463
|
}
|
|
470
|
-
|
|
471
|
-
this.
|
|
464
|
+
drawRounded({ x, y, size, rotation }) {
|
|
465
|
+
this.basicRounded({ x, y, size, rotation });
|
|
472
466
|
}
|
|
473
|
-
|
|
474
|
-
this.
|
|
467
|
+
drawClassy({ x, y, size, rotation }) {
|
|
468
|
+
this.basicClassy({ x, y, size, rotation });
|
|
475
469
|
}
|
|
476
|
-
|
|
477
|
-
this.
|
|
470
|
+
drawInpoint({ x, y, size, rotation }) {
|
|
471
|
+
this.basicInpoint({ x, y, size, rotation });
|
|
478
472
|
}
|
|
479
|
-
|
|
480
|
-
this.
|
|
473
|
+
drawOutpoint({ x, y, size, rotation }) {
|
|
474
|
+
this.basicInpoint({ x, y, size, rotation: (rotation || 0) + Math.PI });
|
|
481
475
|
}
|
|
482
476
|
}
|
|
483
477
|
|
|
484
478
|
class QRCornerSquare {
|
|
485
|
-
|
|
486
|
-
this.
|
|
487
|
-
|
|
488
|
-
|
|
479
|
+
get element() {
|
|
480
|
+
return this._element;
|
|
481
|
+
}
|
|
482
|
+
constructor(type, document) {
|
|
483
|
+
this.type = type;
|
|
484
|
+
this.document = document;
|
|
489
485
|
}
|
|
490
|
-
draw(
|
|
491
|
-
const type = this.
|
|
486
|
+
draw(args) {
|
|
487
|
+
const type = this.type;
|
|
492
488
|
let drawFunction;
|
|
493
489
|
switch (type) {
|
|
494
490
|
case CornerSquareType.square:
|
|
495
|
-
drawFunction = this.
|
|
491
|
+
drawFunction = this.drawSquare;
|
|
496
492
|
break;
|
|
497
493
|
case CornerSquareType.extraRounded:
|
|
498
|
-
drawFunction = this.
|
|
494
|
+
drawFunction = this.drawExtraRounded;
|
|
499
495
|
break;
|
|
500
496
|
case CornerSquareType.classy:
|
|
501
|
-
drawFunction = this.
|
|
497
|
+
drawFunction = this.drawClassy;
|
|
502
498
|
break;
|
|
503
499
|
case CornerSquareType.outpoint:
|
|
504
|
-
drawFunction = this.
|
|
500
|
+
drawFunction = this.drawOutpoint;
|
|
505
501
|
break;
|
|
506
502
|
case CornerSquareType.inpoint:
|
|
507
|
-
drawFunction = this.
|
|
503
|
+
drawFunction = this.drawInpoint;
|
|
508
504
|
break;
|
|
509
505
|
case CornerSquareType.dot:
|
|
510
506
|
default:
|
|
511
|
-
drawFunction = this.
|
|
507
|
+
drawFunction = this.drawDot;
|
|
512
508
|
}
|
|
513
|
-
drawFunction.call(this,
|
|
509
|
+
drawFunction.call(this, args);
|
|
514
510
|
}
|
|
515
|
-
|
|
511
|
+
rotateFigure({ x, y, size, rotation = 0, draw }) {
|
|
516
512
|
const cx = x + size / 2;
|
|
517
513
|
const cy = y + size / 2;
|
|
518
514
|
draw();
|
|
519
515
|
this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`);
|
|
520
516
|
}
|
|
521
|
-
|
|
517
|
+
basicDot(args) {
|
|
522
518
|
const { size, x, y } = args;
|
|
523
519
|
const dotSize = size / 7;
|
|
524
|
-
this.
|
|
520
|
+
this.rotateFigure({
|
|
525
521
|
...args,
|
|
526
522
|
draw: () => {
|
|
527
|
-
this._element = this.
|
|
523
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
528
524
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
529
525
|
this._element.setAttribute("d", `M ${x + size / 2} ${y}` + // M cx, y // Move to top of ring
|
|
530
526
|
`a ${size / 2} ${size / 2} 0 1 0 0.1 0` + // a outerRadius, outerRadius, 0, 1, 0, 1, 0 // Draw outer arc, but don't close it
|
|
@@ -536,13 +532,13 @@ class QRCornerSquare {
|
|
|
536
532
|
}
|
|
537
533
|
});
|
|
538
534
|
}
|
|
539
|
-
|
|
535
|
+
basicSquare(args) {
|
|
540
536
|
const { size, x, y } = args;
|
|
541
537
|
const dotSize = size / 7;
|
|
542
|
-
this.
|
|
538
|
+
this.rotateFigure({
|
|
543
539
|
...args,
|
|
544
540
|
draw: () => {
|
|
545
|
-
this._element = this.
|
|
541
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
546
542
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
547
543
|
this._element.setAttribute("d", `M ${x} ${y}` +
|
|
548
544
|
`v ${size}` +
|
|
@@ -557,13 +553,13 @@ class QRCornerSquare {
|
|
|
557
553
|
}
|
|
558
554
|
});
|
|
559
555
|
}
|
|
560
|
-
|
|
556
|
+
basicExtraRounded(args) {
|
|
561
557
|
const { size, x, y } = args;
|
|
562
558
|
const dotSize = size / 7;
|
|
563
|
-
this.
|
|
559
|
+
this.rotateFigure({
|
|
564
560
|
...args,
|
|
565
561
|
draw: () => {
|
|
566
|
-
this._element = this.
|
|
562
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
567
563
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
568
564
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
569
565
|
`v ${2 * dotSize}` +
|
|
@@ -574,6 +570,7 @@ class QRCornerSquare {
|
|
|
574
570
|
`a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${-dotSize * 2.5}` +
|
|
575
571
|
`h ${-2 * dotSize}` +
|
|
576
572
|
`a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${dotSize * 2.5}` +
|
|
573
|
+
`z` +
|
|
577
574
|
`M ${x + 2.5 * dotSize} ${y + dotSize}` +
|
|
578
575
|
`h ${2 * dotSize}` +
|
|
579
576
|
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${dotSize * 1.5}` +
|
|
@@ -582,17 +579,18 @@ class QRCornerSquare {
|
|
|
582
579
|
`h ${-2 * dotSize}` +
|
|
583
580
|
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${-dotSize * 1.5}` +
|
|
584
581
|
`v ${-2 * dotSize}` +
|
|
585
|
-
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${-dotSize * 1.5}`
|
|
582
|
+
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${-dotSize * 1.5}` +
|
|
583
|
+
`z`);
|
|
586
584
|
}
|
|
587
585
|
});
|
|
588
586
|
}
|
|
589
|
-
|
|
587
|
+
basicClassy(args) {
|
|
590
588
|
const { size, x, y } = args;
|
|
591
589
|
const dotSize = size / 7;
|
|
592
|
-
this.
|
|
590
|
+
this.rotateFigure({
|
|
593
591
|
...args,
|
|
594
592
|
draw: () => {
|
|
595
|
-
this._element = this.
|
|
593
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
596
594
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
597
595
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
598
596
|
`v ${2 * dotSize}` +
|
|
@@ -614,13 +612,13 @@ class QRCornerSquare {
|
|
|
614
612
|
}
|
|
615
613
|
});
|
|
616
614
|
}
|
|
617
|
-
|
|
615
|
+
basicInpoint(args) {
|
|
618
616
|
const { size, x, y } = args;
|
|
619
617
|
const dotSize = size / 7;
|
|
620
|
-
this.
|
|
618
|
+
this.rotateFigure({
|
|
621
619
|
...args,
|
|
622
620
|
draw: () => {
|
|
623
|
-
this._element = this.
|
|
621
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
624
622
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
625
623
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
626
624
|
`v ${2 * dotSize}` +
|
|
@@ -630,6 +628,7 @@ class QRCornerSquare {
|
|
|
630
628
|
`a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${-dotSize * 2.5}` +
|
|
631
629
|
`h ${-2 * dotSize}` +
|
|
632
630
|
`a ${2.5 * dotSize} ${2.5 * dotSize}, 0, 0, 0, ${-dotSize * 2.5} ${dotSize * 2.5}` +
|
|
631
|
+
"z" +
|
|
633
632
|
`M ${x + 2.5 * dotSize} ${y + dotSize}` +
|
|
634
633
|
`h ${2 * dotSize}` +
|
|
635
634
|
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${dotSize * 1.5}` +
|
|
@@ -637,100 +636,103 @@ class QRCornerSquare {
|
|
|
637
636
|
`h ${-3.5 * dotSize}` +
|
|
638
637
|
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${-dotSize * 1.5} ${-dotSize * 1.5}` +
|
|
639
638
|
`v ${-2 * dotSize}` +
|
|
640
|
-
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${-dotSize * 1.5}`
|
|
639
|
+
`a ${1.5 * dotSize} ${1.5 * dotSize}, 0, 0, 1, ${dotSize * 1.5} ${-dotSize * 1.5}` +
|
|
640
|
+
`z`);
|
|
641
641
|
}
|
|
642
642
|
});
|
|
643
643
|
}
|
|
644
|
-
|
|
645
|
-
this.
|
|
644
|
+
drawDot({ x, y, size, rotation }) {
|
|
645
|
+
this.basicDot({ x, y, size, rotation });
|
|
646
646
|
}
|
|
647
|
-
|
|
648
|
-
this.
|
|
647
|
+
drawSquare({ x, y, size, rotation }) {
|
|
648
|
+
this.basicSquare({ x, y, size, rotation });
|
|
649
649
|
}
|
|
650
|
-
|
|
651
|
-
this.
|
|
650
|
+
drawExtraRounded({ x, y, size, rotation }) {
|
|
651
|
+
this.basicExtraRounded({ x, y, size, rotation });
|
|
652
652
|
}
|
|
653
|
-
|
|
654
|
-
this.
|
|
653
|
+
drawClassy({ x, y, size, rotation }) {
|
|
654
|
+
this.basicClassy({ x, y, size, rotation });
|
|
655
655
|
}
|
|
656
|
-
|
|
657
|
-
this.
|
|
656
|
+
drawInpoint({ x, y, size, rotation }) {
|
|
657
|
+
this.basicInpoint({ x, y, size, rotation });
|
|
658
658
|
}
|
|
659
|
-
|
|
660
|
-
this.
|
|
659
|
+
drawOutpoint({ x, y, size, rotation }) {
|
|
660
|
+
this.basicInpoint({ x, y, size, rotation: (rotation || 0) + Math.PI });
|
|
661
661
|
}
|
|
662
662
|
}
|
|
663
663
|
|
|
664
664
|
class QRDot {
|
|
665
|
-
|
|
666
|
-
this.
|
|
667
|
-
|
|
668
|
-
|
|
665
|
+
get element() {
|
|
666
|
+
return this._element;
|
|
667
|
+
}
|
|
668
|
+
constructor(type, document) {
|
|
669
|
+
this.type = type;
|
|
670
|
+
this.document = document;
|
|
669
671
|
}
|
|
670
|
-
draw(
|
|
671
|
-
const type = this.
|
|
672
|
+
draw(args) {
|
|
673
|
+
const type = this.type;
|
|
672
674
|
let drawFunction;
|
|
673
675
|
switch (type) {
|
|
674
|
-
case DotType.
|
|
675
|
-
drawFunction = this.
|
|
676
|
+
case DotType.dot:
|
|
677
|
+
drawFunction = this.drawDot;
|
|
676
678
|
break;
|
|
677
|
-
case DotType.
|
|
678
|
-
drawFunction = this.
|
|
679
|
+
case DotType.randomDot:
|
|
680
|
+
drawFunction = this.drawRandomDot;
|
|
679
681
|
break;
|
|
680
682
|
case DotType.classy:
|
|
681
|
-
drawFunction = this.
|
|
683
|
+
drawFunction = this.drawClassy;
|
|
682
684
|
break;
|
|
683
685
|
case DotType.classyRounded:
|
|
684
|
-
drawFunction = this.
|
|
686
|
+
drawFunction = this.drawClassyRounded;
|
|
685
687
|
break;
|
|
686
688
|
case DotType.rounded:
|
|
687
|
-
drawFunction = this.
|
|
689
|
+
drawFunction = this.drawRounded;
|
|
688
690
|
break;
|
|
689
|
-
case DotType.
|
|
690
|
-
drawFunction = this.
|
|
691
|
+
case DotType.verticalLine:
|
|
692
|
+
drawFunction = this.drawVerticalLine;
|
|
691
693
|
break;
|
|
692
|
-
case DotType.
|
|
693
|
-
drawFunction = this.
|
|
694
|
+
case DotType.horizontalLine:
|
|
695
|
+
drawFunction = this.drawHorizontalLine;
|
|
694
696
|
break;
|
|
695
697
|
case DotType.extraRounded:
|
|
696
|
-
drawFunction = this.
|
|
698
|
+
drawFunction = this.drawExtraRounded;
|
|
697
699
|
break;
|
|
698
700
|
case DotType.diamond:
|
|
699
|
-
drawFunction = this.
|
|
701
|
+
drawFunction = this.drawDiamond;
|
|
700
702
|
break;
|
|
701
703
|
case DotType.smallSquare:
|
|
702
|
-
drawFunction = this.
|
|
704
|
+
drawFunction = this.drawSmallSquare;
|
|
703
705
|
break;
|
|
704
706
|
case DotType.square:
|
|
705
707
|
default:
|
|
706
|
-
drawFunction = this.
|
|
708
|
+
drawFunction = this.drawSquare;
|
|
707
709
|
}
|
|
708
|
-
drawFunction.call(this,
|
|
710
|
+
drawFunction.call(this, args);
|
|
709
711
|
}
|
|
710
|
-
|
|
712
|
+
rotateFigure({ x, y, size, rotation = 0, draw }) {
|
|
711
713
|
const cx = x + size / 2;
|
|
712
714
|
const cy = y + size / 2;
|
|
713
715
|
draw();
|
|
714
716
|
this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`);
|
|
715
717
|
}
|
|
716
|
-
|
|
718
|
+
basicDot(args) {
|
|
717
719
|
const { size, x, y } = args;
|
|
718
|
-
this.
|
|
720
|
+
this.rotateFigure({
|
|
719
721
|
...args,
|
|
720
722
|
draw: () => {
|
|
721
|
-
this._element = this.
|
|
723
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
722
724
|
this._element.setAttribute("cx", String(x + size / 2));
|
|
723
725
|
this._element.setAttribute("cy", String(y + size / 2));
|
|
724
726
|
this._element.setAttribute("r", String(size / 2));
|
|
725
727
|
}
|
|
726
728
|
});
|
|
727
729
|
}
|
|
728
|
-
|
|
730
|
+
basicSquare(args) {
|
|
729
731
|
const { size, x, y } = args;
|
|
730
|
-
this.
|
|
732
|
+
this.rotateFigure({
|
|
731
733
|
...args,
|
|
732
734
|
draw: () => {
|
|
733
|
-
this._element = this.
|
|
735
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
734
736
|
this._element.setAttribute("x", String(x));
|
|
735
737
|
this._element.setAttribute("y", String(y));
|
|
736
738
|
this._element.setAttribute("width", String(size));
|
|
@@ -739,12 +741,12 @@ class QRDot {
|
|
|
739
741
|
});
|
|
740
742
|
}
|
|
741
743
|
//if rotation === 0 - right side is rounded
|
|
742
|
-
|
|
744
|
+
basicSideRounded(args) {
|
|
743
745
|
const { size, x, y } = args;
|
|
744
|
-
this.
|
|
746
|
+
this.rotateFigure({
|
|
745
747
|
...args,
|
|
746
748
|
draw: () => {
|
|
747
|
-
this._element = this.
|
|
749
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
748
750
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
749
751
|
`v ${size}` + //draw line to left bottom corner
|
|
750
752
|
`h ${size / 2}` + //draw line to left bottom corner + half of size right
|
|
@@ -754,12 +756,12 @@ class QRDot {
|
|
|
754
756
|
});
|
|
755
757
|
}
|
|
756
758
|
//if rotation === 0 - top right corner is rounded
|
|
757
|
-
|
|
759
|
+
basicCornerRounded(args) {
|
|
758
760
|
const { size, x, y } = args;
|
|
759
|
-
this.
|
|
761
|
+
this.rotateFigure({
|
|
760
762
|
...args,
|
|
761
763
|
draw: () => {
|
|
762
|
-
this._element = this.
|
|
764
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
763
765
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
764
766
|
`v ${size}` + //draw line to left bottom corner
|
|
765
767
|
`h ${size}` + //draw line to right bottom corner
|
|
@@ -770,12 +772,12 @@ class QRDot {
|
|
|
770
772
|
});
|
|
771
773
|
}
|
|
772
774
|
//if rotation === 0 - top right corner is rounded
|
|
773
|
-
|
|
775
|
+
basicCornerExtraRounded(args) {
|
|
774
776
|
const { size, x, y } = args;
|
|
775
|
-
this.
|
|
777
|
+
this.rotateFigure({
|
|
776
778
|
...args,
|
|
777
779
|
draw: () => {
|
|
778
|
-
this._element = this.
|
|
780
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
779
781
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
780
782
|
`v ${size}` + //draw line to left bottom corner
|
|
781
783
|
`h ${size}` + //draw line to right bottom corner
|
|
@@ -785,12 +787,12 @@ class QRDot {
|
|
|
785
787
|
});
|
|
786
788
|
}
|
|
787
789
|
//if rotation === 0 - left bottom and right top corners are rounded
|
|
788
|
-
|
|
790
|
+
basicCornersRounded(args) {
|
|
789
791
|
const { size, x, y } = args;
|
|
790
|
-
this.
|
|
792
|
+
this.rotateFigure({
|
|
791
793
|
...args,
|
|
792
794
|
draw: () => {
|
|
793
|
-
this._element = this.
|
|
795
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
794
796
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to left top position
|
|
795
797
|
`v ${size / 2}` + //draw line to left top corner + half of size bottom
|
|
796
798
|
`a ${size / 2} ${size / 2}, 0, 0, 0, ${size / 2} ${size / 2}` + // draw rounded left bottom corner
|
|
@@ -801,38 +803,38 @@ class QRDot {
|
|
|
801
803
|
}
|
|
802
804
|
});
|
|
803
805
|
}
|
|
804
|
-
|
|
805
|
-
this.
|
|
806
|
+
drawDot({ x, y, size }) {
|
|
807
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
806
808
|
}
|
|
807
|
-
|
|
809
|
+
drawRandomDot({ x, y, size }) {
|
|
808
810
|
const randomFactor = Math.random() * (1 - 0.75) + 0.75;
|
|
809
|
-
this.
|
|
811
|
+
this.basicDot({ x, y, size: size * randomFactor, rotation: 0 });
|
|
810
812
|
}
|
|
811
|
-
|
|
812
|
-
this.
|
|
813
|
+
drawSquare({ x, y, size }) {
|
|
814
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
813
815
|
}
|
|
814
|
-
|
|
816
|
+
drawSmallSquare({ x, y, size }) {
|
|
815
817
|
const originalSize = size;
|
|
816
818
|
size = originalSize * 0.7;
|
|
817
819
|
x = x + originalSize * 0.15;
|
|
818
820
|
y = y + originalSize * 0.15;
|
|
819
|
-
this.
|
|
821
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
820
822
|
}
|
|
821
|
-
|
|
822
|
-
this.
|
|
823
|
+
drawDiamond({ x, y, size }) {
|
|
824
|
+
this.basicSquare({ x, y, size, rotation: Math.PI / 4 });
|
|
823
825
|
}
|
|
824
|
-
|
|
826
|
+
drawRounded({ x, y, size, getNeighbor }) {
|
|
825
827
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
826
828
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
827
829
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
828
830
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
829
831
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
830
832
|
if (neighborsCount === 0) {
|
|
831
|
-
this.
|
|
833
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
832
834
|
return;
|
|
833
835
|
}
|
|
834
836
|
if (neighborsCount > 2 || (leftNeighbor && rightNeighbor) || (topNeighbor && bottomNeighbor)) {
|
|
835
|
-
this.
|
|
837
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
836
838
|
return;
|
|
837
839
|
}
|
|
838
840
|
if (neighborsCount === 2) {
|
|
@@ -846,7 +848,7 @@ class QRDot {
|
|
|
846
848
|
else if (rightNeighbor && bottomNeighbor) {
|
|
847
849
|
rotation = -Math.PI / 2;
|
|
848
850
|
}
|
|
849
|
-
this.
|
|
851
|
+
this.basicCornerRounded({ x, y, size, rotation });
|
|
850
852
|
return;
|
|
851
853
|
}
|
|
852
854
|
if (neighborsCount === 1) {
|
|
@@ -860,11 +862,11 @@ class QRDot {
|
|
|
860
862
|
else if (bottomNeighbor) {
|
|
861
863
|
rotation = -Math.PI / 2;
|
|
862
864
|
}
|
|
863
|
-
this.
|
|
865
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
864
866
|
return;
|
|
865
867
|
}
|
|
866
868
|
}
|
|
867
|
-
|
|
869
|
+
drawVerticalLine({ x, y, size, getNeighbor }) {
|
|
868
870
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
869
871
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
870
872
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
@@ -873,25 +875,25 @@ class QRDot {
|
|
|
873
875
|
if (neighborsCount === 0 ||
|
|
874
876
|
(leftNeighbor && !(topNeighbor || bottomNeighbor)) ||
|
|
875
877
|
(rightNeighbor && !(topNeighbor || bottomNeighbor))) {
|
|
876
|
-
this.
|
|
878
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
877
879
|
return;
|
|
878
880
|
}
|
|
879
881
|
if (topNeighbor && bottomNeighbor) {
|
|
880
|
-
this.
|
|
882
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
881
883
|
return;
|
|
882
884
|
}
|
|
883
885
|
if (topNeighbor && !bottomNeighbor) {
|
|
884
886
|
const rotation = Math.PI / 2;
|
|
885
|
-
this.
|
|
887
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
886
888
|
return;
|
|
887
889
|
}
|
|
888
890
|
if (bottomNeighbor && !topNeighbor) {
|
|
889
891
|
const rotation = -Math.PI / 2;
|
|
890
|
-
this.
|
|
892
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
891
893
|
return;
|
|
892
894
|
}
|
|
893
895
|
}
|
|
894
|
-
|
|
896
|
+
drawHorizontalLine({ x, y, size, getNeighbor }) {
|
|
895
897
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
896
898
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
897
899
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
@@ -900,36 +902,36 @@ class QRDot {
|
|
|
900
902
|
if (neighborsCount === 0 ||
|
|
901
903
|
(topNeighbor && !(leftNeighbor || rightNeighbor)) ||
|
|
902
904
|
(bottomNeighbor && !(leftNeighbor || rightNeighbor))) {
|
|
903
|
-
this.
|
|
905
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
904
906
|
return;
|
|
905
907
|
}
|
|
906
908
|
if (leftNeighbor && rightNeighbor) {
|
|
907
|
-
this.
|
|
909
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
908
910
|
return;
|
|
909
911
|
}
|
|
910
912
|
if (leftNeighbor && !rightNeighbor) {
|
|
911
913
|
const rotation = 0;
|
|
912
|
-
this.
|
|
914
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
913
915
|
return;
|
|
914
916
|
}
|
|
915
917
|
if (rightNeighbor && !leftNeighbor) {
|
|
916
918
|
const rotation = Math.PI;
|
|
917
|
-
this.
|
|
919
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
918
920
|
return;
|
|
919
921
|
}
|
|
920
922
|
}
|
|
921
|
-
|
|
923
|
+
drawExtraRounded({ x, y, size, getNeighbor }) {
|
|
922
924
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
923
925
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
924
926
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
925
927
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
926
928
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
927
929
|
if (neighborsCount === 0) {
|
|
928
|
-
this.
|
|
930
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
929
931
|
return;
|
|
930
932
|
}
|
|
931
933
|
if (neighborsCount > 2 || (leftNeighbor && rightNeighbor) || (topNeighbor && bottomNeighbor)) {
|
|
932
|
-
this.
|
|
934
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
933
935
|
return;
|
|
934
936
|
}
|
|
935
937
|
if (neighborsCount === 2) {
|
|
@@ -943,7 +945,7 @@ class QRDot {
|
|
|
943
945
|
else if (rightNeighbor && bottomNeighbor) {
|
|
944
946
|
rotation = -Math.PI / 2;
|
|
945
947
|
}
|
|
946
|
-
this.
|
|
948
|
+
this.basicCornerExtraRounded({ x, y, size, rotation });
|
|
947
949
|
return;
|
|
948
950
|
}
|
|
949
951
|
if (neighborsCount === 1) {
|
|
@@ -957,49 +959,49 @@ class QRDot {
|
|
|
957
959
|
else if (bottomNeighbor) {
|
|
958
960
|
rotation = -Math.PI / 2;
|
|
959
961
|
}
|
|
960
|
-
this.
|
|
962
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
961
963
|
return;
|
|
962
964
|
}
|
|
963
965
|
}
|
|
964
|
-
|
|
966
|
+
drawClassy({ x, y, size, getNeighbor }) {
|
|
965
967
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
966
968
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
967
969
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
968
970
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
969
971
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
970
972
|
if (neighborsCount === 0) {
|
|
971
|
-
this.
|
|
973
|
+
this.basicCornersRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
972
974
|
return;
|
|
973
975
|
}
|
|
974
976
|
if (!leftNeighbor && !topNeighbor) {
|
|
975
|
-
this.
|
|
977
|
+
this.basicCornerRounded({ x, y, size, rotation: -Math.PI / 2 });
|
|
976
978
|
return;
|
|
977
979
|
}
|
|
978
980
|
if (!rightNeighbor && !bottomNeighbor) {
|
|
979
|
-
this.
|
|
981
|
+
this.basicCornerRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
980
982
|
return;
|
|
981
983
|
}
|
|
982
|
-
this.
|
|
984
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
983
985
|
}
|
|
984
|
-
|
|
986
|
+
drawClassyRounded({ x, y, size, getNeighbor }) {
|
|
985
987
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
986
988
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
987
989
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
988
990
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
989
991
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
990
992
|
if (neighborsCount === 0) {
|
|
991
|
-
this.
|
|
993
|
+
this.basicCornersRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
992
994
|
return;
|
|
993
995
|
}
|
|
994
996
|
if (!leftNeighbor && !topNeighbor) {
|
|
995
|
-
this.
|
|
997
|
+
this.basicCornerExtraRounded({ x, y, size, rotation: -Math.PI / 2 });
|
|
996
998
|
return;
|
|
997
999
|
}
|
|
998
1000
|
if (!rightNeighbor && !bottomNeighbor) {
|
|
999
|
-
this.
|
|
1001
|
+
this.basicCornerExtraRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
1000
1002
|
return;
|
|
1001
1003
|
}
|
|
1002
|
-
this.
|
|
1004
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
1003
1005
|
}
|
|
1004
1006
|
}
|
|
1005
1007
|
|
|
@@ -1029,24 +1031,21 @@ const browserImageTools = {
|
|
|
1029
1031
|
}
|
|
1030
1032
|
});
|
|
1031
1033
|
},
|
|
1032
|
-
getSize(
|
|
1034
|
+
getSize(src, crossOrigin) {
|
|
1033
1035
|
return new Promise((resolve, reject) => {
|
|
1034
|
-
if (!options.image) {
|
|
1035
|
-
return reject("Image is not defined");
|
|
1036
|
-
}
|
|
1037
1036
|
const image = new Image();
|
|
1038
|
-
if (
|
|
1039
|
-
image.crossOrigin =
|
|
1037
|
+
if (crossOrigin === "string") {
|
|
1038
|
+
image.crossOrigin = crossOrigin;
|
|
1040
1039
|
}
|
|
1041
1040
|
image.onload = () => {
|
|
1042
1041
|
resolve({ width: image.width, height: image.height });
|
|
1043
1042
|
};
|
|
1044
1043
|
image.onerror = image.onabort = reject;
|
|
1045
|
-
if (typeof
|
|
1046
|
-
image.src =
|
|
1044
|
+
if (typeof src == "string")
|
|
1045
|
+
image.src = src;
|
|
1047
1046
|
else
|
|
1048
1047
|
browserImageTools
|
|
1049
|
-
.toDataURL(
|
|
1048
|
+
.toDataURL(src)
|
|
1050
1049
|
.then((url) => (image.src = url))
|
|
1051
1050
|
.catch(reject);
|
|
1052
1051
|
});
|
|
@@ -1151,43 +1150,42 @@ const alignmentCount = [
|
|
|
1151
1150
|
[1, 1]
|
|
1152
1151
|
];
|
|
1153
1152
|
class QRSVG {
|
|
1154
|
-
|
|
1153
|
+
get element() {
|
|
1154
|
+
return this._element;
|
|
1155
|
+
}
|
|
1155
1156
|
constructor(options) {
|
|
1156
|
-
this.
|
|
1157
|
-
this.
|
|
1157
|
+
this.options = options;
|
|
1158
|
+
this.document = options.document;
|
|
1159
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1158
1160
|
this._element.setAttribute("width", String(options.width));
|
|
1159
1161
|
this._element.setAttribute("height", String(options.height));
|
|
1160
1162
|
this._element.setAttribute("viewBox", `0 0 ${options.width} ${options.height}`);
|
|
1161
|
-
this.
|
|
1162
|
-
this._element.appendChild(this.
|
|
1163
|
-
this.
|
|
1164
|
-
this._options = options;
|
|
1163
|
+
this.defs = this.document.createElementNS("http://www.w3.org/2000/svg", "defs");
|
|
1164
|
+
this._element.appendChild(this.defs);
|
|
1165
|
+
this.imageTools = options.imageTools || browserImageTools;
|
|
1165
1166
|
}
|
|
1166
1167
|
get width() {
|
|
1167
|
-
return this.
|
|
1168
|
+
return this.options.width;
|
|
1168
1169
|
}
|
|
1169
1170
|
get height() {
|
|
1170
|
-
return this.
|
|
1171
|
-
}
|
|
1172
|
-
getElement() {
|
|
1173
|
-
return this._element;
|
|
1171
|
+
return this.options.height;
|
|
1174
1172
|
}
|
|
1175
1173
|
async drawQR(qr) {
|
|
1176
1174
|
const count = qr.getModuleCount();
|
|
1177
1175
|
const typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10);
|
|
1178
|
-
const dotSize = this.
|
|
1176
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1179
1177
|
let drawImageSize = {
|
|
1180
1178
|
hideXDots: 0,
|
|
1181
1179
|
hideYDots: 0,
|
|
1182
1180
|
width: 0,
|
|
1183
1181
|
height: 0
|
|
1184
1182
|
};
|
|
1185
|
-
this.
|
|
1186
|
-
if (this.
|
|
1183
|
+
this.qr = qr;
|
|
1184
|
+
if (this.options.image) {
|
|
1187
1185
|
//We need it to get image size
|
|
1188
|
-
const size = await this.
|
|
1189
|
-
const { imageOptions,
|
|
1190
|
-
const coverLevel = imageOptions.imageSize *
|
|
1186
|
+
const size = await this.imageTools.getSize(this.options.image, this.options.imageOptions.crossOrigin);
|
|
1187
|
+
const { imageOptions, errorCorrectionPercent } = this.options;
|
|
1188
|
+
const coverLevel = imageOptions.imageSize * errorCorrectionPercent;
|
|
1191
1189
|
const alignment = alignmentCount.find((v) => v[0] <= typeNumber) || [0, 0];
|
|
1192
1190
|
const maxHiddenDots = Math.floor(coverLevel * (count * count - 3 * 8 * 8 - 2 * (count - 16) - alignment[1] * 25));
|
|
1193
1191
|
drawImageSize = calculateImageSize({
|
|
@@ -1201,7 +1199,7 @@ class QRSVG {
|
|
|
1201
1199
|
}
|
|
1202
1200
|
this.drawBackground();
|
|
1203
1201
|
this.drawDots((i, j) => {
|
|
1204
|
-
if (this.
|
|
1202
|
+
if (this.options.imageOptions.hideBackgroundDots) {
|
|
1205
1203
|
if (i >= (count - drawImageSize.hideXDots) / 2 &&
|
|
1206
1204
|
i < (count + drawImageSize.hideXDots) / 2 &&
|
|
1207
1205
|
j >= (count - drawImageSize.hideYDots) / 2 &&
|
|
@@ -1218,17 +1216,17 @@ class QRSVG {
|
|
|
1218
1216
|
return true;
|
|
1219
1217
|
});
|
|
1220
1218
|
this.drawCorners();
|
|
1221
|
-
if (this.
|
|
1219
|
+
if (this.options.image && drawImageSize.width > 0 && drawImageSize.height > 0) {
|
|
1222
1220
|
await this.drawImage({ width: drawImageSize.width, height: drawImageSize.height, count, dotSize });
|
|
1223
1221
|
}
|
|
1224
1222
|
}
|
|
1225
1223
|
drawBackground() {
|
|
1226
1224
|
const element = this._element;
|
|
1227
|
-
const options = this.
|
|
1225
|
+
const options = this.options;
|
|
1228
1226
|
if (element && options.backgroundOptions) {
|
|
1229
1227
|
const gradientOptions = options.backgroundOptions.gradient;
|
|
1230
1228
|
const color = options.backgroundOptions.color;
|
|
1231
|
-
this.
|
|
1229
|
+
this.createColor({
|
|
1232
1230
|
options: gradientOptions,
|
|
1233
1231
|
color: color,
|
|
1234
1232
|
additionalRotation: 0,
|
|
@@ -1239,50 +1237,55 @@ class QRSVG {
|
|
|
1239
1237
|
name: "background-color"
|
|
1240
1238
|
});
|
|
1241
1239
|
const size = Math.min(options.width, options.height);
|
|
1242
|
-
const element = this.
|
|
1243
|
-
[this.
|
|
1244
|
-
this.
|
|
1240
|
+
const element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
1241
|
+
[this.backgroundMask, this.backgroundMaskGroup] = this.createMask("mask-background-color");
|
|
1242
|
+
this.defs.appendChild(this.backgroundMask);
|
|
1245
1243
|
element.setAttribute("x", String((options.width - size) / 2));
|
|
1246
1244
|
element.setAttribute("y", String((options.height - size) / 2));
|
|
1247
1245
|
element.setAttribute("width", String(size));
|
|
1248
1246
|
element.setAttribute("height", String(size));
|
|
1249
1247
|
element.setAttribute("rx", String((size / 2) * (options.backgroundOptions.round || 0)));
|
|
1250
|
-
this.
|
|
1248
|
+
this.backgroundMaskGroup.appendChild(element);
|
|
1251
1249
|
}
|
|
1252
1250
|
}
|
|
1253
1251
|
drawDots(filter) {
|
|
1254
|
-
if (!this.
|
|
1252
|
+
if (!this.qr) {
|
|
1255
1253
|
throw "QR code is not defined";
|
|
1256
1254
|
}
|
|
1257
|
-
const options = this.
|
|
1258
|
-
const count = this.
|
|
1255
|
+
const options = this.options;
|
|
1256
|
+
const count = this.qr.getModuleCount();
|
|
1259
1257
|
if (count > options.width || count > options.height) {
|
|
1260
1258
|
throw "The canvas is too small.";
|
|
1261
1259
|
}
|
|
1262
1260
|
const minSize = Math.min(options.width, options.height);
|
|
1263
|
-
const dotSize = this.
|
|
1261
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1264
1262
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
1265
1263
|
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
1266
|
-
const dot = new QRDot(
|
|
1267
|
-
[this.
|
|
1268
|
-
this.
|
|
1264
|
+
const dot = new QRDot(options.dotsOptions.type, this.document);
|
|
1265
|
+
[this.dotsMask, this.dotsMaskGroup] = this.createMask("mask-dot-color");
|
|
1266
|
+
this.defs.appendChild(this.dotsMask);
|
|
1269
1267
|
for (let i = 0; i < count; i++) {
|
|
1270
1268
|
for (let j = 0; j < count; j++) {
|
|
1271
1269
|
if (filter && !filter(i, j)) {
|
|
1272
1270
|
continue;
|
|
1273
1271
|
}
|
|
1274
|
-
if (!this.
|
|
1272
|
+
if (!this.qr?.isDark(j, i)) {
|
|
1275
1273
|
continue;
|
|
1276
1274
|
}
|
|
1277
|
-
dot.draw(
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1275
|
+
dot.draw({
|
|
1276
|
+
x: xBeginning + i * dotSize,
|
|
1277
|
+
y: yBeginning + j * dotSize,
|
|
1278
|
+
size: dotSize,
|
|
1279
|
+
getNeighbor: (xOffset, yOffset) => {
|
|
1280
|
+
if (i + xOffset < 0 || j + yOffset < 0 || i + xOffset >= count || j + yOffset >= count)
|
|
1281
|
+
return false;
|
|
1282
|
+
if (filter && !filter(i + xOffset, j + yOffset))
|
|
1283
|
+
return false;
|
|
1284
|
+
return !!this.qr && this.qr.isDark(j + yOffset, i + xOffset);
|
|
1285
|
+
}
|
|
1283
1286
|
});
|
|
1284
|
-
if (dot.
|
|
1285
|
-
this.
|
|
1287
|
+
if (dot.element && this.dotsMask) {
|
|
1288
|
+
this.dotsMaskGroup.appendChild(dot.element);
|
|
1286
1289
|
}
|
|
1287
1290
|
}
|
|
1288
1291
|
}
|
|
@@ -1290,7 +1293,7 @@ class QRSVG {
|
|
|
1290
1293
|
let colorY = yBeginning;
|
|
1291
1294
|
let colorCount = count;
|
|
1292
1295
|
if (options.shape === ShapeType.circle) {
|
|
1293
|
-
const margin = (this.
|
|
1296
|
+
const margin = (this.options.backgroundOptions && this.options.backgroundOptions.margin) || 0;
|
|
1294
1297
|
const additionalDots = Math.floor((minSize / dotSize - count - 2 * margin) / 2);
|
|
1295
1298
|
const fakeCount = count + additionalDots * 2;
|
|
1296
1299
|
const xFakeBeginning = xBeginning - additionalDots * dotSize;
|
|
@@ -1315,7 +1318,7 @@ class QRSVG {
|
|
|
1315
1318
|
continue;
|
|
1316
1319
|
}
|
|
1317
1320
|
//Get random dots from QR code to show it outside of QR code
|
|
1318
|
-
fakeMatrix[i][j] = this.
|
|
1321
|
+
fakeMatrix[i][j] = this.qr.isDark(j - 2 * additionalDots < 0 ? j : j >= count ? j - 2 * additionalDots : j - additionalDots, i - 2 * additionalDots < 0 ? i : i >= count ? i - 2 * additionalDots : i - additionalDots)
|
|
1319
1322
|
? 1
|
|
1320
1323
|
: 0;
|
|
1321
1324
|
}
|
|
@@ -1324,16 +1327,21 @@ class QRSVG {
|
|
|
1324
1327
|
for (let j = 0; j < fakeCount; j++) {
|
|
1325
1328
|
if (!fakeMatrix[i][j])
|
|
1326
1329
|
continue;
|
|
1327
|
-
dot.draw(
|
|
1328
|
-
|
|
1330
|
+
dot.draw({
|
|
1331
|
+
x: xFakeBeginning + i * dotSize,
|
|
1332
|
+
y: yFakeBeginning + j * dotSize,
|
|
1333
|
+
size: dotSize,
|
|
1334
|
+
getNeighbor: (xOffset, yOffset) => {
|
|
1335
|
+
return !!fakeMatrix[i + xOffset]?.[j + yOffset];
|
|
1336
|
+
}
|
|
1329
1337
|
});
|
|
1330
|
-
if (dot.
|
|
1331
|
-
this.
|
|
1338
|
+
if (dot.element && this.dotsMask) {
|
|
1339
|
+
this.dotsMaskGroup.appendChild(dot.element);
|
|
1332
1340
|
}
|
|
1333
1341
|
}
|
|
1334
1342
|
}
|
|
1335
1343
|
}
|
|
1336
|
-
this.
|
|
1344
|
+
this.createColor({
|
|
1337
1345
|
options: options.dotsOptions?.gradient,
|
|
1338
1346
|
color: options.dotsOptions.color,
|
|
1339
1347
|
additionalRotation: 0,
|
|
@@ -1345,16 +1353,16 @@ class QRSVG {
|
|
|
1345
1353
|
});
|
|
1346
1354
|
}
|
|
1347
1355
|
drawCorners() {
|
|
1348
|
-
if (!this.
|
|
1356
|
+
if (!this.qr) {
|
|
1349
1357
|
throw "QR code is not defined";
|
|
1350
1358
|
}
|
|
1351
1359
|
const element = this._element;
|
|
1352
|
-
const options = this.
|
|
1360
|
+
const options = this.options;
|
|
1353
1361
|
if (!element) {
|
|
1354
1362
|
throw "Element code is not defined";
|
|
1355
1363
|
}
|
|
1356
|
-
const count = this.
|
|
1357
|
-
const dotSize = this.
|
|
1364
|
+
const count = this.qr.getModuleCount();
|
|
1365
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1358
1366
|
const cornersSquareSize = dotSize * 7;
|
|
1359
1367
|
const cornersDotSize = dotSize * 3;
|
|
1360
1368
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
@@ -1366,16 +1374,16 @@ class QRSVG {
|
|
|
1366
1374
|
].forEach(([column, row, rotation]) => {
|
|
1367
1375
|
const x = xBeginning + column * dotSize * (count - 7);
|
|
1368
1376
|
const y = yBeginning + row * dotSize * (count - 7);
|
|
1369
|
-
let cornersSquareMask = this.
|
|
1370
|
-
let cornersSquareMaskGroup = this.
|
|
1371
|
-
let cornersDotMask = this.
|
|
1372
|
-
let cornersDotMaskGroup = this.
|
|
1377
|
+
let cornersSquareMask = this.dotsMask;
|
|
1378
|
+
let cornersSquareMaskGroup = this.dotsMaskGroup;
|
|
1379
|
+
let cornersDotMask = this.dotsMask;
|
|
1380
|
+
let cornersDotMaskGroup = this.dotsMaskGroup;
|
|
1373
1381
|
if (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) {
|
|
1374
|
-
[cornersSquareMask, cornersSquareMaskGroup] = this.
|
|
1375
|
-
this.
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
this.
|
|
1382
|
+
[cornersSquareMask, cornersSquareMaskGroup] = this.createMask(`mask-corners-square-color-${column}-${row}`);
|
|
1383
|
+
this.defs.appendChild(cornersSquareMask);
|
|
1384
|
+
cornersDotMask = cornersSquareMask;
|
|
1385
|
+
cornersDotMaskGroup = cornersSquareMaskGroup;
|
|
1386
|
+
this.createColor({
|
|
1379
1387
|
options: options.cornersSquareOptions?.gradient,
|
|
1380
1388
|
color: options.cornersSquareOptions?.color,
|
|
1381
1389
|
additionalRotation: rotation,
|
|
@@ -1387,36 +1395,40 @@ class QRSVG {
|
|
|
1387
1395
|
});
|
|
1388
1396
|
}
|
|
1389
1397
|
if (options.cornersSquareOptions?.type) {
|
|
1390
|
-
const cornersSquare = new QRCornerSquare(
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1398
|
+
const cornersSquare = new QRCornerSquare(options.cornersSquareOptions.type, this.document);
|
|
1399
|
+
cornersSquare.draw({
|
|
1400
|
+
x,
|
|
1401
|
+
y,
|
|
1402
|
+
size: cornersSquareSize,
|
|
1403
|
+
rotation
|
|
1394
1404
|
});
|
|
1395
|
-
cornersSquare.
|
|
1396
|
-
|
|
1397
|
-
cornersSquareMaskGroup.appendChild(cornersSquare._element);
|
|
1405
|
+
if (cornersSquare.element && cornersSquareMaskGroup) {
|
|
1406
|
+
cornersSquareMaskGroup.appendChild(cornersSquare.element);
|
|
1398
1407
|
}
|
|
1399
1408
|
}
|
|
1400
1409
|
else {
|
|
1401
|
-
const dot = new QRDot(
|
|
1410
|
+
const dot = new QRDot(options.dotsOptions.type, this.document);
|
|
1402
1411
|
for (let i = 0; i < squareMask.length; i++) {
|
|
1403
1412
|
for (let j = 0; j < squareMask[i].length; j++) {
|
|
1404
1413
|
if (!squareMask[i]?.[j]) {
|
|
1405
1414
|
continue;
|
|
1406
1415
|
}
|
|
1407
|
-
dot.draw(
|
|
1408
|
-
|
|
1409
|
-
|
|
1416
|
+
dot.draw({
|
|
1417
|
+
x: x + i * dotSize,
|
|
1418
|
+
y: y + j * dotSize,
|
|
1419
|
+
size: dotSize,
|
|
1420
|
+
getNeighbor: (xOffset, yOffset) => !!squareMask[i + xOffset]?.[j + yOffset]
|
|
1421
|
+
});
|
|
1422
|
+
if (dot.element && cornersSquareMaskGroup) {
|
|
1423
|
+
cornersSquareMaskGroup.appendChild(dot.element);
|
|
1410
1424
|
}
|
|
1411
1425
|
}
|
|
1412
1426
|
}
|
|
1413
1427
|
}
|
|
1414
1428
|
if (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) {
|
|
1415
|
-
[cornersDotMask, cornersDotMaskGroup] = this.
|
|
1416
|
-
this.
|
|
1417
|
-
this.
|
|
1418
|
-
this._cornersDotMaskGroup = cornersDotMaskGroup;
|
|
1419
|
-
this._createColor({
|
|
1429
|
+
[cornersDotMask, cornersDotMaskGroup] = this.createMask(`mask-corners-dot-color-${column}-${row}`);
|
|
1430
|
+
this.defs.appendChild(cornersDotMask);
|
|
1431
|
+
this.createColor({
|
|
1420
1432
|
options: options.cornersDotOptions?.gradient,
|
|
1421
1433
|
color: options.cornersDotOptions?.color,
|
|
1422
1434
|
additionalRotation: rotation,
|
|
@@ -1428,26 +1440,32 @@ class QRSVG {
|
|
|
1428
1440
|
});
|
|
1429
1441
|
}
|
|
1430
1442
|
if (options.cornersDotOptions?.type) {
|
|
1431
|
-
const cornersDot = new QRCornerDot(
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1443
|
+
const cornersDot = new QRCornerDot(options.cornersDotOptions.type, this.document);
|
|
1444
|
+
cornersDot.draw({
|
|
1445
|
+
x: x + dotSize * 2,
|
|
1446
|
+
y: y + dotSize * 2,
|
|
1447
|
+
size: cornersDotSize,
|
|
1448
|
+
rotation
|
|
1435
1449
|
});
|
|
1436
|
-
cornersDot.
|
|
1437
|
-
|
|
1438
|
-
cornersDotMaskGroup.appendChild(cornersDot._element);
|
|
1450
|
+
if (cornersDot.element && cornersDotMaskGroup) {
|
|
1451
|
+
cornersDotMaskGroup.appendChild(cornersDot.element);
|
|
1439
1452
|
}
|
|
1440
1453
|
}
|
|
1441
1454
|
else {
|
|
1442
|
-
const dot = new QRDot(
|
|
1455
|
+
const dot = new QRDot(options.dotsOptions.type, this.document);
|
|
1443
1456
|
for (let i = 0; i < dotMask.length; i++) {
|
|
1444
1457
|
for (let j = 0; j < dotMask[i].length; j++) {
|
|
1445
1458
|
if (!dotMask[i]?.[j]) {
|
|
1446
1459
|
continue;
|
|
1447
1460
|
}
|
|
1448
|
-
dot.draw(
|
|
1449
|
-
|
|
1450
|
-
|
|
1461
|
+
dot.draw({
|
|
1462
|
+
x: x + i * dotSize,
|
|
1463
|
+
y: y + j * dotSize,
|
|
1464
|
+
size: dotSize,
|
|
1465
|
+
getNeighbor: (xOffset, yOffset) => !!dotMask[i + xOffset]?.[j + yOffset]
|
|
1466
|
+
});
|
|
1467
|
+
if (dot.element && cornersDotMaskGroup) {
|
|
1468
|
+
cornersDotMaskGroup.appendChild(dot.element);
|
|
1451
1469
|
}
|
|
1452
1470
|
}
|
|
1453
1471
|
}
|
|
@@ -1455,7 +1473,7 @@ class QRSVG {
|
|
|
1455
1473
|
});
|
|
1456
1474
|
}
|
|
1457
1475
|
async drawImage({ width, height, count, dotSize }) {
|
|
1458
|
-
const options = this.
|
|
1476
|
+
const options = this.options;
|
|
1459
1477
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
1460
1478
|
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
1461
1479
|
const margin = options.imageOptions.margin * dotSize;
|
|
@@ -1463,8 +1481,8 @@ class QRSVG {
|
|
|
1463
1481
|
const dy = yBeginning + margin + (count * dotSize - height) / 2;
|
|
1464
1482
|
const dw = width - margin * 2;
|
|
1465
1483
|
const dh = height - margin * 2;
|
|
1466
|
-
const imageUrl = await this.
|
|
1467
|
-
let image = this.
|
|
1484
|
+
const imageUrl = await this.imageTools.toDataURL(options.image || "");
|
|
1485
|
+
let image = this.document.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
1468
1486
|
image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || "");
|
|
1469
1487
|
if (imageUrl.startsWith("data:image/svg+xml;")) {
|
|
1470
1488
|
let data = imageUrl.substring(19);
|
|
@@ -1492,10 +1510,9 @@ class QRSVG {
|
|
|
1492
1510
|
image.setAttribute("height", `${dh}px`);
|
|
1493
1511
|
this._element.appendChild(image);
|
|
1494
1512
|
}
|
|
1495
|
-
|
|
1496
|
-
_createColor({ options, color, additionalRotation, x, y, height, width, name }) {
|
|
1513
|
+
createColor({ options, color, additionalRotation, x, y, height, width, name }) {
|
|
1497
1514
|
const size = width > height ? width : height;
|
|
1498
|
-
const rect = this.
|
|
1515
|
+
const rect = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
1499
1516
|
rect.setAttribute("x", String(x));
|
|
1500
1517
|
rect.setAttribute("y", String(y));
|
|
1501
1518
|
rect.setAttribute("height", String(height));
|
|
@@ -1504,7 +1521,7 @@ class QRSVG {
|
|
|
1504
1521
|
if (options) {
|
|
1505
1522
|
let gradient;
|
|
1506
1523
|
if (options.type === GradientType.radial) {
|
|
1507
|
-
gradient = this.
|
|
1524
|
+
gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "radialGradient");
|
|
1508
1525
|
gradient.setAttribute("id", name);
|
|
1509
1526
|
gradient.setAttribute("gradientUnits", "userSpaceOnUse");
|
|
1510
1527
|
gradient.setAttribute("fx", String(x + width / 2));
|
|
@@ -1545,7 +1562,7 @@ class QRSVG {
|
|
|
1545
1562
|
y1 = y1 - height / 2;
|
|
1546
1563
|
x1 = x1 - width / 2 / Math.tan(rotation);
|
|
1547
1564
|
}
|
|
1548
|
-
gradient = this.
|
|
1565
|
+
gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "linearGradient");
|
|
1549
1566
|
gradient.setAttribute("id", name);
|
|
1550
1567
|
gradient.setAttribute("gradientUnits", "userSpaceOnUse");
|
|
1551
1568
|
gradient.setAttribute("x1", String(Math.round(x0)));
|
|
@@ -1554,29 +1571,29 @@ class QRSVG {
|
|
|
1554
1571
|
gradient.setAttribute("y2", String(Math.round(y1)));
|
|
1555
1572
|
}
|
|
1556
1573
|
options.colorStops.forEach(({ offset, color }) => {
|
|
1557
|
-
const stop = this.
|
|
1574
|
+
const stop = this.document.createElementNS("http://www.w3.org/2000/svg", "stop");
|
|
1558
1575
|
stop.setAttribute("offset", `${100 * offset}%`);
|
|
1559
1576
|
stop.setAttribute("stop-color", color);
|
|
1560
1577
|
gradient.appendChild(stop);
|
|
1561
1578
|
});
|
|
1562
1579
|
rect.setAttribute("fill", `url(#${name})`);
|
|
1563
|
-
this.
|
|
1580
|
+
this.defs.appendChild(gradient);
|
|
1564
1581
|
}
|
|
1565
1582
|
else if (color) {
|
|
1566
1583
|
rect.setAttribute("fill", color);
|
|
1567
1584
|
}
|
|
1568
1585
|
this._element.appendChild(rect);
|
|
1569
1586
|
}
|
|
1570
|
-
|
|
1571
|
-
const options = this.
|
|
1572
|
-
const mask = this.
|
|
1587
|
+
createMask(id) {
|
|
1588
|
+
const options = this.options;
|
|
1589
|
+
const mask = this.document.createElementNS("http://www.w3.org/2000/svg", "mask");
|
|
1573
1590
|
mask.setAttribute("id", id);
|
|
1574
1591
|
mask.setAttribute("maskUnits", "userSpaceOnUse");
|
|
1575
1592
|
mask.setAttribute("x", "0");
|
|
1576
1593
|
mask.setAttribute("y", "0");
|
|
1577
1594
|
mask.setAttribute("width", String(options.width));
|
|
1578
1595
|
mask.setAttribute("height", String(options.height));
|
|
1579
|
-
const group = this.
|
|
1596
|
+
const group = this.document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
1580
1597
|
group.setAttribute("fill", "#fff");
|
|
1581
1598
|
mask.appendChild(group);
|
|
1582
1599
|
return [mask, group];
|
|
@@ -1584,60 +1601,33 @@ class QRSVG {
|
|
|
1584
1601
|
}
|
|
1585
1602
|
|
|
1586
1603
|
let QRCodeStyling$1 = class QRCodeStyling {
|
|
1604
|
+
get size() {
|
|
1605
|
+
if (this.qrSVG)
|
|
1606
|
+
return {
|
|
1607
|
+
width: this.qrSVG.width,
|
|
1608
|
+
height: this.qrSVG.height
|
|
1609
|
+
};
|
|
1610
|
+
return undefined;
|
|
1611
|
+
}
|
|
1587
1612
|
constructor(options) {
|
|
1588
|
-
this.
|
|
1613
|
+
this.options = options ? sanitizeOptions(mergeDeep(defaultOptions, options)) : defaultOptions;
|
|
1589
1614
|
this.update();
|
|
1590
1615
|
}
|
|
1591
|
-
/** @ignore */
|
|
1592
|
-
static _clearContainer(container) {
|
|
1593
|
-
if (container) {
|
|
1594
|
-
container.innerHTML = "";
|
|
1595
|
-
}
|
|
1596
|
-
}
|
|
1597
|
-
/** @ignore */
|
|
1598
|
-
_setupSvg() {
|
|
1599
|
-
if (!this._qr) {
|
|
1600
|
-
return;
|
|
1601
|
-
}
|
|
1602
|
-
const count = Math.ceil((this._options.shape == ShapeType.circle ? Math.sqrt(2) : 1) * this._qr.getModuleCount());
|
|
1603
|
-
const margin = (this._options.backgroundOptions && this._options.backgroundOptions.margin) || 0;
|
|
1604
|
-
const size = Math.ceil(this._options.dotsOptions.size * (count + 2 * margin));
|
|
1605
|
-
const qrSVG = new QRSVG({
|
|
1606
|
-
...this._options,
|
|
1607
|
-
width: size,
|
|
1608
|
-
height: size
|
|
1609
|
-
});
|
|
1610
|
-
this._svg = qrSVG.getElement();
|
|
1611
|
-
this._svgDrawingPromise = qrSVG.drawQR(this._qr).then(() => {
|
|
1612
|
-
if (!this._svg)
|
|
1613
|
-
return;
|
|
1614
|
-
this._extension?.(qrSVG.getElement(), this._options);
|
|
1615
|
-
});
|
|
1616
|
-
}
|
|
1617
|
-
/** @ignore */
|
|
1618
|
-
async _getElement() {
|
|
1619
|
-
if (!this._qr)
|
|
1620
|
-
throw "QR code is empty";
|
|
1621
|
-
if (!this._svg || !this._svgDrawingPromise) {
|
|
1622
|
-
this._setupSvg();
|
|
1623
|
-
}
|
|
1624
|
-
await this._svgDrawingPromise;
|
|
1625
|
-
return this._svg;
|
|
1626
|
-
}
|
|
1627
1616
|
update(
|
|
1628
1617
|
/** The same options as for initialization */
|
|
1629
1618
|
options) {
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1619
|
+
if (this.container)
|
|
1620
|
+
this.container.innerHTML = "";
|
|
1621
|
+
this.options = options ? sanitizeOptions(mergeDeep(this.options, options)) : this.options;
|
|
1622
|
+
if (!this.options.data) {
|
|
1633
1623
|
return;
|
|
1634
1624
|
}
|
|
1635
|
-
if (this.
|
|
1636
|
-
Object.assign(qrcode.stringToBytesFuncs, this.
|
|
1637
|
-
delete this.
|
|
1625
|
+
if (this.options.stringToBytesFuncs) {
|
|
1626
|
+
Object.assign(qrcode.stringToBytesFuncs, this.options.stringToBytesFuncs);
|
|
1627
|
+
delete this.options.stringToBytesFuncs;
|
|
1638
1628
|
}
|
|
1639
|
-
this.
|
|
1640
|
-
let mode = this.
|
|
1629
|
+
this.qr = qrcode(this.options.qrOptions.typeNumber, this.options.qrOptions.errorCorrectionLevel);
|
|
1630
|
+
let mode = this.options.qrOptions.mode || getMode(this.options.data);
|
|
1641
1631
|
if (mode == Mode.unicode) {
|
|
1642
1632
|
qrcode.stringToBytes = qrcode.stringToBytesFuncs["UTF-8"];
|
|
1643
1633
|
mode = Mode.byte;
|
|
@@ -1645,10 +1635,10 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1645
1635
|
else {
|
|
1646
1636
|
qrcode.stringToBytes = qrcode.stringToBytesFuncs["default"];
|
|
1647
1637
|
}
|
|
1648
|
-
this.
|
|
1649
|
-
this.
|
|
1650
|
-
this.
|
|
1651
|
-
this.append(this.
|
|
1638
|
+
this.qr.addData(this.options.data, mode);
|
|
1639
|
+
this.qr.make();
|
|
1640
|
+
this.setupSvg();
|
|
1641
|
+
this.append(this.container);
|
|
1652
1642
|
}
|
|
1653
1643
|
append(
|
|
1654
1644
|
/** This container will be used for appending of the QR code */
|
|
@@ -1656,13 +1646,10 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1656
1646
|
if (!container) {
|
|
1657
1647
|
return;
|
|
1658
1648
|
}
|
|
1659
|
-
if (
|
|
1660
|
-
|
|
1661
|
-
}
|
|
1662
|
-
if (this._svg) {
|
|
1663
|
-
container.appendChild(this._svg);
|
|
1649
|
+
if (this.qrSVG?.element) {
|
|
1650
|
+
container.appendChild(this.qrSVG.element);
|
|
1664
1651
|
}
|
|
1665
|
-
this.
|
|
1652
|
+
this.container = container;
|
|
1666
1653
|
}
|
|
1667
1654
|
/**
|
|
1668
1655
|
*
|
|
@@ -1696,27 +1683,57 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1696
1683
|
if (!extension) {
|
|
1697
1684
|
throw "Extension function should be defined.";
|
|
1698
1685
|
}
|
|
1699
|
-
this.
|
|
1686
|
+
this.extension = extension;
|
|
1700
1687
|
this.update();
|
|
1701
1688
|
}
|
|
1702
1689
|
deleteExtension() {
|
|
1703
|
-
this.
|
|
1690
|
+
this.extension = undefined;
|
|
1704
1691
|
this.update();
|
|
1705
1692
|
}
|
|
1706
1693
|
async serialize() {
|
|
1707
|
-
if (!this.
|
|
1694
|
+
if (!this.qr)
|
|
1708
1695
|
throw "QR code is empty";
|
|
1709
|
-
|
|
1710
|
-
|
|
1696
|
+
if (!this.qrSVG?.element || !this.svgDrawingPromise) {
|
|
1697
|
+
this.setupSvg();
|
|
1698
|
+
}
|
|
1699
|
+
await this.svgDrawingPromise;
|
|
1700
|
+
if (!this.qrSVG?.element) {
|
|
1711
1701
|
return;
|
|
1712
1702
|
}
|
|
1713
1703
|
const serializer = new XMLSerializer();
|
|
1714
|
-
let source = serializer.serializeToString(element);
|
|
1704
|
+
let source = serializer.serializeToString(this.qrSVG.element);
|
|
1715
1705
|
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
|
|
1716
1706
|
return source;
|
|
1717
1707
|
}
|
|
1708
|
+
setupSvg() {
|
|
1709
|
+
if (!this.qr) {
|
|
1710
|
+
return;
|
|
1711
|
+
}
|
|
1712
|
+
const count = Math.ceil((this.options.shape == ShapeType.circle ? Math.sqrt(2) : 1) * this.qr.getModuleCount());
|
|
1713
|
+
const margin = (this.options.backgroundOptions && this.options.backgroundOptions.margin) || 0;
|
|
1714
|
+
const size = Math.ceil(this.options.dotsOptions.size * (count + 2 * margin));
|
|
1715
|
+
this.qrSVG = new QRSVG({
|
|
1716
|
+
...this.options,
|
|
1717
|
+
width: size,
|
|
1718
|
+
height: size,
|
|
1719
|
+
errorCorrectionPercent: ErrorCorrectionPercents[this.options.qrOptions.errorCorrectionLevel]
|
|
1720
|
+
});
|
|
1721
|
+
this.svgDrawingPromise = this.qrSVG.drawQR(this.qr).then(() => {
|
|
1722
|
+
if (!this.qrSVG?.element)
|
|
1723
|
+
return;
|
|
1724
|
+
this.extension?.(this.qrSVG.element, this.options);
|
|
1725
|
+
});
|
|
1726
|
+
}
|
|
1718
1727
|
};
|
|
1719
1728
|
|
|
1729
|
+
var FileExtension;
|
|
1730
|
+
(function (FileExtension) {
|
|
1731
|
+
FileExtension["svg"] = "svg";
|
|
1732
|
+
FileExtension["png"] = "png";
|
|
1733
|
+
FileExtension["jpeg"] = "jpeg";
|
|
1734
|
+
FileExtension["webp"] = "webp";
|
|
1735
|
+
})(FileExtension || (FileExtension = {}));
|
|
1736
|
+
|
|
1720
1737
|
const browserUtils = undefined;
|
|
1721
1738
|
class QRCodeStyling extends QRCodeStyling$1 {
|
|
1722
1739
|
constructor(options) {
|
|
@@ -1753,11 +1770,8 @@ class QRCodeStyling extends QRCodeStyling$1 {
|
|
|
1753
1770
|
document: options.document || dom,
|
|
1754
1771
|
imageTools: options.imageTools || {
|
|
1755
1772
|
toDataURL: (url) => loadImage(url).then(({ contentType, data }) => `data:${contentType?.replace("application/xml", "image/svg+xml")};base64,${data.toString("base64")}`),
|
|
1756
|
-
getSize: async
|
|
1757
|
-
|
|
1758
|
-
throw new Error("Image is not defined");
|
|
1759
|
-
}
|
|
1760
|
-
const { data } = Buffer.isBuffer(options.image) ? { data: options.image } : await loadImage(options.image);
|
|
1773
|
+
getSize: async (src) => {
|
|
1774
|
+
const { data } = Buffer.isBuffer(options.image) ? { data: options.image } : await loadImage(src);
|
|
1761
1775
|
const meta = await sharp(data).metadata();
|
|
1762
1776
|
return {
|
|
1763
1777
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|