@liquid-js/qr-code-styling 3.0.0-2 → 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 +449 -439
- 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}` +
|
|
@@ -588,13 +584,13 @@ class QRCornerSquare {
|
|
|
588
584
|
}
|
|
589
585
|
});
|
|
590
586
|
}
|
|
591
|
-
|
|
587
|
+
basicClassy(args) {
|
|
592
588
|
const { size, x, y } = args;
|
|
593
589
|
const dotSize = size / 7;
|
|
594
|
-
this.
|
|
590
|
+
this.rotateFigure({
|
|
595
591
|
...args,
|
|
596
592
|
draw: () => {
|
|
597
|
-
this._element = this.
|
|
593
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
598
594
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
599
595
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
600
596
|
`v ${2 * dotSize}` +
|
|
@@ -616,13 +612,13 @@ class QRCornerSquare {
|
|
|
616
612
|
}
|
|
617
613
|
});
|
|
618
614
|
}
|
|
619
|
-
|
|
615
|
+
basicInpoint(args) {
|
|
620
616
|
const { size, x, y } = args;
|
|
621
617
|
const dotSize = size / 7;
|
|
622
|
-
this.
|
|
618
|
+
this.rotateFigure({
|
|
623
619
|
...args,
|
|
624
620
|
draw: () => {
|
|
625
|
-
this._element = this.
|
|
621
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
626
622
|
this._element.setAttribute("clip-rule", "evenodd");
|
|
627
623
|
this._element.setAttribute("d", `M ${x} ${y + 2.5 * dotSize}` +
|
|
628
624
|
`v ${2 * dotSize}` +
|
|
@@ -645,96 +641,98 @@ class QRCornerSquare {
|
|
|
645
641
|
}
|
|
646
642
|
});
|
|
647
643
|
}
|
|
648
|
-
|
|
649
|
-
this.
|
|
644
|
+
drawDot({ x, y, size, rotation }) {
|
|
645
|
+
this.basicDot({ x, y, size, rotation });
|
|
650
646
|
}
|
|
651
|
-
|
|
652
|
-
this.
|
|
647
|
+
drawSquare({ x, y, size, rotation }) {
|
|
648
|
+
this.basicSquare({ x, y, size, rotation });
|
|
653
649
|
}
|
|
654
|
-
|
|
655
|
-
this.
|
|
650
|
+
drawExtraRounded({ x, y, size, rotation }) {
|
|
651
|
+
this.basicExtraRounded({ x, y, size, rotation });
|
|
656
652
|
}
|
|
657
|
-
|
|
658
|
-
this.
|
|
653
|
+
drawClassy({ x, y, size, rotation }) {
|
|
654
|
+
this.basicClassy({ x, y, size, rotation });
|
|
659
655
|
}
|
|
660
|
-
|
|
661
|
-
this.
|
|
656
|
+
drawInpoint({ x, y, size, rotation }) {
|
|
657
|
+
this.basicInpoint({ x, y, size, rotation });
|
|
662
658
|
}
|
|
663
|
-
|
|
664
|
-
this.
|
|
659
|
+
drawOutpoint({ x, y, size, rotation }) {
|
|
660
|
+
this.basicInpoint({ x, y, size, rotation: (rotation || 0) + Math.PI });
|
|
665
661
|
}
|
|
666
662
|
}
|
|
667
663
|
|
|
668
664
|
class QRDot {
|
|
669
|
-
|
|
670
|
-
this.
|
|
671
|
-
|
|
672
|
-
|
|
665
|
+
get element() {
|
|
666
|
+
return this._element;
|
|
667
|
+
}
|
|
668
|
+
constructor(type, document) {
|
|
669
|
+
this.type = type;
|
|
670
|
+
this.document = document;
|
|
673
671
|
}
|
|
674
|
-
draw(
|
|
675
|
-
const type = this.
|
|
672
|
+
draw(args) {
|
|
673
|
+
const type = this.type;
|
|
676
674
|
let drawFunction;
|
|
677
675
|
switch (type) {
|
|
678
|
-
case DotType.
|
|
679
|
-
drawFunction = this.
|
|
676
|
+
case DotType.dot:
|
|
677
|
+
drawFunction = this.drawDot;
|
|
680
678
|
break;
|
|
681
|
-
case DotType.
|
|
682
|
-
drawFunction = this.
|
|
679
|
+
case DotType.randomDot:
|
|
680
|
+
drawFunction = this.drawRandomDot;
|
|
683
681
|
break;
|
|
684
682
|
case DotType.classy:
|
|
685
|
-
drawFunction = this.
|
|
683
|
+
drawFunction = this.drawClassy;
|
|
686
684
|
break;
|
|
687
685
|
case DotType.classyRounded:
|
|
688
|
-
drawFunction = this.
|
|
686
|
+
drawFunction = this.drawClassyRounded;
|
|
689
687
|
break;
|
|
690
688
|
case DotType.rounded:
|
|
691
|
-
drawFunction = this.
|
|
689
|
+
drawFunction = this.drawRounded;
|
|
692
690
|
break;
|
|
693
|
-
case DotType.
|
|
694
|
-
drawFunction = this.
|
|
691
|
+
case DotType.verticalLine:
|
|
692
|
+
drawFunction = this.drawVerticalLine;
|
|
695
693
|
break;
|
|
696
|
-
case DotType.
|
|
697
|
-
drawFunction = this.
|
|
694
|
+
case DotType.horizontalLine:
|
|
695
|
+
drawFunction = this.drawHorizontalLine;
|
|
698
696
|
break;
|
|
699
697
|
case DotType.extraRounded:
|
|
700
|
-
drawFunction = this.
|
|
698
|
+
drawFunction = this.drawExtraRounded;
|
|
701
699
|
break;
|
|
702
700
|
case DotType.diamond:
|
|
703
|
-
drawFunction = this.
|
|
701
|
+
drawFunction = this.drawDiamond;
|
|
704
702
|
break;
|
|
705
703
|
case DotType.smallSquare:
|
|
706
|
-
drawFunction = this.
|
|
704
|
+
drawFunction = this.drawSmallSquare;
|
|
707
705
|
break;
|
|
708
706
|
case DotType.square:
|
|
709
707
|
default:
|
|
710
|
-
drawFunction = this.
|
|
708
|
+
drawFunction = this.drawSquare;
|
|
711
709
|
}
|
|
712
|
-
drawFunction.call(this,
|
|
710
|
+
drawFunction.call(this, args);
|
|
713
711
|
}
|
|
714
|
-
|
|
712
|
+
rotateFigure({ x, y, size, rotation = 0, draw }) {
|
|
715
713
|
const cx = x + size / 2;
|
|
716
714
|
const cy = y + size / 2;
|
|
717
715
|
draw();
|
|
718
716
|
this._element?.setAttribute("transform", `rotate(${(180 * rotation) / Math.PI},${cx},${cy})`);
|
|
719
717
|
}
|
|
720
|
-
|
|
718
|
+
basicDot(args) {
|
|
721
719
|
const { size, x, y } = args;
|
|
722
|
-
this.
|
|
720
|
+
this.rotateFigure({
|
|
723
721
|
...args,
|
|
724
722
|
draw: () => {
|
|
725
|
-
this._element = this.
|
|
723
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
726
724
|
this._element.setAttribute("cx", String(x + size / 2));
|
|
727
725
|
this._element.setAttribute("cy", String(y + size / 2));
|
|
728
726
|
this._element.setAttribute("r", String(size / 2));
|
|
729
727
|
}
|
|
730
728
|
});
|
|
731
729
|
}
|
|
732
|
-
|
|
730
|
+
basicSquare(args) {
|
|
733
731
|
const { size, x, y } = args;
|
|
734
|
-
this.
|
|
732
|
+
this.rotateFigure({
|
|
735
733
|
...args,
|
|
736
734
|
draw: () => {
|
|
737
|
-
this._element = this.
|
|
735
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
738
736
|
this._element.setAttribute("x", String(x));
|
|
739
737
|
this._element.setAttribute("y", String(y));
|
|
740
738
|
this._element.setAttribute("width", String(size));
|
|
@@ -743,12 +741,12 @@ class QRDot {
|
|
|
743
741
|
});
|
|
744
742
|
}
|
|
745
743
|
//if rotation === 0 - right side is rounded
|
|
746
|
-
|
|
744
|
+
basicSideRounded(args) {
|
|
747
745
|
const { size, x, y } = args;
|
|
748
|
-
this.
|
|
746
|
+
this.rotateFigure({
|
|
749
747
|
...args,
|
|
750
748
|
draw: () => {
|
|
751
|
-
this._element = this.
|
|
749
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
752
750
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
753
751
|
`v ${size}` + //draw line to left bottom corner
|
|
754
752
|
`h ${size / 2}` + //draw line to left bottom corner + half of size right
|
|
@@ -758,12 +756,12 @@ class QRDot {
|
|
|
758
756
|
});
|
|
759
757
|
}
|
|
760
758
|
//if rotation === 0 - top right corner is rounded
|
|
761
|
-
|
|
759
|
+
basicCornerRounded(args) {
|
|
762
760
|
const { size, x, y } = args;
|
|
763
|
-
this.
|
|
761
|
+
this.rotateFigure({
|
|
764
762
|
...args,
|
|
765
763
|
draw: () => {
|
|
766
|
-
this._element = this.
|
|
764
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
767
765
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
768
766
|
`v ${size}` + //draw line to left bottom corner
|
|
769
767
|
`h ${size}` + //draw line to right bottom corner
|
|
@@ -774,12 +772,12 @@ class QRDot {
|
|
|
774
772
|
});
|
|
775
773
|
}
|
|
776
774
|
//if rotation === 0 - top right corner is rounded
|
|
777
|
-
|
|
775
|
+
basicCornerExtraRounded(args) {
|
|
778
776
|
const { size, x, y } = args;
|
|
779
|
-
this.
|
|
777
|
+
this.rotateFigure({
|
|
780
778
|
...args,
|
|
781
779
|
draw: () => {
|
|
782
|
-
this._element = this.
|
|
780
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
783
781
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to top left position
|
|
784
782
|
`v ${size}` + //draw line to left bottom corner
|
|
785
783
|
`h ${size}` + //draw line to right bottom corner
|
|
@@ -789,12 +787,12 @@ class QRDot {
|
|
|
789
787
|
});
|
|
790
788
|
}
|
|
791
789
|
//if rotation === 0 - left bottom and right top corners are rounded
|
|
792
|
-
|
|
790
|
+
basicCornersRounded(args) {
|
|
793
791
|
const { size, x, y } = args;
|
|
794
|
-
this.
|
|
792
|
+
this.rotateFigure({
|
|
795
793
|
...args,
|
|
796
794
|
draw: () => {
|
|
797
|
-
this._element = this.
|
|
795
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
798
796
|
this._element.setAttribute("d", `M ${x} ${y}` + //go to left top position
|
|
799
797
|
`v ${size / 2}` + //draw line to left top corner + half of size bottom
|
|
800
798
|
`a ${size / 2} ${size / 2}, 0, 0, 0, ${size / 2} ${size / 2}` + // draw rounded left bottom corner
|
|
@@ -805,38 +803,38 @@ class QRDot {
|
|
|
805
803
|
}
|
|
806
804
|
});
|
|
807
805
|
}
|
|
808
|
-
|
|
809
|
-
this.
|
|
806
|
+
drawDot({ x, y, size }) {
|
|
807
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
810
808
|
}
|
|
811
|
-
|
|
809
|
+
drawRandomDot({ x, y, size }) {
|
|
812
810
|
const randomFactor = Math.random() * (1 - 0.75) + 0.75;
|
|
813
|
-
this.
|
|
811
|
+
this.basicDot({ x, y, size: size * randomFactor, rotation: 0 });
|
|
814
812
|
}
|
|
815
|
-
|
|
816
|
-
this.
|
|
813
|
+
drawSquare({ x, y, size }) {
|
|
814
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
817
815
|
}
|
|
818
|
-
|
|
816
|
+
drawSmallSquare({ x, y, size }) {
|
|
819
817
|
const originalSize = size;
|
|
820
818
|
size = originalSize * 0.7;
|
|
821
819
|
x = x + originalSize * 0.15;
|
|
822
820
|
y = y + originalSize * 0.15;
|
|
823
|
-
this.
|
|
821
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
824
822
|
}
|
|
825
|
-
|
|
826
|
-
this.
|
|
823
|
+
drawDiamond({ x, y, size }) {
|
|
824
|
+
this.basicSquare({ x, y, size, rotation: Math.PI / 4 });
|
|
827
825
|
}
|
|
828
|
-
|
|
826
|
+
drawRounded({ x, y, size, getNeighbor }) {
|
|
829
827
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
830
828
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
831
829
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
832
830
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
833
831
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
834
832
|
if (neighborsCount === 0) {
|
|
835
|
-
this.
|
|
833
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
836
834
|
return;
|
|
837
835
|
}
|
|
838
836
|
if (neighborsCount > 2 || (leftNeighbor && rightNeighbor) || (topNeighbor && bottomNeighbor)) {
|
|
839
|
-
this.
|
|
837
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
840
838
|
return;
|
|
841
839
|
}
|
|
842
840
|
if (neighborsCount === 2) {
|
|
@@ -850,7 +848,7 @@ class QRDot {
|
|
|
850
848
|
else if (rightNeighbor && bottomNeighbor) {
|
|
851
849
|
rotation = -Math.PI / 2;
|
|
852
850
|
}
|
|
853
|
-
this.
|
|
851
|
+
this.basicCornerRounded({ x, y, size, rotation });
|
|
854
852
|
return;
|
|
855
853
|
}
|
|
856
854
|
if (neighborsCount === 1) {
|
|
@@ -864,11 +862,11 @@ class QRDot {
|
|
|
864
862
|
else if (bottomNeighbor) {
|
|
865
863
|
rotation = -Math.PI / 2;
|
|
866
864
|
}
|
|
867
|
-
this.
|
|
865
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
868
866
|
return;
|
|
869
867
|
}
|
|
870
868
|
}
|
|
871
|
-
|
|
869
|
+
drawVerticalLine({ x, y, size, getNeighbor }) {
|
|
872
870
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
873
871
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
874
872
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
@@ -877,25 +875,25 @@ class QRDot {
|
|
|
877
875
|
if (neighborsCount === 0 ||
|
|
878
876
|
(leftNeighbor && !(topNeighbor || bottomNeighbor)) ||
|
|
879
877
|
(rightNeighbor && !(topNeighbor || bottomNeighbor))) {
|
|
880
|
-
this.
|
|
878
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
881
879
|
return;
|
|
882
880
|
}
|
|
883
881
|
if (topNeighbor && bottomNeighbor) {
|
|
884
|
-
this.
|
|
882
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
885
883
|
return;
|
|
886
884
|
}
|
|
887
885
|
if (topNeighbor && !bottomNeighbor) {
|
|
888
886
|
const rotation = Math.PI / 2;
|
|
889
|
-
this.
|
|
887
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
890
888
|
return;
|
|
891
889
|
}
|
|
892
890
|
if (bottomNeighbor && !topNeighbor) {
|
|
893
891
|
const rotation = -Math.PI / 2;
|
|
894
|
-
this.
|
|
892
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
895
893
|
return;
|
|
896
894
|
}
|
|
897
895
|
}
|
|
898
|
-
|
|
896
|
+
drawHorizontalLine({ x, y, size, getNeighbor }) {
|
|
899
897
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
900
898
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
901
899
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
@@ -904,36 +902,36 @@ class QRDot {
|
|
|
904
902
|
if (neighborsCount === 0 ||
|
|
905
903
|
(topNeighbor && !(leftNeighbor || rightNeighbor)) ||
|
|
906
904
|
(bottomNeighbor && !(leftNeighbor || rightNeighbor))) {
|
|
907
|
-
this.
|
|
905
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
908
906
|
return;
|
|
909
907
|
}
|
|
910
908
|
if (leftNeighbor && rightNeighbor) {
|
|
911
|
-
this.
|
|
909
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
912
910
|
return;
|
|
913
911
|
}
|
|
914
912
|
if (leftNeighbor && !rightNeighbor) {
|
|
915
913
|
const rotation = 0;
|
|
916
|
-
this.
|
|
914
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
917
915
|
return;
|
|
918
916
|
}
|
|
919
917
|
if (rightNeighbor && !leftNeighbor) {
|
|
920
918
|
const rotation = Math.PI;
|
|
921
|
-
this.
|
|
919
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
922
920
|
return;
|
|
923
921
|
}
|
|
924
922
|
}
|
|
925
|
-
|
|
923
|
+
drawExtraRounded({ x, y, size, getNeighbor }) {
|
|
926
924
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
927
925
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
928
926
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
929
927
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
930
928
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
931
929
|
if (neighborsCount === 0) {
|
|
932
|
-
this.
|
|
930
|
+
this.basicDot({ x, y, size, rotation: 0 });
|
|
933
931
|
return;
|
|
934
932
|
}
|
|
935
933
|
if (neighborsCount > 2 || (leftNeighbor && rightNeighbor) || (topNeighbor && bottomNeighbor)) {
|
|
936
|
-
this.
|
|
934
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
937
935
|
return;
|
|
938
936
|
}
|
|
939
937
|
if (neighborsCount === 2) {
|
|
@@ -947,7 +945,7 @@ class QRDot {
|
|
|
947
945
|
else if (rightNeighbor && bottomNeighbor) {
|
|
948
946
|
rotation = -Math.PI / 2;
|
|
949
947
|
}
|
|
950
|
-
this.
|
|
948
|
+
this.basicCornerExtraRounded({ x, y, size, rotation });
|
|
951
949
|
return;
|
|
952
950
|
}
|
|
953
951
|
if (neighborsCount === 1) {
|
|
@@ -961,49 +959,49 @@ class QRDot {
|
|
|
961
959
|
else if (bottomNeighbor) {
|
|
962
960
|
rotation = -Math.PI / 2;
|
|
963
961
|
}
|
|
964
|
-
this.
|
|
962
|
+
this.basicSideRounded({ x, y, size, rotation });
|
|
965
963
|
return;
|
|
966
964
|
}
|
|
967
965
|
}
|
|
968
|
-
|
|
966
|
+
drawClassy({ x, y, size, getNeighbor }) {
|
|
969
967
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
970
968
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
971
969
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
972
970
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
973
971
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
974
972
|
if (neighborsCount === 0) {
|
|
975
|
-
this.
|
|
973
|
+
this.basicCornersRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
976
974
|
return;
|
|
977
975
|
}
|
|
978
976
|
if (!leftNeighbor && !topNeighbor) {
|
|
979
|
-
this.
|
|
977
|
+
this.basicCornerRounded({ x, y, size, rotation: -Math.PI / 2 });
|
|
980
978
|
return;
|
|
981
979
|
}
|
|
982
980
|
if (!rightNeighbor && !bottomNeighbor) {
|
|
983
|
-
this.
|
|
981
|
+
this.basicCornerRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
984
982
|
return;
|
|
985
983
|
}
|
|
986
|
-
this.
|
|
984
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
987
985
|
}
|
|
988
|
-
|
|
986
|
+
drawClassyRounded({ x, y, size, getNeighbor }) {
|
|
989
987
|
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0;
|
|
990
988
|
const rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0;
|
|
991
989
|
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0;
|
|
992
990
|
const bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
993
991
|
const neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
994
992
|
if (neighborsCount === 0) {
|
|
995
|
-
this.
|
|
993
|
+
this.basicCornersRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
996
994
|
return;
|
|
997
995
|
}
|
|
998
996
|
if (!leftNeighbor && !topNeighbor) {
|
|
999
|
-
this.
|
|
997
|
+
this.basicCornerExtraRounded({ x, y, size, rotation: -Math.PI / 2 });
|
|
1000
998
|
return;
|
|
1001
999
|
}
|
|
1002
1000
|
if (!rightNeighbor && !bottomNeighbor) {
|
|
1003
|
-
this.
|
|
1001
|
+
this.basicCornerExtraRounded({ x, y, size, rotation: Math.PI / 2 });
|
|
1004
1002
|
return;
|
|
1005
1003
|
}
|
|
1006
|
-
this.
|
|
1004
|
+
this.basicSquare({ x, y, size, rotation: 0 });
|
|
1007
1005
|
}
|
|
1008
1006
|
}
|
|
1009
1007
|
|
|
@@ -1033,24 +1031,21 @@ const browserImageTools = {
|
|
|
1033
1031
|
}
|
|
1034
1032
|
});
|
|
1035
1033
|
},
|
|
1036
|
-
getSize(
|
|
1034
|
+
getSize(src, crossOrigin) {
|
|
1037
1035
|
return new Promise((resolve, reject) => {
|
|
1038
|
-
if (!options.image) {
|
|
1039
|
-
return reject("Image is not defined");
|
|
1040
|
-
}
|
|
1041
1036
|
const image = new Image();
|
|
1042
|
-
if (
|
|
1043
|
-
image.crossOrigin =
|
|
1037
|
+
if (crossOrigin === "string") {
|
|
1038
|
+
image.crossOrigin = crossOrigin;
|
|
1044
1039
|
}
|
|
1045
1040
|
image.onload = () => {
|
|
1046
1041
|
resolve({ width: image.width, height: image.height });
|
|
1047
1042
|
};
|
|
1048
1043
|
image.onerror = image.onabort = reject;
|
|
1049
|
-
if (typeof
|
|
1050
|
-
image.src =
|
|
1044
|
+
if (typeof src == "string")
|
|
1045
|
+
image.src = src;
|
|
1051
1046
|
else
|
|
1052
1047
|
browserImageTools
|
|
1053
|
-
.toDataURL(
|
|
1048
|
+
.toDataURL(src)
|
|
1054
1049
|
.then((url) => (image.src = url))
|
|
1055
1050
|
.catch(reject);
|
|
1056
1051
|
});
|
|
@@ -1155,43 +1150,42 @@ const alignmentCount = [
|
|
|
1155
1150
|
[1, 1]
|
|
1156
1151
|
];
|
|
1157
1152
|
class QRSVG {
|
|
1158
|
-
|
|
1153
|
+
get element() {
|
|
1154
|
+
return this._element;
|
|
1155
|
+
}
|
|
1159
1156
|
constructor(options) {
|
|
1160
|
-
this.
|
|
1161
|
-
this.
|
|
1157
|
+
this.options = options;
|
|
1158
|
+
this.document = options.document;
|
|
1159
|
+
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
1162
1160
|
this._element.setAttribute("width", String(options.width));
|
|
1163
1161
|
this._element.setAttribute("height", String(options.height));
|
|
1164
1162
|
this._element.setAttribute("viewBox", `0 0 ${options.width} ${options.height}`);
|
|
1165
|
-
this.
|
|
1166
|
-
this._element.appendChild(this.
|
|
1167
|
-
this.
|
|
1168
|
-
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;
|
|
1169
1166
|
}
|
|
1170
1167
|
get width() {
|
|
1171
|
-
return this.
|
|
1168
|
+
return this.options.width;
|
|
1172
1169
|
}
|
|
1173
1170
|
get height() {
|
|
1174
|
-
return this.
|
|
1175
|
-
}
|
|
1176
|
-
getElement() {
|
|
1177
|
-
return this._element;
|
|
1171
|
+
return this.options.height;
|
|
1178
1172
|
}
|
|
1179
1173
|
async drawQR(qr) {
|
|
1180
1174
|
const count = qr.getModuleCount();
|
|
1181
1175
|
const typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10);
|
|
1182
|
-
const dotSize = this.
|
|
1176
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1183
1177
|
let drawImageSize = {
|
|
1184
1178
|
hideXDots: 0,
|
|
1185
1179
|
hideYDots: 0,
|
|
1186
1180
|
width: 0,
|
|
1187
1181
|
height: 0
|
|
1188
1182
|
};
|
|
1189
|
-
this.
|
|
1190
|
-
if (this.
|
|
1183
|
+
this.qr = qr;
|
|
1184
|
+
if (this.options.image) {
|
|
1191
1185
|
//We need it to get image size
|
|
1192
|
-
const size = await this.
|
|
1193
|
-
const { imageOptions,
|
|
1194
|
-
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;
|
|
1195
1189
|
const alignment = alignmentCount.find((v) => v[0] <= typeNumber) || [0, 0];
|
|
1196
1190
|
const maxHiddenDots = Math.floor(coverLevel * (count * count - 3 * 8 * 8 - 2 * (count - 16) - alignment[1] * 25));
|
|
1197
1191
|
drawImageSize = calculateImageSize({
|
|
@@ -1205,7 +1199,7 @@ class QRSVG {
|
|
|
1205
1199
|
}
|
|
1206
1200
|
this.drawBackground();
|
|
1207
1201
|
this.drawDots((i, j) => {
|
|
1208
|
-
if (this.
|
|
1202
|
+
if (this.options.imageOptions.hideBackgroundDots) {
|
|
1209
1203
|
if (i >= (count - drawImageSize.hideXDots) / 2 &&
|
|
1210
1204
|
i < (count + drawImageSize.hideXDots) / 2 &&
|
|
1211
1205
|
j >= (count - drawImageSize.hideYDots) / 2 &&
|
|
@@ -1222,17 +1216,17 @@ class QRSVG {
|
|
|
1222
1216
|
return true;
|
|
1223
1217
|
});
|
|
1224
1218
|
this.drawCorners();
|
|
1225
|
-
if (this.
|
|
1219
|
+
if (this.options.image && drawImageSize.width > 0 && drawImageSize.height > 0) {
|
|
1226
1220
|
await this.drawImage({ width: drawImageSize.width, height: drawImageSize.height, count, dotSize });
|
|
1227
1221
|
}
|
|
1228
1222
|
}
|
|
1229
1223
|
drawBackground() {
|
|
1230
1224
|
const element = this._element;
|
|
1231
|
-
const options = this.
|
|
1225
|
+
const options = this.options;
|
|
1232
1226
|
if (element && options.backgroundOptions) {
|
|
1233
1227
|
const gradientOptions = options.backgroundOptions.gradient;
|
|
1234
1228
|
const color = options.backgroundOptions.color;
|
|
1235
|
-
this.
|
|
1229
|
+
this.createColor({
|
|
1236
1230
|
options: gradientOptions,
|
|
1237
1231
|
color: color,
|
|
1238
1232
|
additionalRotation: 0,
|
|
@@ -1243,50 +1237,55 @@ class QRSVG {
|
|
|
1243
1237
|
name: "background-color"
|
|
1244
1238
|
});
|
|
1245
1239
|
const size = Math.min(options.width, options.height);
|
|
1246
|
-
const element = this.
|
|
1247
|
-
[this.
|
|
1248
|
-
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);
|
|
1249
1243
|
element.setAttribute("x", String((options.width - size) / 2));
|
|
1250
1244
|
element.setAttribute("y", String((options.height - size) / 2));
|
|
1251
1245
|
element.setAttribute("width", String(size));
|
|
1252
1246
|
element.setAttribute("height", String(size));
|
|
1253
1247
|
element.setAttribute("rx", String((size / 2) * (options.backgroundOptions.round || 0)));
|
|
1254
|
-
this.
|
|
1248
|
+
this.backgroundMaskGroup.appendChild(element);
|
|
1255
1249
|
}
|
|
1256
1250
|
}
|
|
1257
1251
|
drawDots(filter) {
|
|
1258
|
-
if (!this.
|
|
1252
|
+
if (!this.qr) {
|
|
1259
1253
|
throw "QR code is not defined";
|
|
1260
1254
|
}
|
|
1261
|
-
const options = this.
|
|
1262
|
-
const count = this.
|
|
1255
|
+
const options = this.options;
|
|
1256
|
+
const count = this.qr.getModuleCount();
|
|
1263
1257
|
if (count > options.width || count > options.height) {
|
|
1264
1258
|
throw "The canvas is too small.";
|
|
1265
1259
|
}
|
|
1266
1260
|
const minSize = Math.min(options.width, options.height);
|
|
1267
|
-
const dotSize = this.
|
|
1261
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1268
1262
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
1269
1263
|
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
1270
|
-
const dot = new QRDot(
|
|
1271
|
-
[this.
|
|
1272
|
-
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);
|
|
1273
1267
|
for (let i = 0; i < count; i++) {
|
|
1274
1268
|
for (let j = 0; j < count; j++) {
|
|
1275
1269
|
if (filter && !filter(i, j)) {
|
|
1276
1270
|
continue;
|
|
1277
1271
|
}
|
|
1278
|
-
if (!this.
|
|
1272
|
+
if (!this.qr?.isDark(j, i)) {
|
|
1279
1273
|
continue;
|
|
1280
1274
|
}
|
|
1281
|
-
dot.draw(
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
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
|
+
}
|
|
1287
1286
|
});
|
|
1288
|
-
if (dot.
|
|
1289
|
-
this.
|
|
1287
|
+
if (dot.element && this.dotsMask) {
|
|
1288
|
+
this.dotsMaskGroup.appendChild(dot.element);
|
|
1290
1289
|
}
|
|
1291
1290
|
}
|
|
1292
1291
|
}
|
|
@@ -1294,7 +1293,7 @@ class QRSVG {
|
|
|
1294
1293
|
let colorY = yBeginning;
|
|
1295
1294
|
let colorCount = count;
|
|
1296
1295
|
if (options.shape === ShapeType.circle) {
|
|
1297
|
-
const margin = (this.
|
|
1296
|
+
const margin = (this.options.backgroundOptions && this.options.backgroundOptions.margin) || 0;
|
|
1298
1297
|
const additionalDots = Math.floor((minSize / dotSize - count - 2 * margin) / 2);
|
|
1299
1298
|
const fakeCount = count + additionalDots * 2;
|
|
1300
1299
|
const xFakeBeginning = xBeginning - additionalDots * dotSize;
|
|
@@ -1319,7 +1318,7 @@ class QRSVG {
|
|
|
1319
1318
|
continue;
|
|
1320
1319
|
}
|
|
1321
1320
|
//Get random dots from QR code to show it outside of QR code
|
|
1322
|
-
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)
|
|
1323
1322
|
? 1
|
|
1324
1323
|
: 0;
|
|
1325
1324
|
}
|
|
@@ -1328,16 +1327,21 @@ class QRSVG {
|
|
|
1328
1327
|
for (let j = 0; j < fakeCount; j++) {
|
|
1329
1328
|
if (!fakeMatrix[i][j])
|
|
1330
1329
|
continue;
|
|
1331
|
-
dot.draw(
|
|
1332
|
-
|
|
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
|
+
}
|
|
1333
1337
|
});
|
|
1334
|
-
if (dot.
|
|
1335
|
-
this.
|
|
1338
|
+
if (dot.element && this.dotsMask) {
|
|
1339
|
+
this.dotsMaskGroup.appendChild(dot.element);
|
|
1336
1340
|
}
|
|
1337
1341
|
}
|
|
1338
1342
|
}
|
|
1339
1343
|
}
|
|
1340
|
-
this.
|
|
1344
|
+
this.createColor({
|
|
1341
1345
|
options: options.dotsOptions?.gradient,
|
|
1342
1346
|
color: options.dotsOptions.color,
|
|
1343
1347
|
additionalRotation: 0,
|
|
@@ -1349,16 +1353,16 @@ class QRSVG {
|
|
|
1349
1353
|
});
|
|
1350
1354
|
}
|
|
1351
1355
|
drawCorners() {
|
|
1352
|
-
if (!this.
|
|
1356
|
+
if (!this.qr) {
|
|
1353
1357
|
throw "QR code is not defined";
|
|
1354
1358
|
}
|
|
1355
1359
|
const element = this._element;
|
|
1356
|
-
const options = this.
|
|
1360
|
+
const options = this.options;
|
|
1357
1361
|
if (!element) {
|
|
1358
1362
|
throw "Element code is not defined";
|
|
1359
1363
|
}
|
|
1360
|
-
const count = this.
|
|
1361
|
-
const dotSize = this.
|
|
1364
|
+
const count = this.qr.getModuleCount();
|
|
1365
|
+
const dotSize = this.options.dotsOptions.size;
|
|
1362
1366
|
const cornersSquareSize = dotSize * 7;
|
|
1363
1367
|
const cornersDotSize = dotSize * 3;
|
|
1364
1368
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
@@ -1370,16 +1374,16 @@ class QRSVG {
|
|
|
1370
1374
|
].forEach(([column, row, rotation]) => {
|
|
1371
1375
|
const x = xBeginning + column * dotSize * (count - 7);
|
|
1372
1376
|
const y = yBeginning + row * dotSize * (count - 7);
|
|
1373
|
-
let cornersSquareMask = this.
|
|
1374
|
-
let cornersSquareMaskGroup = this.
|
|
1375
|
-
let cornersDotMask = this.
|
|
1376
|
-
let cornersDotMaskGroup = this.
|
|
1377
|
+
let cornersSquareMask = this.dotsMask;
|
|
1378
|
+
let cornersSquareMaskGroup = this.dotsMaskGroup;
|
|
1379
|
+
let cornersDotMask = this.dotsMask;
|
|
1380
|
+
let cornersDotMaskGroup = this.dotsMaskGroup;
|
|
1377
1381
|
if (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) {
|
|
1378
|
-
[cornersSquareMask, cornersSquareMaskGroup] = this.
|
|
1379
|
-
this.
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
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({
|
|
1383
1387
|
options: options.cornersSquareOptions?.gradient,
|
|
1384
1388
|
color: options.cornersSquareOptions?.color,
|
|
1385
1389
|
additionalRotation: rotation,
|
|
@@ -1391,36 +1395,40 @@ class QRSVG {
|
|
|
1391
1395
|
});
|
|
1392
1396
|
}
|
|
1393
1397
|
if (options.cornersSquareOptions?.type) {
|
|
1394
|
-
const cornersSquare = new QRCornerSquare(
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
+
const cornersSquare = new QRCornerSquare(options.cornersSquareOptions.type, this.document);
|
|
1399
|
+
cornersSquare.draw({
|
|
1400
|
+
x,
|
|
1401
|
+
y,
|
|
1402
|
+
size: cornersSquareSize,
|
|
1403
|
+
rotation
|
|
1398
1404
|
});
|
|
1399
|
-
cornersSquare.
|
|
1400
|
-
|
|
1401
|
-
cornersSquareMaskGroup.appendChild(cornersSquare._element);
|
|
1405
|
+
if (cornersSquare.element && cornersSquareMaskGroup) {
|
|
1406
|
+
cornersSquareMaskGroup.appendChild(cornersSquare.element);
|
|
1402
1407
|
}
|
|
1403
1408
|
}
|
|
1404
1409
|
else {
|
|
1405
|
-
const dot = new QRDot(
|
|
1410
|
+
const dot = new QRDot(options.dotsOptions.type, this.document);
|
|
1406
1411
|
for (let i = 0; i < squareMask.length; i++) {
|
|
1407
1412
|
for (let j = 0; j < squareMask[i].length; j++) {
|
|
1408
1413
|
if (!squareMask[i]?.[j]) {
|
|
1409
1414
|
continue;
|
|
1410
1415
|
}
|
|
1411
|
-
dot.draw(
|
|
1412
|
-
|
|
1413
|
-
|
|
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);
|
|
1414
1424
|
}
|
|
1415
1425
|
}
|
|
1416
1426
|
}
|
|
1417
1427
|
}
|
|
1418
1428
|
if (options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) {
|
|
1419
|
-
[cornersDotMask, cornersDotMaskGroup] = this.
|
|
1420
|
-
this.
|
|
1421
|
-
this.
|
|
1422
|
-
this._cornersDotMaskGroup = cornersDotMaskGroup;
|
|
1423
|
-
this._createColor({
|
|
1429
|
+
[cornersDotMask, cornersDotMaskGroup] = this.createMask(`mask-corners-dot-color-${column}-${row}`);
|
|
1430
|
+
this.defs.appendChild(cornersDotMask);
|
|
1431
|
+
this.createColor({
|
|
1424
1432
|
options: options.cornersDotOptions?.gradient,
|
|
1425
1433
|
color: options.cornersDotOptions?.color,
|
|
1426
1434
|
additionalRotation: rotation,
|
|
@@ -1432,26 +1440,32 @@ class QRSVG {
|
|
|
1432
1440
|
});
|
|
1433
1441
|
}
|
|
1434
1442
|
if (options.cornersDotOptions?.type) {
|
|
1435
|
-
const cornersDot = new QRCornerDot(
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
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
|
|
1439
1449
|
});
|
|
1440
|
-
cornersDot.
|
|
1441
|
-
|
|
1442
|
-
cornersDotMaskGroup.appendChild(cornersDot._element);
|
|
1450
|
+
if (cornersDot.element && cornersDotMaskGroup) {
|
|
1451
|
+
cornersDotMaskGroup.appendChild(cornersDot.element);
|
|
1443
1452
|
}
|
|
1444
1453
|
}
|
|
1445
1454
|
else {
|
|
1446
|
-
const dot = new QRDot(
|
|
1455
|
+
const dot = new QRDot(options.dotsOptions.type, this.document);
|
|
1447
1456
|
for (let i = 0; i < dotMask.length; i++) {
|
|
1448
1457
|
for (let j = 0; j < dotMask[i].length; j++) {
|
|
1449
1458
|
if (!dotMask[i]?.[j]) {
|
|
1450
1459
|
continue;
|
|
1451
1460
|
}
|
|
1452
|
-
dot.draw(
|
|
1453
|
-
|
|
1454
|
-
|
|
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);
|
|
1455
1469
|
}
|
|
1456
1470
|
}
|
|
1457
1471
|
}
|
|
@@ -1459,7 +1473,7 @@ class QRSVG {
|
|
|
1459
1473
|
});
|
|
1460
1474
|
}
|
|
1461
1475
|
async drawImage({ width, height, count, dotSize }) {
|
|
1462
|
-
const options = this.
|
|
1476
|
+
const options = this.options;
|
|
1463
1477
|
const xBeginning = Math.floor((options.width - count * dotSize) / 2);
|
|
1464
1478
|
const yBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
1465
1479
|
const margin = options.imageOptions.margin * dotSize;
|
|
@@ -1467,8 +1481,8 @@ class QRSVG {
|
|
|
1467
1481
|
const dy = yBeginning + margin + (count * dotSize - height) / 2;
|
|
1468
1482
|
const dw = width - margin * 2;
|
|
1469
1483
|
const dh = height - margin * 2;
|
|
1470
|
-
const imageUrl = await this.
|
|
1471
|
-
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");
|
|
1472
1486
|
image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || "");
|
|
1473
1487
|
if (imageUrl.startsWith("data:image/svg+xml;")) {
|
|
1474
1488
|
let data = imageUrl.substring(19);
|
|
@@ -1496,10 +1510,9 @@ class QRSVG {
|
|
|
1496
1510
|
image.setAttribute("height", `${dh}px`);
|
|
1497
1511
|
this._element.appendChild(image);
|
|
1498
1512
|
}
|
|
1499
|
-
|
|
1500
|
-
_createColor({ options, color, additionalRotation, x, y, height, width, name }) {
|
|
1513
|
+
createColor({ options, color, additionalRotation, x, y, height, width, name }) {
|
|
1501
1514
|
const size = width > height ? width : height;
|
|
1502
|
-
const rect = this.
|
|
1515
|
+
const rect = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
1503
1516
|
rect.setAttribute("x", String(x));
|
|
1504
1517
|
rect.setAttribute("y", String(y));
|
|
1505
1518
|
rect.setAttribute("height", String(height));
|
|
@@ -1508,7 +1521,7 @@ class QRSVG {
|
|
|
1508
1521
|
if (options) {
|
|
1509
1522
|
let gradient;
|
|
1510
1523
|
if (options.type === GradientType.radial) {
|
|
1511
|
-
gradient = this.
|
|
1524
|
+
gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "radialGradient");
|
|
1512
1525
|
gradient.setAttribute("id", name);
|
|
1513
1526
|
gradient.setAttribute("gradientUnits", "userSpaceOnUse");
|
|
1514
1527
|
gradient.setAttribute("fx", String(x + width / 2));
|
|
@@ -1549,7 +1562,7 @@ class QRSVG {
|
|
|
1549
1562
|
y1 = y1 - height / 2;
|
|
1550
1563
|
x1 = x1 - width / 2 / Math.tan(rotation);
|
|
1551
1564
|
}
|
|
1552
|
-
gradient = this.
|
|
1565
|
+
gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "linearGradient");
|
|
1553
1566
|
gradient.setAttribute("id", name);
|
|
1554
1567
|
gradient.setAttribute("gradientUnits", "userSpaceOnUse");
|
|
1555
1568
|
gradient.setAttribute("x1", String(Math.round(x0)));
|
|
@@ -1558,29 +1571,29 @@ class QRSVG {
|
|
|
1558
1571
|
gradient.setAttribute("y2", String(Math.round(y1)));
|
|
1559
1572
|
}
|
|
1560
1573
|
options.colorStops.forEach(({ offset, color }) => {
|
|
1561
|
-
const stop = this.
|
|
1574
|
+
const stop = this.document.createElementNS("http://www.w3.org/2000/svg", "stop");
|
|
1562
1575
|
stop.setAttribute("offset", `${100 * offset}%`);
|
|
1563
1576
|
stop.setAttribute("stop-color", color);
|
|
1564
1577
|
gradient.appendChild(stop);
|
|
1565
1578
|
});
|
|
1566
1579
|
rect.setAttribute("fill", `url(#${name})`);
|
|
1567
|
-
this.
|
|
1580
|
+
this.defs.appendChild(gradient);
|
|
1568
1581
|
}
|
|
1569
1582
|
else if (color) {
|
|
1570
1583
|
rect.setAttribute("fill", color);
|
|
1571
1584
|
}
|
|
1572
1585
|
this._element.appendChild(rect);
|
|
1573
1586
|
}
|
|
1574
|
-
|
|
1575
|
-
const options = this.
|
|
1576
|
-
const mask = this.
|
|
1587
|
+
createMask(id) {
|
|
1588
|
+
const options = this.options;
|
|
1589
|
+
const mask = this.document.createElementNS("http://www.w3.org/2000/svg", "mask");
|
|
1577
1590
|
mask.setAttribute("id", id);
|
|
1578
1591
|
mask.setAttribute("maskUnits", "userSpaceOnUse");
|
|
1579
1592
|
mask.setAttribute("x", "0");
|
|
1580
1593
|
mask.setAttribute("y", "0");
|
|
1581
1594
|
mask.setAttribute("width", String(options.width));
|
|
1582
1595
|
mask.setAttribute("height", String(options.height));
|
|
1583
|
-
const group = this.
|
|
1596
|
+
const group = this.document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
1584
1597
|
group.setAttribute("fill", "#fff");
|
|
1585
1598
|
mask.appendChild(group);
|
|
1586
1599
|
return [mask, group];
|
|
@@ -1588,60 +1601,33 @@ class QRSVG {
|
|
|
1588
1601
|
}
|
|
1589
1602
|
|
|
1590
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
|
+
}
|
|
1591
1612
|
constructor(options) {
|
|
1592
|
-
this.
|
|
1613
|
+
this.options = options ? sanitizeOptions(mergeDeep(defaultOptions, options)) : defaultOptions;
|
|
1593
1614
|
this.update();
|
|
1594
1615
|
}
|
|
1595
|
-
/** @ignore */
|
|
1596
|
-
static _clearContainer(container) {
|
|
1597
|
-
if (container) {
|
|
1598
|
-
container.innerHTML = "";
|
|
1599
|
-
}
|
|
1600
|
-
}
|
|
1601
|
-
/** @ignore */
|
|
1602
|
-
_setupSvg() {
|
|
1603
|
-
if (!this._qr) {
|
|
1604
|
-
return;
|
|
1605
|
-
}
|
|
1606
|
-
const count = Math.ceil((this._options.shape == ShapeType.circle ? Math.sqrt(2) : 1) * this._qr.getModuleCount());
|
|
1607
|
-
const margin = (this._options.backgroundOptions && this._options.backgroundOptions.margin) || 0;
|
|
1608
|
-
const size = Math.ceil(this._options.dotsOptions.size * (count + 2 * margin));
|
|
1609
|
-
const qrSVG = new QRSVG({
|
|
1610
|
-
...this._options,
|
|
1611
|
-
width: size,
|
|
1612
|
-
height: size
|
|
1613
|
-
});
|
|
1614
|
-
this._svg = qrSVG.getElement();
|
|
1615
|
-
this._svgDrawingPromise = qrSVG.drawQR(this._qr).then(() => {
|
|
1616
|
-
if (!this._svg)
|
|
1617
|
-
return;
|
|
1618
|
-
this._extension?.(qrSVG.getElement(), this._options);
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
|
-
/** @ignore */
|
|
1622
|
-
async _getElement() {
|
|
1623
|
-
if (!this._qr)
|
|
1624
|
-
throw "QR code is empty";
|
|
1625
|
-
if (!this._svg || !this._svgDrawingPromise) {
|
|
1626
|
-
this._setupSvg();
|
|
1627
|
-
}
|
|
1628
|
-
await this._svgDrawingPromise;
|
|
1629
|
-
return this._svg;
|
|
1630
|
-
}
|
|
1631
1616
|
update(
|
|
1632
1617
|
/** The same options as for initialization */
|
|
1633
1618
|
options) {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1619
|
+
if (this.container)
|
|
1620
|
+
this.container.innerHTML = "";
|
|
1621
|
+
this.options = options ? sanitizeOptions(mergeDeep(this.options, options)) : this.options;
|
|
1622
|
+
if (!this.options.data) {
|
|
1637
1623
|
return;
|
|
1638
1624
|
}
|
|
1639
|
-
if (this.
|
|
1640
|
-
Object.assign(qrcode.stringToBytesFuncs, this.
|
|
1641
|
-
delete this.
|
|
1625
|
+
if (this.options.stringToBytesFuncs) {
|
|
1626
|
+
Object.assign(qrcode.stringToBytesFuncs, this.options.stringToBytesFuncs);
|
|
1627
|
+
delete this.options.stringToBytesFuncs;
|
|
1642
1628
|
}
|
|
1643
|
-
this.
|
|
1644
|
-
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);
|
|
1645
1631
|
if (mode == Mode.unicode) {
|
|
1646
1632
|
qrcode.stringToBytes = qrcode.stringToBytesFuncs["UTF-8"];
|
|
1647
1633
|
mode = Mode.byte;
|
|
@@ -1649,10 +1635,10 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1649
1635
|
else {
|
|
1650
1636
|
qrcode.stringToBytes = qrcode.stringToBytesFuncs["default"];
|
|
1651
1637
|
}
|
|
1652
|
-
this.
|
|
1653
|
-
this.
|
|
1654
|
-
this.
|
|
1655
|
-
this.append(this.
|
|
1638
|
+
this.qr.addData(this.options.data, mode);
|
|
1639
|
+
this.qr.make();
|
|
1640
|
+
this.setupSvg();
|
|
1641
|
+
this.append(this.container);
|
|
1656
1642
|
}
|
|
1657
1643
|
append(
|
|
1658
1644
|
/** This container will be used for appending of the QR code */
|
|
@@ -1660,13 +1646,10 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1660
1646
|
if (!container) {
|
|
1661
1647
|
return;
|
|
1662
1648
|
}
|
|
1663
|
-
if (
|
|
1664
|
-
|
|
1665
|
-
}
|
|
1666
|
-
if (this._svg) {
|
|
1667
|
-
container.appendChild(this._svg);
|
|
1649
|
+
if (this.qrSVG?.element) {
|
|
1650
|
+
container.appendChild(this.qrSVG.element);
|
|
1668
1651
|
}
|
|
1669
|
-
this.
|
|
1652
|
+
this.container = container;
|
|
1670
1653
|
}
|
|
1671
1654
|
/**
|
|
1672
1655
|
*
|
|
@@ -1700,27 +1683,57 @@ let QRCodeStyling$1 = class QRCodeStyling {
|
|
|
1700
1683
|
if (!extension) {
|
|
1701
1684
|
throw "Extension function should be defined.";
|
|
1702
1685
|
}
|
|
1703
|
-
this.
|
|
1686
|
+
this.extension = extension;
|
|
1704
1687
|
this.update();
|
|
1705
1688
|
}
|
|
1706
1689
|
deleteExtension() {
|
|
1707
|
-
this.
|
|
1690
|
+
this.extension = undefined;
|
|
1708
1691
|
this.update();
|
|
1709
1692
|
}
|
|
1710
1693
|
async serialize() {
|
|
1711
|
-
if (!this.
|
|
1694
|
+
if (!this.qr)
|
|
1712
1695
|
throw "QR code is empty";
|
|
1713
|
-
|
|
1714
|
-
|
|
1696
|
+
if (!this.qrSVG?.element || !this.svgDrawingPromise) {
|
|
1697
|
+
this.setupSvg();
|
|
1698
|
+
}
|
|
1699
|
+
await this.svgDrawingPromise;
|
|
1700
|
+
if (!this.qrSVG?.element) {
|
|
1715
1701
|
return;
|
|
1716
1702
|
}
|
|
1717
1703
|
const serializer = new XMLSerializer();
|
|
1718
|
-
let source = serializer.serializeToString(element);
|
|
1704
|
+
let source = serializer.serializeToString(this.qrSVG.element);
|
|
1719
1705
|
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
|
|
1720
1706
|
return source;
|
|
1721
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
|
+
}
|
|
1722
1727
|
};
|
|
1723
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
|
+
|
|
1724
1737
|
const browserUtils = undefined;
|
|
1725
1738
|
class QRCodeStyling extends QRCodeStyling$1 {
|
|
1726
1739
|
constructor(options) {
|
|
@@ -1757,11 +1770,8 @@ class QRCodeStyling extends QRCodeStyling$1 {
|
|
|
1757
1770
|
document: options.document || dom,
|
|
1758
1771
|
imageTools: options.imageTools || {
|
|
1759
1772
|
toDataURL: (url) => loadImage(url).then(({ contentType, data }) => `data:${contentType?.replace("application/xml", "image/svg+xml")};base64,${data.toString("base64")}`),
|
|
1760
|
-
getSize: async
|
|
1761
|
-
|
|
1762
|
-
throw new Error("Image is not defined");
|
|
1763
|
-
}
|
|
1764
|
-
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);
|
|
1765
1775
|
const meta = await sharp(data).metadata();
|
|
1766
1776
|
return {
|
|
1767
1777
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|