@liquid-js/qr-code-styling 5.0.0-1 → 5.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 +38 -0
- package/lib/border-plugin.js +2 -0
- package/lib/border-plugin.js.map +1 -0
- package/lib/core/qr-code-styling.d.ts +5 -2
- package/lib/core/qr-svg.d.ts +2 -2
- package/lib/figures/corner-dot.d.ts +2 -1
- package/lib/figures/corner-square.d.ts +2 -1
- package/lib/figures/dot.d.ts +3 -2
- package/lib/figures/square-elements.d.ts +0 -1
- package/lib/index.d.ts +1 -1
- package/lib/node.d.ts +1 -1
- package/lib/plugin-utils.js +2 -0
- package/lib/plugin-utils.js.map +1 -0
- package/lib/plugins/border.d.ts +38 -0
- package/lib/plugins/utils.d.ts +2 -0
- package/lib/qr-code-styling-node.js +476 -413
- 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/utils/options.d.ts +26 -0
- package/lib/utils/svg.d.ts +7 -1
- package/package.json +12 -2
|
@@ -29,34 +29,42 @@ function mergeDeep(target, ...sources) {
|
|
|
29
29
|
|
|
30
30
|
var GradientType, DotType, CornerDotType, CornerSquareType, ShapeType, ImageMode;
|
|
31
31
|
|
|
32
|
-
function sanitizeGradient(
|
|
33
|
-
|
|
34
|
-
...
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
function sanitizeGradient(gradient) {
|
|
33
|
+
let newGradient = {
|
|
34
|
+
...gradient
|
|
35
|
+
};
|
|
36
|
+
if (!newGradient.colorStops || !newGradient.colorStops.length) throw new Error("Field 'colorStops' is required in gradient");
|
|
37
|
+
return newGradient.rotation ? newGradient.rotation = Number(newGradient.rotation) : newGradient.rotation = 0,
|
|
38
|
+
newGradient.colorStops = newGradient.colorStops.map(colorStop => ({
|
|
38
39
|
...colorStop,
|
|
39
40
|
offset: Number(colorStop.offset)
|
|
40
|
-
})),
|
|
41
|
+
})), newGradient;
|
|
41
42
|
}
|
|
42
43
|
|
|
43
|
-
(GradientType
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
DotType.
|
|
47
|
-
DotType.
|
|
48
|
-
DotType.
|
|
49
|
-
DotType.
|
|
50
|
-
DotType.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
CornerDotType.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
(
|
|
59
|
-
|
|
44
|
+
!function(GradientType) {
|
|
45
|
+
GradientType.radial = "radial", GradientType.linear = "linear";
|
|
46
|
+
}(GradientType || (GradientType = {})), function(DotType) {
|
|
47
|
+
DotType.dot = "dot", DotType.randomDot = "random-dot", DotType.rounded = "rounded",
|
|
48
|
+
DotType.extraRounded = "extra-rounded", DotType.verticalLine = "vertical-line",
|
|
49
|
+
DotType.horizontalLine = "horizontal-line", DotType.classy = "classy", DotType.classyRounded = "classy-rounded",
|
|
50
|
+
DotType.square = "square", DotType.smallSquare = "small-square", DotType.tinySquare = "tiny-square",
|
|
51
|
+
DotType.diamond = "diamond", DotType.wave = "wave", DotType.heart = "heart", DotType.star = "star",
|
|
52
|
+
DotType.weave = "weave", DotType.pentagon = "pentagon", DotType.hexagon = "hexagon",
|
|
53
|
+
DotType.zebraHorizontal = "zebra-horizontal", DotType.zebraVertical = "zebra-vertical";
|
|
54
|
+
}(DotType || (DotType = {})), function(CornerDotType) {
|
|
55
|
+
CornerDotType.dot = "dot", CornerDotType.square = "square", CornerDotType.heart = "heart",
|
|
56
|
+
CornerDotType.extraRounded = "extra-rounded", CornerDotType.classy = "classy", CornerDotType.inpoint = "inpoint",
|
|
57
|
+
CornerDotType.outpoint = "outpoint", CornerDotType.star = "star", CornerDotType.pentagon = "pentagon",
|
|
58
|
+
CornerDotType.hexagon = "hexagon", CornerDotType.diamond = "diamond";
|
|
59
|
+
}(CornerDotType || (CornerDotType = {})), function(CornerSquareType) {
|
|
60
|
+
CornerSquareType.dot = "dot", CornerSquareType.square = "square", CornerSquareType.extraRounded = "extra-rounded",
|
|
61
|
+
CornerSquareType.classy = "classy", CornerSquareType.inpoint = "inpoint", CornerSquareType.outpoint = "outpoint",
|
|
62
|
+
CornerSquareType.centerCircle = "center-circle";
|
|
63
|
+
}(CornerSquareType || (CornerSquareType = {})), function(ShapeType) {
|
|
64
|
+
ShapeType.square = "square", ShapeType.circle = "circle";
|
|
65
|
+
}(ShapeType || (ShapeType = {})), function(ImageMode) {
|
|
66
|
+
ImageMode.center = "center", ImageMode.overlay = "overlay", ImageMode.background = "background";
|
|
67
|
+
}(ImageMode || (ImageMode = {}));
|
|
60
68
|
|
|
61
69
|
let defaultOptions = {
|
|
62
70
|
document: void 0,
|
|
@@ -85,32 +93,33 @@ let defaultOptions = {
|
|
|
85
93
|
}
|
|
86
94
|
};
|
|
87
95
|
|
|
88
|
-
function sanitizeOptions(
|
|
89
|
-
|
|
90
|
-
...
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
function sanitizeOptions(options) {
|
|
97
|
+
let newOptions = {
|
|
98
|
+
...options
|
|
99
|
+
};
|
|
100
|
+
return newOptions.imageOptions = {
|
|
101
|
+
...newOptions.imageOptions,
|
|
102
|
+
imageSize: Math.min(1, Number(newOptions.imageOptions.imageSize)) || 1,
|
|
103
|
+
margin: Number(newOptions.imageOptions.margin),
|
|
95
104
|
fill: {
|
|
96
|
-
...
|
|
105
|
+
...newOptions.imageOptions.fill
|
|
97
106
|
}
|
|
98
|
-
},
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
...
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
...
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
...
|
|
109
|
-
},
|
|
110
|
-
|
|
111
|
-
...
|
|
112
|
-
},
|
|
113
|
-
|
|
107
|
+
}, newOptions.imageOptions.mode == ImageMode.overlay && (newOptions.imageOptions.margin = 0),
|
|
108
|
+
newOptions.imageOptions.fill.gradient && (newOptions.imageOptions.fill.gradient = sanitizeGradient(newOptions.imageOptions.fill.gradient)),
|
|
109
|
+
newOptions.dotsOptions = {
|
|
110
|
+
...newOptions.dotsOptions
|
|
111
|
+
}, newOptions.dotsOptions.gradient && (newOptions.dotsOptions.gradient = sanitizeGradient(newOptions.dotsOptions.gradient)),
|
|
112
|
+
newOptions.dotsOptions.size = Math.round(Math.max(0, newOptions.dotsOptions.size) || 10),
|
|
113
|
+
newOptions.cornersSquareOptions && (newOptions.cornersSquareOptions = {
|
|
114
|
+
...newOptions.cornersSquareOptions
|
|
115
|
+
}, newOptions.cornersSquareOptions.gradient && (newOptions.cornersSquareOptions.gradient = sanitizeGradient(newOptions.cornersSquareOptions.gradient))),
|
|
116
|
+
newOptions.cornersDotOptions && (newOptions.cornersDotOptions = {
|
|
117
|
+
...newOptions.cornersDotOptions
|
|
118
|
+
}, newOptions.cornersDotOptions.gradient && (newOptions.cornersDotOptions.gradient = sanitizeGradient(newOptions.cornersDotOptions.gradient))),
|
|
119
|
+
newOptions.backgroundOptions && (newOptions.backgroundOptions = {
|
|
120
|
+
...newOptions.backgroundOptions
|
|
121
|
+
}, newOptions.backgroundOptions.gradient && (newOptions.backgroundOptions.gradient = sanitizeGradient(newOptions.backgroundOptions.gradient))),
|
|
122
|
+
newOptions.document || (newOptions.document = document), newOptions;
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
let ErrorCorrectionPercents = {
|
|
@@ -123,7 +132,7 @@ let ErrorCorrectionPercents = {
|
|
|
123
132
|
let rx = /\.?0+$/;
|
|
124
133
|
|
|
125
134
|
function numToAttr(value) {
|
|
126
|
-
return value.toFixed(7).replace(rx, "");
|
|
135
|
+
return "string" == typeof value ? value : value.toFixed(7).replace(rx, "");
|
|
127
136
|
}
|
|
128
137
|
|
|
129
138
|
function svgPath(strings, ...values) {
|
|
@@ -133,58 +142,52 @@ function svgPath(strings, ...values) {
|
|
|
133
142
|
}, "").trim().replace(/[\s\n\r]+/gim, " ");
|
|
134
143
|
}
|
|
135
144
|
|
|
136
|
-
function rotateFigure({draw
|
|
137
|
-
let {x, y, size, rotation = 0} = args, cx = x + size / 2, cy = y + size / 2;
|
|
138
|
-
return
|
|
139
|
-
|
|
145
|
+
function rotateFigure({draw, ...args}) {
|
|
146
|
+
let {x, y, size, rotation = 0} = args, cx = x + size / 2, cy = y + size / 2, element = draw(args);
|
|
147
|
+
return rotation && (Array.isArray(element) ? element : [ element ]).forEach(el => el.setAttribute("transform", `rotate(${numToAttr(180 * rotation / Math.PI)},${cx},${cy})`)),
|
|
148
|
+
element;
|
|
140
149
|
}
|
|
141
150
|
|
|
142
151
|
let DotElements = {
|
|
143
152
|
dot: args => {
|
|
144
|
-
const {size, x, y, document} = args;
|
|
145
|
-
return
|
|
146
|
-
|
|
147
|
-
args;
|
|
153
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "circle");
|
|
154
|
+
return element.setAttribute("cx", numToAttr(x + size / 2)), element.setAttribute("cy", numToAttr(y + size / 2)),
|
|
155
|
+
element.setAttribute("r", numToAttr(size / 2)), element;
|
|
148
156
|
},
|
|
149
157
|
square: (args, {width = args.size, height = args.size} = {}) => {
|
|
150
|
-
const {x, y, size, document} = args;
|
|
151
|
-
return
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
const {x, y, size, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
159
|
+
return element.setAttribute("x", numToAttr(x + (size - width) / 2)), element.setAttribute("y", numToAttr(y + (size - height) / 2)),
|
|
160
|
+
element.setAttribute("width", numToAttr(width)), element.setAttribute("height", numToAttr(height)),
|
|
161
|
+
element;
|
|
154
162
|
},
|
|
155
163
|
sideRounded: (args, {height = args.size} = {}) => {
|
|
156
|
-
const {size, x, y, document} = args;
|
|
157
|
-
return
|
|
158
|
-
|
|
164
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
165
|
+
return element.setAttribute("d", svgPath`M ${x} ${y + (size - height) / 2} v ${height} h ${size / 2} a ${height / 2} ${height / 2} 0 0 0 0 ${-height} z`),
|
|
166
|
+
element;
|
|
159
167
|
},
|
|
160
168
|
cornerRounded: args => {
|
|
161
|
-
const {size, x, y, document} = args;
|
|
162
|
-
return
|
|
163
|
-
|
|
169
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
170
|
+
return element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size} v ${-size / 2} a ${size / 2} ${size / 2} 0 0 0 ${-size / 2} ${-size / 2} z`),
|
|
171
|
+
element;
|
|
164
172
|
},
|
|
165
173
|
cornerExtraRounded: args => {
|
|
166
|
-
const {size, x, y, document} = args;
|
|
167
|
-
return
|
|
168
|
-
|
|
174
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
175
|
+
return element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size} a ${size} ${size} 0 0 0 ${-size} ${-size} z`),
|
|
176
|
+
element;
|
|
169
177
|
},
|
|
170
178
|
cornersRounded: args => {
|
|
171
|
-
const {size, x, y, document} = args;
|
|
172
|
-
return
|
|
173
|
-
|
|
179
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
180
|
+
return element.setAttribute("d", svgPath`M ${x} ${y} v ${size / 2} a ${size / 2} ${size / 2} 0 0 0 ${size / 2} ${size / 2} h ${size / 2} v ${-size / 2} a ${size / 2} ${size / 2} 0 0 0 ${-size / 2} ${-size / 2} z`),
|
|
181
|
+
element;
|
|
174
182
|
},
|
|
175
183
|
wave: args => {
|
|
176
|
-
const {size, x, y, document} = args;
|
|
177
|
-
|
|
178
|
-
args = size * (1 - .65 * Math.sin(a1_c23y)), a1_c23y = -size * (.95 - .65 * Math.cos(a1_c23y));
|
|
179
|
-
const c31x = -size * Math.sin(a2_c31y) / 2;
|
|
180
|
-
a2_c31y = size * Math.cos(a2_c31y) / 2;
|
|
181
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
182
|
-
return element.setAttribute("d", svgPath`M ${x} ${y + size} c ${.65 * size} 0 ${args} ${a1_c23y} ${size} ${.95 * -size} c ${c31x} ${a2_c31y} ${-size / 2} ${size * (.95 - 1)} ${-size} ${size * (.95 - 1)} z`),
|
|
184
|
+
const {size, x, y, document} = args, a1 = 5 * Math.PI / 180, a2 = 65 * Math.PI / 180, c23x = size * (1 - .65 * Math.sin(a1)), c23y = -size * (.95 - .65 * Math.cos(a1)), c31x = -size * Math.sin(a2) / 2, c31y = size * Math.cos(a2) / 2, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
185
|
+
return element.setAttribute("d", svgPath`M ${x} ${y + size} c ${.65 * size} 0 ${c23x} ${c23y} ${size} ${.95 * -size} c ${c31x} ${c31y} ${-size / 2} ${size * (.95 - 1)} ${-size} ${size * (.95 - 1)} z`),
|
|
183
186
|
element;
|
|
184
187
|
},
|
|
185
188
|
heart: args => {
|
|
186
|
-
const {size, x, y, document} = args;
|
|
187
|
-
return
|
|
189
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
190
|
+
return element.setAttribute("d", function(path, {x, y, size}) {
|
|
188
191
|
let move = !1, i = 0;
|
|
189
192
|
return path.map(v => "string" == typeof v ? (i = 0, move = v.toUpperCase() == v,
|
|
190
193
|
v) : (i++, v *= size, move && (v += i % 2 == 1 ? x : y), numToAttr(v))).join(" ");
|
|
@@ -192,35 +195,35 @@ let DotElements = {
|
|
|
192
195
|
x,
|
|
193
196
|
y,
|
|
194
197
|
size
|
|
195
|
-
})),
|
|
198
|
+
})), element;
|
|
196
199
|
},
|
|
197
200
|
rounded: args => {
|
|
198
|
-
const {size, x, y, document} = args;
|
|
199
|
-
return
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
202
|
+
return element.setAttribute("x", numToAttr(x)), element.setAttribute("y", numToAttr(y)),
|
|
203
|
+
element.setAttribute("width", numToAttr(size)), element.setAttribute("height", numToAttr(size)),
|
|
204
|
+
element.setAttribute("rx", numToAttr(size / 4)), element.setAttribute("ry", numToAttr(size / 4)),
|
|
205
|
+
element;
|
|
203
206
|
},
|
|
204
207
|
classy: args => {
|
|
205
|
-
const {size, x, y, document} = args;
|
|
206
|
-
|
|
207
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
208
|
-
return element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * args} v ${2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * args} ${2.5 * args} h ${4.5 * args} v ${-4.5 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * -args} h ${-2 * args} H ${x} z`),
|
|
208
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
209
|
+
return element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * dotSize} v ${2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * dotSize} ${2.5 * dotSize} h ${4.5 * dotSize} v ${-4.5 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * -dotSize} h ${-2 * dotSize} H ${x} z`),
|
|
209
210
|
element;
|
|
210
211
|
},
|
|
211
212
|
inpoint: args => {
|
|
212
|
-
const {size, x, y, document} = args;
|
|
213
|
-
return
|
|
214
|
-
|
|
213
|
+
const {size, x, y, document} = args, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
214
|
+
return element.setAttribute("d", svgPath`M ${x} ${y + size / 2} v ${size / 4} a ${size / 4} ${size / 4} 0 0 0 ${size / 4} ${size / 4} h ${size / 4 * 3} v ${-size / 4 * 3} a ${size / 4} ${size / 4} 0 0 0 ${-size / 4} ${-size / 4} h ${-size / 2} a ${size / 4} ${size / 4} 0 0 0 ${-size / 4} ${size / 4} z`),
|
|
215
|
+
element;
|
|
215
216
|
},
|
|
216
217
|
star: (args, {spikes = 5, outerRadius = args.size / 2, innerRadius = args.size / 4} = {}) => {
|
|
217
|
-
const {size, x, y, document} = args, cx = x + size / 2, cy = y + size / 2, angle = Math.PI / spikes;
|
|
218
|
-
return
|
|
219
|
-
|
|
218
|
+
const {size, x, y, document} = args, cx = x + size / 2, cy = y + size / 2, angle = Math.PI / spikes, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
219
|
+
return element.setAttribute("d", Array(2 * spikes).fill(0).map((_, i) => {
|
|
220
|
+
const radius = i % 2 == 0 ? outerRadius : innerRadius;
|
|
221
|
+
return svgPath`${0 === i ? "M" : "L"} ${cx + radius * Math.sin(i * angle)} ${cy - radius * Math.cos(i * angle)}`;
|
|
222
|
+
}).join(" ")), element;
|
|
220
223
|
},
|
|
221
224
|
weave: args => {
|
|
222
|
-
const {size, x, y, document} = args,
|
|
223
|
-
return element.setAttribute("d", svgPath`M ${x + notch} ${y} l ${
|
|
225
|
+
const {size, x, y, document} = args, thickness = .6 * size, notch = (size - thickness) / 2, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
226
|
+
return element.setAttribute("d", svgPath`M ${x + notch} ${y} l ${thickness} 0 l 0 ${notch} l ${notch} 0 l 0 ${thickness} l ${-notch} 0 l 0 ${notch} l ${-thickness} 0 l 0 ${-notch} l ${-notch} 0 l 0 ${-thickness} l ${notch} 0 z`),
|
|
224
227
|
element;
|
|
225
228
|
}
|
|
226
229
|
}, qrCornerDotFigures = {
|
|
@@ -269,70 +272,49 @@ let DotElements = {
|
|
|
269
272
|
height: .85 * args2.size
|
|
270
273
|
})
|
|
271
274
|
})
|
|
272
|
-
}
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
let SquareElements = {
|
|
273
278
|
dot: args => {
|
|
274
|
-
const {size, x, y, document} = args;
|
|
275
|
-
|
|
276
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
277
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x + size / 2} ${y} a ${size / 2} ${size / 2} 0 1 0 0.1 0 z m 0 ${args} a ${size / 2 - args} ${size / 2 - args} 0 1 1 -0.1 0 Z`);
|
|
279
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
280
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x + size / 2} ${y} a ${size / 2} ${size / 2} 0 1 0 0.1 0 z m 0 ${dotSize} a ${size / 2 - dotSize} ${size / 2 - dotSize} 0 1 1 -0.1 0 Z`);
|
|
278
281
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
279
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + size / 2} ${y -
|
|
282
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + size / 2} ${y - dotSize} a ${size / 2 + dotSize} ${size / 2 + dotSize} 0 1 0 0.1 0 z`),
|
|
280
283
|
[ element, fill ];
|
|
281
284
|
},
|
|
282
285
|
square: args => {
|
|
283
|
-
const {size, x, y, document} = args;
|
|
284
|
-
|
|
285
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
286
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size} v ${-size} z M ${x + args} ${y + args} h ${size - 2 * args} v ${size - 2 * args} h ${2 * args - size} z`);
|
|
286
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
287
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size} v ${-size} z M ${x + dotSize} ${y + dotSize} h ${size - 2 * dotSize} v ${size - 2 * dotSize} h ${2 * dotSize - size} z`);
|
|
287
288
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
288
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x -
|
|
289
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x - dotSize} ${y - dotSize} h ${size + 2 * dotSize} v ${size + 2 * dotSize} h ${-size - 2 * dotSize} z`),
|
|
289
290
|
[ element, fill ];
|
|
290
291
|
},
|
|
291
292
|
extraRounded: args => {
|
|
292
|
-
const {size, x, y, document} = args;
|
|
293
|
-
|
|
294
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
295
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * args} v ${2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * args} ${2.5 * args} h ${2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * args} ${2.5 * -args} v ${-2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * -args} h ${-2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * args} z M ${x + 2.5 * args} ${y + args} h ${2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * args} ${1.5 * args} v ${2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * -args} ${1.5 * args} h ${-2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * -args} ${1.5 * -args} v ${-2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * args} ${1.5 * -args} z`);
|
|
293
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
294
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * dotSize} v ${2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * dotSize} ${2.5 * dotSize} h ${2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * dotSize} ${2.5 * -dotSize} v ${-2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * -dotSize} h ${-2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * dotSize} z M ${x + 2.5 * dotSize} ${y + dotSize} h ${2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * dotSize} ${1.5 * dotSize} v ${2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * -dotSize} ${1.5 * dotSize} h ${-2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * -dotSize} ${1.5 * -dotSize} v ${-2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * dotSize} ${1.5 * -dotSize} z`);
|
|
296
295
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
297
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x -
|
|
296
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x - dotSize} ${y + 2.5 * dotSize} v ${2 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 0 ${3.5 * dotSize} ${3.5 * dotSize} h ${2 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 0 ${3.5 * dotSize} ${3.5 * -dotSize} v ${-2 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 0 ${3.5 * -dotSize} ${3.5 * -dotSize} h ${-2 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 0 ${3.5 * -dotSize} ${3.5 * dotSize} z`),
|
|
298
297
|
[ element, fill ];
|
|
299
298
|
},
|
|
300
299
|
classy: args => {
|
|
301
|
-
const {size, x, y, document} = args;
|
|
302
|
-
|
|
303
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
304
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * args} v ${2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * args} ${2.5 * args} h ${4.5 * args} v ${-4.5 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * -args} h ${-2 * args} H ${x} z M ${x + 2.5 * args} ${y + args} h ${2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * args} ${1.5 * args} v ${3.5 * args} h ${-3.5 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * -args} ${1.5 * -args} v ${-3.5 * args} z`);
|
|
300
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
301
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * dotSize} v ${2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * dotSize} ${2.5 * dotSize} h ${4.5 * dotSize} v ${-4.5 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * -dotSize} h ${-2 * dotSize} H ${x} z M ${x + 2.5 * dotSize} ${y + dotSize} h ${2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * dotSize} ${1.5 * dotSize} v ${3.5 * dotSize} h ${-3.5 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * -dotSize} ${1.5 * -dotSize} v ${-3.5 * dotSize} z`);
|
|
305
302
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
306
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + .5 *
|
|
303
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + .5 * dotSize} ${y - dotSize} h ${4 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 1 ${3.5 * dotSize} ${3.5 * dotSize} v ${5.5 * dotSize} h ${-5.5 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 1 ${3.5 * -dotSize} ${3.5 * -dotSize} v ${-5.5 * dotSize} z`),
|
|
307
304
|
[ element, fill ];
|
|
308
305
|
},
|
|
309
306
|
inpoint: args => {
|
|
310
|
-
const {size, x, y, document} = args;
|
|
311
|
-
|
|
312
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
313
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * args} v ${2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * args} ${2.5 * args} h ${4.5 * args} v ${-4.5 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * -args} h ${-2 * args} a ${2.5 * args} ${2.5 * args} 0 0 0 ${2.5 * -args} ${2.5 * args} z M ${x + 2.5 * args} ${y + args} h ${2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * args} ${1.5 * args} v ${3.5 * args} h ${-3.5 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * -args} ${1.5 * -args} v ${-2 * args} a ${1.5 * args} ${1.5 * args} 0 0 1 ${1.5 * args} ${1.5 * -args} z`);
|
|
307
|
+
const {size, x, y, document} = args, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
308
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y + 2.5 * dotSize} v ${2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * dotSize} ${2.5 * dotSize} h ${4.5 * dotSize} v ${-4.5 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * -dotSize} h ${-2 * dotSize} a ${2.5 * dotSize} ${2.5 * dotSize} 0 0 0 ${2.5 * -dotSize} ${2.5 * dotSize} z M ${x + 2.5 * dotSize} ${y + dotSize} h ${2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * dotSize} ${1.5 * dotSize} v ${3.5 * dotSize} h ${-3.5 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * -dotSize} ${1.5 * -dotSize} v ${-2 * dotSize} a ${1.5 * dotSize} ${1.5 * dotSize} 0 0 1 ${1.5 * dotSize} ${1.5 * -dotSize} z`);
|
|
314
309
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
315
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + .5 *
|
|
310
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x + .5 * dotSize} ${y - dotSize} h ${4 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 1 ${3.5 * dotSize} ${3.5 * dotSize} v ${5.5 * dotSize} h ${-5.5 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 1 ${3.5 * -dotSize} ${3.5 * -dotSize} v ${-2 * dotSize} a ${3.5 * dotSize} ${3.5 * dotSize} 0 0 1 ${3.5 * dotSize} ${3.5 * -dotSize} z`),
|
|
316
311
|
[ element, fill ];
|
|
317
312
|
},
|
|
318
313
|
centerCircle: args => {
|
|
319
|
-
const {x, y, size} = args;
|
|
320
|
-
|
|
321
|
-
const cx = x + size / 2, cy = y + size / 2;
|
|
322
|
-
args = size / 7;
|
|
323
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
324
|
-
return element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y} h ${size} v ${size} h ${-size} z M ${cx - circleRadius_fill} ${cy} a ${circleRadius_fill} ${circleRadius_fill} 0 1 0 ${2 * circleRadius_fill} 0 a ${circleRadius_fill} ${circleRadius_fill} 0 1 0 ${2 * -circleRadius_fill} 0 z`),
|
|
325
|
-
(circleRadius_fill = document.createElementNS("http://www.w3.org/2000/svg", "path")).setAttribute("clip-rule", "evenodd"),
|
|
326
|
-
circleRadius_fill.setAttribute("d", svgPath`M ${x - args} ${y - args} h ${size + 2 * args} v ${size + 2 * args} h ${-size - 2 * args} z`),
|
|
327
|
-
[ element, circleRadius_fill ];
|
|
328
|
-
},
|
|
329
|
-
cornerCut: args => {
|
|
330
|
-
const {x, y, size} = args;
|
|
331
|
-
args = size / 8;
|
|
332
|
-
const element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
333
|
-
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", `M ${x} ${y} L ${x + size} ${y} L ${x + size} ${y + size - args} Q ${x + size} ${y + size} ${x + size - args} ${y + size} L ${x + args} ${y + size} Q ${x} ${y + size - args} ${x} ${y + size - args} Z M ${x + args} ${y + args} L ${x + size - args} ${y + args} L ${x + size - args} ${y + size - args} L ${x + args} ${y + size - args} Z`);
|
|
314
|
+
const {x, y, size} = args, circleRadius = size / 2.5, cx = x + size / 2, cy = y + size / 2, dotSize = size / 7, element = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
315
|
+
element.setAttribute("clip-rule", "evenodd"), element.setAttribute("d", svgPath`M ${x} ${y} h ${size} v ${size} h ${-size} z M ${cx - circleRadius} ${cy} a ${circleRadius} ${circleRadius} 0 1 0 ${2 * circleRadius} 0 a ${circleRadius} ${circleRadius} 0 1 0 ${2 * -circleRadius} 0 z`);
|
|
334
316
|
const fill = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
335
|
-
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x -
|
|
317
|
+
return fill.setAttribute("clip-rule", "evenodd"), fill.setAttribute("d", svgPath`M ${x - dotSize} ${y - dotSize} h ${size + 2 * dotSize} v ${size + 2 * dotSize} h ${-size - 2 * dotSize} z`),
|
|
336
318
|
[ element, fill ];
|
|
337
319
|
}
|
|
338
320
|
}, qrCornerSquareFigures = {
|
|
@@ -353,38 +335,49 @@ let DotElements = {
|
|
|
353
335
|
draw: SquareElements.inpoint
|
|
354
336
|
}),
|
|
355
337
|
[CornerSquareType.centerCircle]: args => SquareElements.centerCircle(args)
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
let compoundDots_rounded = ({x, y, size, document, getNeighbor}, {corner = DotElements.cornerRounded, end = DotElements.sideRounded} = {}) => {
|
|
341
|
+
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0, rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0, topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0, bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0, neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor;
|
|
342
|
+
if (0 === neighborsCount) return DotElements.dot({
|
|
359
343
|
x,
|
|
360
344
|
y,
|
|
361
345
|
size,
|
|
362
346
|
document
|
|
363
|
-
})
|
|
347
|
+
});
|
|
348
|
+
if (neighborsCount > 2 || leftNeighbor && rightNeighbor || topNeighbor && bottomNeighbor) return DotElements.square({
|
|
364
349
|
x,
|
|
365
350
|
y,
|
|
366
351
|
size,
|
|
367
352
|
document
|
|
368
|
-
})
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
353
|
+
});
|
|
354
|
+
if (2 === neighborsCount) {
|
|
355
|
+
let rotation = 0;
|
|
356
|
+
return leftNeighbor && topNeighbor ? rotation = Math.PI / 2 : topNeighbor && rightNeighbor ? rotation = Math.PI : rightNeighbor && bottomNeighbor && (rotation = -Math.PI / 2),
|
|
357
|
+
rotateFigure({
|
|
358
|
+
x,
|
|
359
|
+
y,
|
|
360
|
+
size,
|
|
361
|
+
rotation,
|
|
362
|
+
document,
|
|
363
|
+
draw: corner
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
{
|
|
367
|
+
let rotation = 0;
|
|
368
|
+
return topNeighbor ? rotation = Math.PI / 2 : rightNeighbor ? rotation = Math.PI : bottomNeighbor && (rotation = -Math.PI / 2),
|
|
369
|
+
rotateFigure({
|
|
370
|
+
x,
|
|
371
|
+
y,
|
|
372
|
+
size,
|
|
373
|
+
rotation,
|
|
374
|
+
document,
|
|
375
|
+
draw: end
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}, compoundDots_classy = ({x, y, size, document, getNeighbor}, {corner = DotElements.cornerRounded} = {}) => {
|
|
379
|
+
const leftNeighbor = getNeighbor ? +getNeighbor(-1, 0) : 0, rightNeighbor = getNeighbor ? +getNeighbor(1, 0) : 0, topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0, bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
380
|
+
return 0 === leftNeighbor + rightNeighbor + topNeighbor + bottomNeighbor ? rotateFigure({
|
|
388
381
|
x,
|
|
389
382
|
y,
|
|
390
383
|
size,
|
|
@@ -411,15 +404,15 @@ let DotElements = {
|
|
|
411
404
|
document,
|
|
412
405
|
draw: corner
|
|
413
406
|
});
|
|
414
|
-
}, compoundDots_line = ({x, y, size, document, getNeighbor
|
|
415
|
-
const topNeighbor =
|
|
416
|
-
return
|
|
407
|
+
}, compoundDots_line = ({x, y, size, document, getNeighbor}, {stripe = size, rotation = 0} = {}) => {
|
|
408
|
+
const topNeighbor = getNeighbor ? +getNeighbor(0, -1) : 0, bottomNeighbor = getNeighbor ? +getNeighbor(0, 1) : 0;
|
|
409
|
+
return topNeighbor && bottomNeighbor ? rotateFigure({
|
|
417
410
|
x,
|
|
418
411
|
y,
|
|
419
412
|
size,
|
|
420
413
|
rotation,
|
|
421
414
|
document,
|
|
422
|
-
draw:
|
|
415
|
+
draw: _ => DotElements.square({
|
|
423
416
|
x,
|
|
424
417
|
y,
|
|
425
418
|
size,
|
|
@@ -451,7 +444,7 @@ let DotElements = {
|
|
|
451
444
|
size,
|
|
452
445
|
rotation,
|
|
453
446
|
document,
|
|
454
|
-
draw:
|
|
447
|
+
draw: _ => DotElements.dot({
|
|
455
448
|
x: x + (size - stripe) / 2,
|
|
456
449
|
y: y + (size - stripe) / 2,
|
|
457
450
|
size: stripe,
|
|
@@ -460,10 +453,13 @@ let DotElements = {
|
|
|
460
453
|
});
|
|
461
454
|
}, qrDotFigures = {
|
|
462
455
|
[DotType.dot]: args => DotElements.dot(args),
|
|
463
|
-
[DotType.randomDot]: ({size, ...args}) =>
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
456
|
+
[DotType.randomDot]: ({size, ...args}) => {
|
|
457
|
+
const randomFactor = .25 * Math.random() + .75;
|
|
458
|
+
return DotElements.dot({
|
|
459
|
+
...args,
|
|
460
|
+
size: size * randomFactor
|
|
461
|
+
});
|
|
462
|
+
},
|
|
467
463
|
[DotType.rounded]: args => compoundDots_rounded(args),
|
|
468
464
|
[DotType.extraRounded]: args => compoundDots_rounded(args, {
|
|
469
465
|
corner: DotElements.cornerExtraRounded
|
|
@@ -529,8 +525,18 @@ let DotElements = {
|
|
|
529
525
|
})
|
|
530
526
|
};
|
|
531
527
|
|
|
532
|
-
function getQrDotFigure(type) {
|
|
533
|
-
|
|
528
|
+
function getQrDotFigure(type, plugins) {
|
|
529
|
+
let defaultDraw = qrDotFigures[type] || qrDotFigures[DotType.square];
|
|
530
|
+
if (!plugins?.length) return defaultDraw;
|
|
531
|
+
let drawPlugin = function(plugins) {
|
|
532
|
+
return args => {
|
|
533
|
+
for (let plugin of plugins) {
|
|
534
|
+
let el = plugin.drawDot?.(args);
|
|
535
|
+
if (el) return el;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}(plugins);
|
|
539
|
+
return args => drawPlugin(args) || defaultDraw(args);
|
|
534
540
|
}
|
|
535
541
|
|
|
536
542
|
let browserImageTools = {
|
|
@@ -562,25 +568,32 @@ let browserImageTools = {
|
|
|
562
568
|
})
|
|
563
569
|
};
|
|
564
570
|
|
|
565
|
-
function parseColor(
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
size
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
m_parts[1] || (m_parts[1] = 0), m_parts[2] || (m_parts[2] = 0);
|
|
571
|
+
function parseColor(cstr) {
|
|
572
|
+
let m, parts = [], alpha = 1;
|
|
573
|
+
if ("#" === (cstr = cstr.toLowerCase())[0]) {
|
|
574
|
+
let base = cstr.slice(1), size = base.length;
|
|
575
|
+
size <= 4 ? (parts = [ parseInt(base[0] + base[0], 16), parseInt(base[1] + base[1], 16), parseInt(base[2] + base[2], 16) ],
|
|
576
|
+
4 === size && (alpha = parseInt(base[3] + base[3], 16) / 255)) : (parts = [ parseInt(base[0] + base[1], 16), parseInt(base[2] + base[3], 16), parseInt(base[4] + base[5], 16) ],
|
|
577
|
+
8 === size && (alpha = parseInt(base[6] + base[7], 16) / 255)), parts[0] || (parts[0] = 0),
|
|
578
|
+
parts[1] || (parts[1] = 0), parts[2] || (parts[2] = 0);
|
|
574
579
|
} else {
|
|
575
|
-
if (!(
|
|
576
|
-
value:
|
|
580
|
+
if (!(m = /^((?:rgba?))\s*\(([^)]*)\)/.exec(cstr))) return {
|
|
581
|
+
value: cstr,
|
|
577
582
|
alpha
|
|
578
583
|
};
|
|
579
|
-
|
|
580
|
-
|
|
584
|
+
{
|
|
585
|
+
let dims = 3;
|
|
586
|
+
parts = m[2].trim().split(/\s*[,/]\s*|\s+/), parts = parts.map((x, i) => {
|
|
587
|
+
if ("%" === x[x.length - 1]) {
|
|
588
|
+
let v = parseFloat(x) / 100;
|
|
589
|
+
return 3 === i ? v : 255 * v;
|
|
590
|
+
}
|
|
591
|
+
return "none" === x ? 0 : parseFloat(x);
|
|
592
|
+
}), alpha = parts.length > dims ? parts.pop() : 1;
|
|
593
|
+
}
|
|
581
594
|
}
|
|
582
595
|
return {
|
|
583
|
-
value: "#" +
|
|
596
|
+
value: "#" + parts.map(v => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join(""),
|
|
584
597
|
alpha: Math.max(0, Math.min(1, alpha))
|
|
585
598
|
};
|
|
586
599
|
}
|
|
@@ -618,76 +631,78 @@ class QRSVG {
|
|
|
618
631
|
get height() {
|
|
619
632
|
return this.options.height;
|
|
620
633
|
}
|
|
621
|
-
async drawQR(
|
|
622
|
-
let count =
|
|
623
|
-
var alignment_maxWidth_typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10);
|
|
624
|
-
let dotSize = this.options.dotsOptions.size, drawImageSize = {
|
|
634
|
+
async drawQR(qr) {
|
|
635
|
+
let count = qr.getModuleCount(), typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10), dotSize = this.options.dotsOptions.size, drawImageSize = {
|
|
625
636
|
hideXDots: 0,
|
|
626
637
|
hideYDots: 0,
|
|
627
638
|
width: 0,
|
|
628
639
|
height: 0
|
|
629
640
|
};
|
|
630
|
-
if (this.qr =
|
|
631
|
-
|
|
632
|
-
let {imageOptions, errorCorrectionPercent} = this.options;
|
|
641
|
+
if (this.qr = qr, this.options.image) {
|
|
642
|
+
let size = await this.imageTools.getSize(this.options.image, this.options.imageOptions.crossOrigin), {imageOptions, errorCorrectionPercent} = this.options;
|
|
633
643
|
if (imageOptions.mode == ImageMode.background) {
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
let {width, height} = qr_size;
|
|
638
|
-
height = height / width * alignment_maxWidth_typeNumber, width = alignment_maxWidth_typeNumber,
|
|
639
|
-
height > coverLevel_margin && (width = width / height * coverLevel_margin, height = coverLevel_margin),
|
|
640
|
-
drawImageSize = {
|
|
644
|
+
let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0, maxWidth = (this.options.width - 2 * margin * dotSize) * imageOptions.imageSize, maxHeight = (this.options.height - 2 * margin * dotSize) * imageOptions.imageSize, {width, height} = size;
|
|
645
|
+
height = height / width * maxWidth, width = maxWidth, height > maxHeight && (width = width / height * maxHeight,
|
|
646
|
+
height = maxHeight), drawImageSize = {
|
|
641
647
|
hideXDots: 0,
|
|
642
648
|
hideYDots: 0,
|
|
643
649
|
width,
|
|
644
650
|
height
|
|
645
651
|
};
|
|
646
|
-
} else
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
652
|
+
} else {
|
|
653
|
+
let coverLevel = imageOptions.imageSize * errorCorrectionPercent, alignment = QRUtil.getPatternPosition(typeNumber), maxHiddenDots = Math.floor(coverLevel * (count * count - 192 - 2 * (count - 16) - alignment.length ** 2 * 25));
|
|
654
|
+
drawImageSize = function({originalHeight, originalWidth, maxHiddenDots, maxHiddenAxisDots, dotSize, margin}) {
|
|
655
|
+
let hideDots = {
|
|
656
|
+
x: 0,
|
|
657
|
+
y: 0
|
|
658
|
+
}, imageSize = {
|
|
659
|
+
x: 0,
|
|
660
|
+
y: 0
|
|
661
|
+
};
|
|
662
|
+
if (originalHeight <= 0 || originalWidth <= 0 || maxHiddenDots <= 0 || dotSize <= 0 || 4 * margin ** 2 > maxHiddenDots) return {
|
|
663
|
+
height: 0,
|
|
664
|
+
width: 0,
|
|
665
|
+
hideYDots: 0,
|
|
666
|
+
hideXDots: 0
|
|
667
|
+
};
|
|
668
|
+
maxHiddenAxisDots && maxHiddenAxisDots % 2 == 0 && (maxHiddenAxisDots = Math.max(1, maxHiddenAxisDots - 1));
|
|
669
|
+
let dimMax = Math.max(originalWidth, originalHeight), dimMin = Math.min(originalWidth, originalHeight), lower = 0, upper = (maxHiddenAxisDots || maxHiddenDots) - 2 * margin;
|
|
670
|
+
do {
|
|
671
|
+
let newSize = lower + (upper - lower) / 2, dotsMax = Math.max(1, Math.ceil(newSize + 2 * margin));
|
|
672
|
+
dotsMax % 2 == 0 && dotsMax++;
|
|
673
|
+
let dotsMin = Math.max(1, Math.ceil(newSize * dimMin / dimMax + 2 * margin));
|
|
674
|
+
dotsMin % 2 == 0 && dotsMin++, dotsMax * dotsMin > maxHiddenDots ? upper = newSize : lower = newSize;
|
|
675
|
+
} while (Math.abs(lower - upper) > .001);
|
|
676
|
+
let size = lower, hideMax = Math.max(1, Math.ceil(size + 2 * margin));
|
|
677
|
+
hideMax % 2 == 0 && hideMax++;
|
|
678
|
+
let hideMin = Math.max(1, Math.ceil(size * dimMin / dimMax + 2 * margin));
|
|
679
|
+
hideMin % 2 == 0 && hideMin++, originalWidth > originalHeight ? (hideDots.x = hideMax,
|
|
680
|
+
hideDots.y = hideMin) : (hideDots.x = hideMin, hideDots.y = hideMax);
|
|
681
|
+
let maxW = (hideDots.x - 2 * margin) * dotSize, maxH = (hideDots.y - 2 * margin) * dotSize;
|
|
682
|
+
return imageSize.x = maxW, imageSize.y = maxW * originalHeight / originalWidth,
|
|
683
|
+
imageSize.y > maxH && (imageSize.y = maxH, imageSize.x = maxH * originalWidth / originalHeight),
|
|
684
|
+
{
|
|
685
|
+
height: Math.round(imageSize.y + 2 * margin * dotSize),
|
|
686
|
+
width: Math.round(imageSize.x + 2 * margin * dotSize),
|
|
687
|
+
hideYDots: hideDots.y,
|
|
688
|
+
hideXDots: hideDots.x
|
|
689
|
+
};
|
|
690
|
+
}({
|
|
691
|
+
originalWidth: size.width,
|
|
692
|
+
originalHeight: size.height,
|
|
693
|
+
maxHiddenDots,
|
|
694
|
+
maxHiddenAxisDots: count - 14,
|
|
695
|
+
dotSize,
|
|
696
|
+
margin: imageOptions.margin
|
|
697
|
+
});
|
|
698
|
+
}
|
|
684
699
|
}
|
|
685
700
|
this.drawBackground(), this.options.imageOptions.mode != ImageMode.overlay && this.options.image && drawImageSize.width > 0 && drawImageSize.height > 0 && await this.drawImage({
|
|
686
701
|
width: drawImageSize.width,
|
|
687
702
|
height: drawImageSize.height,
|
|
688
703
|
count,
|
|
689
704
|
dotSize
|
|
690
|
-
}), this.drawDots((i, j) => !(this.options.imageOptions.mode == ImageMode.center && i >= (count - drawImageSize.hideXDots) / 2 && i < (count + drawImageSize.hideXDots) / 2 && j >= (count - drawImageSize.hideYDots) / 2 && j < (count + drawImageSize.hideYDots) / 2
|
|
705
|
+
}), this.drawDots((i, j) => !(this.options.imageOptions.mode == ImageMode.center && i >= (count - drawImageSize.hideXDots) / 2 && i < (count + drawImageSize.hideXDots) / 2 && j >= (count - drawImageSize.hideYDots) / 2 && j < (count + drawImageSize.hideYDots) / 2) && !(i < 8 && j < 8 || i >= count - 8 && j < 8 || j >= count - 8 && i < 8)),
|
|
691
706
|
this.options.imageOptions.mode == ImageMode.overlay && this.options.image && drawImageSize.width > 0 && drawImageSize.height > 0 && await this.drawImage({
|
|
692
707
|
width: drawImageSize.width,
|
|
693
708
|
height: drawImageSize.height,
|
|
@@ -698,9 +713,10 @@ class QRSVG {
|
|
|
698
713
|
drawBackground() {
|
|
699
714
|
let options = this.options;
|
|
700
715
|
if (this._element && options.backgroundOptions) {
|
|
716
|
+
let gradientOptions = options.backgroundOptions.gradient, color = options.backgroundOptions.color;
|
|
701
717
|
this.createColor({
|
|
702
|
-
options:
|
|
703
|
-
color
|
|
718
|
+
options: gradientOptions,
|
|
719
|
+
color,
|
|
704
720
|
additionalRotation: 0,
|
|
705
721
|
x: 0,
|
|
706
722
|
y: 0,
|
|
@@ -716,149 +732,172 @@ class QRSVG {
|
|
|
716
732
|
this.backgroundMaskGroup.appendChild(element);
|
|
717
733
|
}
|
|
718
734
|
}
|
|
719
|
-
drawDots(
|
|
720
|
-
if (!this.qr) throw Error("QR code is not defined");
|
|
721
|
-
let options = this.options;
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
options.imageOptions.mode == ImageMode.background && (minSize_xFakeBeginning -= 2 * dotSize * (options.imageOptions.margin || 0));
|
|
727
|
-
var colorCount_xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning_yFakeBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
728
|
-
let draw = getQrDotFigure(options.dotsOptions.type);
|
|
735
|
+
drawDots(filter) {
|
|
736
|
+
if (!this.qr) throw new Error("QR code is not defined");
|
|
737
|
+
let options = this.options, count = this.qr.getModuleCount();
|
|
738
|
+
if (count > options.width || count > options.height) throw new Error("The canvas is too small");
|
|
739
|
+
let dotSize = this.options.dotsOptions.size, minSize = Math.min(options.width, options.height);
|
|
740
|
+
options.imageOptions.mode == ImageMode.background && (minSize -= 2 * dotSize * (options.imageOptions.margin || 0));
|
|
741
|
+
let xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2), draw = getQrDotFigure(options.dotsOptions.type, options.plugins);
|
|
729
742
|
[this.dotsMask, this.dotsMaskGroup] = this.createMask("mask-dot-color"), this.defs.appendChild(this.dotsMask),
|
|
730
743
|
options.imageOptions.mode == ImageMode.background && ([this.lightDotsMask, this.lightDotsMaskGroup] = this.createMask("mask-light-dot-color"),
|
|
731
744
|
this.defs.appendChild(this.lightDotsMask));
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
745
|
+
let margin = 0, additionalDots = 0, fakeCount = count;
|
|
746
|
+
options.shape === ShapeType.circle ? (margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0,
|
|
747
|
+
additionalDots = Math.floor((minSize / dotSize - count - 2 * margin) / 2), fakeCount = count + 2 * additionalDots) : options.imageOptions.mode == ImageMode.background && (additionalDots = 1,
|
|
748
|
+
fakeCount = count + 2 * additionalDots);
|
|
749
|
+
let xFakeBeginning = xBeginning - additionalDots * dotSize, yFakeBeginning = yBeginning - additionalDots * dotSize, colorX = xFakeBeginning, colorY = yFakeBeginning, colorCount = count + 2 * additionalDots, fakeMatrix = new Array(fakeCount), center = Math.floor(fakeCount / 2);
|
|
750
|
+
for (let i = 0; i < fakeCount; i++) {
|
|
751
|
+
fakeMatrix[i] = new Array(fakeCount);
|
|
752
|
+
for (let j = 0; j < fakeCount; j++) {
|
|
753
|
+
if (i > additionalDots - 1 && i < fakeCount - additionalDots && j > additionalDots - 1 && j < fakeCount - additionalDots) {
|
|
754
|
+
let ii = i - additionalDots, jj = j - additionalDots;
|
|
755
|
+
filter && !filter(ii, jj) ? fakeMatrix[i][j] = void 0 : fakeMatrix[i][j] = !!this.qr.isDark(jj, ii);
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
options.shape === ShapeType.circle && Math.sqrt((i - center) * (i - center) + (j - center) * (j - center)) > center ? fakeMatrix[i][j] = void 0 : fakeMatrix[i][j] = i != additionalDots - 1 && i != fakeCount - additionalDots && j != additionalDots - 1 && j != fakeCount - additionalDots ? 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) : (j == additionalDots - 1 && (i < additionalDots + 8 || i > fakeCount - additionalDots - 9) || j == fakeCount - additionalDots && i < additionalDots + 8 || i == additionalDots - 1 && (j < additionalDots + 8 || j > fakeCount - additionalDots - 9) || i == fakeCount - additionalDots && j < additionalDots + 8) && void 0;
|
|
759
|
+
}
|
|
747
760
|
}
|
|
748
|
-
|
|
749
|
-
for (let i = 0; i <
|
|
750
|
-
|
|
751
|
-
for (let j = 0; j <
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
761
|
+
let typeNr = (count - 17) / 4, alignment = QRUtil.getPatternPosition(typeNr);
|
|
762
|
+
for (let i = 0; i < fakeCount; i++) {
|
|
763
|
+
let iAlign = alignment.find(v => i - additionalDots > v - 3 && i - additionalDots < v + 3);
|
|
764
|
+
for (let j = 0; j < fakeCount; j++) {
|
|
765
|
+
let jAlign = alignment.find(v => j - additionalDots > v - 3 && j - additionalDots < v + 3);
|
|
766
|
+
null != fakeMatrix[i][j] && (this.lightDotsMask && (draw = iAlign && jAlign && (iAlign != alignment[0] && jAlign != alignment[0] || jAlign != alignment[0] && jAlign != alignment[alignment.length - 1] || iAlign != alignment[0] && iAlign != alignment[alignment.length - 1]) ? getQrDotFigure(DotType.square) : getQrDotFigure(DotType.tinySquare)),
|
|
767
|
+
fakeMatrix[i][j] ? this.dotsMaskGroup && this.dotsMaskGroup.appendChild(draw({
|
|
768
|
+
x: xFakeBeginning + i * dotSize,
|
|
769
|
+
y: yFakeBeginning + j * dotSize,
|
|
770
|
+
size: dotSize,
|
|
771
|
+
document: this.options.document,
|
|
772
|
+
getNeighbor: (xOffset, yOffset) => !0 === fakeMatrix[i + xOffset]?.[j + yOffset]
|
|
773
|
+
})) : this.lightDotsMask && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
|
|
774
|
+
x: xFakeBeginning + i * dotSize,
|
|
775
|
+
y: yFakeBeginning + j * dotSize,
|
|
776
|
+
size: dotSize,
|
|
777
|
+
document: this.options.document,
|
|
778
|
+
getNeighbor: (xOffset, yOffset) => !1 === fakeMatrix[i + xOffset]?.[j + yOffset]
|
|
779
|
+
})));
|
|
780
|
+
}
|
|
766
781
|
}
|
|
767
782
|
this.lightDotsMask && this.createColor({
|
|
768
783
|
options: options.imageOptions.fill.gradient,
|
|
769
784
|
color: options.imageOptions.fill.color,
|
|
770
785
|
additionalRotation: 0,
|
|
771
|
-
x:
|
|
772
|
-
y:
|
|
773
|
-
height:
|
|
774
|
-
width:
|
|
786
|
+
x: colorX,
|
|
787
|
+
y: colorY,
|
|
788
|
+
height: colorCount * dotSize,
|
|
789
|
+
width: colorCount * dotSize,
|
|
775
790
|
name: "light-dot-color"
|
|
776
791
|
}), this.createColor({
|
|
777
792
|
options: options.dotsOptions?.gradient,
|
|
778
793
|
color: options.dotsOptions.color,
|
|
779
794
|
additionalRotation: 0,
|
|
780
|
-
x:
|
|
781
|
-
y:
|
|
782
|
-
height:
|
|
783
|
-
width:
|
|
795
|
+
x: colorX,
|
|
796
|
+
y: colorY,
|
|
797
|
+
height: colorCount * dotSize,
|
|
798
|
+
width: colorCount * dotSize,
|
|
784
799
|
name: "dot-color"
|
|
785
800
|
});
|
|
786
801
|
}
|
|
787
802
|
drawCorners() {
|
|
788
|
-
if (!this.qr) throw Error("QR code is not defined");
|
|
789
|
-
let options = this.options;
|
|
790
|
-
if (!
|
|
803
|
+
if (!this.qr) throw new Error("QR code is not defined");
|
|
804
|
+
let element = this._element, options = this.options;
|
|
805
|
+
if (!element) throw new Error("Element code is not defined");
|
|
791
806
|
let count = this.qr.getModuleCount(), dotSize = this.options.dotsOptions.size, cornersSquareSize = 7 * dotSize, cornersDotSize = 3 * dotSize, xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2);
|
|
792
|
-
[ [ 0, 0, 0 ], [ 1, 0, Math.PI / 2 ], [ 0, 1, -Math.PI / 2 ] ].forEach(([
|
|
793
|
-
let x = xBeginning +
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
if (cornersDotMaskGroup_cornersSquareMask = this.dotsMaskGroup, (options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && ([cornersDotMaskGroup_cornersSquareMask, cornersSquareMaskGroup] = this.createMask(`mask-corners-square-color-${column_draw}-${row}`),
|
|
798
|
-
this.defs.appendChild(cornersDotMaskGroup_cornersSquareMask), cornersDotMask_draw = cornersDotMaskGroup_cornersSquareMask,
|
|
799
|
-
cornersDotMaskGroup_cornersSquareMask = cornersSquareMaskGroup, this.createColor({
|
|
807
|
+
[ [ 0, 0, 0 ], [ 1, 0, Math.PI / 2 ], [ 0, 1, -Math.PI / 2 ] ].forEach(([column, row, rotation]) => {
|
|
808
|
+
let x = xBeginning + column * dotSize * (count - 7), y = yBeginning + row * dotSize * (count - 7), cornersSquareMask = this.dotsMask, cornersSquareMaskGroup = this.dotsMaskGroup, cornersDotMask = this.dotsMask, cornersDotMaskGroup = this.dotsMaskGroup;
|
|
809
|
+
(options.cornersSquareOptions?.gradient || options.cornersSquareOptions?.color) && ([cornersSquareMask, cornersSquareMaskGroup] = this.createMask(`mask-corners-square-color-${column}-${row}`),
|
|
810
|
+
this.defs.appendChild(cornersSquareMask), cornersDotMask = cornersSquareMask, cornersDotMaskGroup = cornersSquareMaskGroup,
|
|
811
|
+
this.createColor({
|
|
800
812
|
options: options.cornersSquareOptions?.gradient,
|
|
801
813
|
color: options.cornersSquareOptions?.color,
|
|
802
|
-
additionalRotation:
|
|
814
|
+
additionalRotation: rotation,
|
|
803
815
|
x,
|
|
804
816
|
y,
|
|
805
817
|
height: cornersSquareSize,
|
|
806
818
|
width: cornersSquareSize,
|
|
807
|
-
name: `corners-square-color-${
|
|
808
|
-
}))
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
819
|
+
name: `corners-square-color-${column}-${row}`
|
|
820
|
+
}));
|
|
821
|
+
let squareArgs = {
|
|
822
|
+
x,
|
|
823
|
+
y,
|
|
824
|
+
size: cornersSquareSize,
|
|
825
|
+
document: this.options.document,
|
|
826
|
+
rotation
|
|
827
|
+
}, pluinCornerSquare = options.plugins?.length ? (plugins = options.plugins, args => {
|
|
828
|
+
for (let plugin of plugins) {
|
|
829
|
+
let el = plugin.drawCornerSquare?.(args);
|
|
830
|
+
if (el) return el;
|
|
831
|
+
}
|
|
832
|
+
})(squareArgs) : void 0;
|
|
833
|
+
var plugins, type, val;
|
|
834
|
+
if (pluinCornerSquare) {
|
|
835
|
+
let [cornerElement, cornerFill] = pluinCornerSquare;
|
|
836
|
+
cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(cornerElement), this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(cornerFill);
|
|
837
|
+
} else if (val = options.cornersSquareOptions?.type, val && cornerSquareTypes.has(val)) {
|
|
838
|
+
let draw = (type = options.cornersSquareOptions.type, qrCornerSquareFigures[type] || qrCornerSquareFigures[CornerSquareType.square]), [cornerElement, cornerFill] = draw(squareArgs);
|
|
816
839
|
cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(cornerElement), this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(cornerFill);
|
|
817
840
|
} else {
|
|
818
|
-
|
|
819
|
-
for (let i = 0; i < squareMask.length; i++) for (let j = 0; j < squareMask[i].length; j++) squareMask[i]?.[j] ? cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(
|
|
841
|
+
let draw = getQrDotFigure(options.cornersSquareOptions?.type || options.dotsOptions.type, options.plugins);
|
|
842
|
+
for (let i = 0; i < squareMask.length; i++) for (let j = 0; j < squareMask[i].length; j++) squareMask[i]?.[j] ? cornersSquareMaskGroup && cornersSquareMaskGroup.appendChild(draw({
|
|
820
843
|
x: x + i * dotSize,
|
|
821
844
|
y: y + j * dotSize,
|
|
822
845
|
size: dotSize,
|
|
823
846
|
document: this.options.document,
|
|
824
847
|
getNeighbor: (xOffset, yOffset) => !!squareMask[i + xOffset]?.[j + yOffset]
|
|
825
|
-
})) : this.lightDotsMask && !dotMask[i]?.[j] && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(
|
|
848
|
+
})) : this.lightDotsMask && !dotMask[i]?.[j] && this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
|
|
826
849
|
x: x + i * dotSize,
|
|
827
850
|
y: y + j * dotSize,
|
|
828
851
|
size: dotSize,
|
|
829
852
|
document: this.options.document,
|
|
830
853
|
getNeighbor: (xOffset, yOffset) => !squareMask[i + xOffset]?.[j + yOffset] && !dotMask[i + xOffset]?.[j + yOffset]
|
|
831
854
|
}));
|
|
832
|
-
if (this.lightDotsMask) for (let i = -1; i < 8; i++) for (let j = -1; j < 8; j++)
|
|
855
|
+
if (this.lightDotsMask) for (let i = -1; i < 8; i++) for (let j = -1; j < 8; j++) -1 != i && 7 != i && -1 != j && 7 != j || this.lightDotsMaskGroup && this.lightDotsMaskGroup.appendChild(draw({
|
|
833
856
|
x: x + i * dotSize,
|
|
834
857
|
y: y + j * dotSize,
|
|
835
858
|
size: dotSize,
|
|
836
859
|
document: this.options.document,
|
|
837
|
-
getNeighbor: (
|
|
860
|
+
getNeighbor: (xOffset, yOffset) => {
|
|
861
|
+
let ii = i + xOffset, jj = j + yOffset;
|
|
862
|
+
return ii >= -1 && ii <= 7 && jj >= -1 && jj <= 7 && (-1 == ii || 7 == ii || -1 == jj || 7 == jj);
|
|
863
|
+
}
|
|
838
864
|
}));
|
|
839
865
|
}
|
|
840
|
-
|
|
841
|
-
this.defs.appendChild(
|
|
866
|
+
(options.cornersDotOptions?.gradient || options.cornersDotOptions?.color) && ([cornersDotMask, cornersDotMaskGroup] = this.createMask(`mask-corners-dot-color-${column}-${row}`),
|
|
867
|
+
this.defs.appendChild(cornersDotMask), this.createColor({
|
|
842
868
|
options: options.cornersDotOptions?.gradient,
|
|
843
869
|
color: options.cornersDotOptions?.color,
|
|
844
|
-
additionalRotation:
|
|
870
|
+
additionalRotation: rotation,
|
|
845
871
|
x: x + 2 * dotSize,
|
|
846
872
|
y: y + 2 * dotSize,
|
|
847
873
|
height: cornersDotSize,
|
|
848
874
|
width: cornersDotSize,
|
|
849
|
-
name: `corners-dot-color-${
|
|
850
|
-
}))
|
|
851
|
-
|
|
852
|
-
}(options.cornersDotOptions?.type)) column_draw = qrCornerDotFigures[options.cornersDotOptions.type] || qrCornerDotFigures[CornerDotType.square],
|
|
853
|
-
cornersDotMaskGroup_cornersSquareMask && cornersDotMaskGroup_cornersSquareMask.appendChild(column_draw({
|
|
875
|
+
name: `corners-dot-color-${column}-${row}`
|
|
876
|
+
}));
|
|
877
|
+
let dotArgs = {
|
|
854
878
|
x: x + 2 * dotSize,
|
|
855
879
|
y: y + 2 * dotSize,
|
|
856
880
|
size: cornersDotSize,
|
|
857
881
|
document: this.document,
|
|
858
|
-
rotation
|
|
859
|
-
})
|
|
860
|
-
|
|
861
|
-
|
|
882
|
+
rotation
|
|
883
|
+
}, pluinCornerDot = options.plugins?.length ? function(plugins) {
|
|
884
|
+
return args => {
|
|
885
|
+
for (let plugin of plugins) {
|
|
886
|
+
let el = plugin.drawCornerDot?.(args);
|
|
887
|
+
if (el) return el;
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
}(options.plugins)(dotArgs) : void 0;
|
|
891
|
+
if (pluinCornerDot) cornersDotMaskGroup && cornersDotMaskGroup.appendChild(pluinCornerDot); else if (function(val) {
|
|
892
|
+
return !(!val || !cornerDotTypes.has(val));
|
|
893
|
+
}(options.cornersDotOptions?.type)) {
|
|
894
|
+
let draw = function(type) {
|
|
895
|
+
return qrCornerDotFigures[type] || qrCornerDotFigures[CornerDotType.square];
|
|
896
|
+
}(options.cornersDotOptions.type);
|
|
897
|
+
cornersDotMaskGroup && cornersDotMaskGroup.appendChild(draw(dotArgs));
|
|
898
|
+
} else {
|
|
899
|
+
let draw = getQrDotFigure(options.cornersDotOptions?.type || options.dotsOptions.type, options.plugins);
|
|
900
|
+
for (let i = 0; i < dotMask.length; i++) for (let j = 0; j < dotMask[i].length; j++) dotMask[i]?.[j] && cornersDotMaskGroup && cornersDotMaskGroup.appendChild(draw({
|
|
862
901
|
x: x + i * dotSize,
|
|
863
902
|
y: y + j * dotSize,
|
|
864
903
|
size: dotSize,
|
|
@@ -868,24 +907,25 @@ class QRSVG {
|
|
|
868
907
|
}
|
|
869
908
|
});
|
|
870
909
|
}
|
|
871
|
-
async drawImage({width
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
count =
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
if (
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
910
|
+
async drawImage({width, height, count, dotSize}) {
|
|
911
|
+
let options = this.options, xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning = Math.floor((options.height - count * dotSize) / 2), margin = options.imageOptions.margin * dotSize;
|
|
912
|
+
options.imageOptions.mode == ImageMode.background && (margin = 0);
|
|
913
|
+
let dx = xBeginning + margin + (count * dotSize - width) / 2, dy = yBeginning + margin + (count * dotSize - height) / 2, dw = width - 2 * margin, dh = height - 2 * margin, imageUrl = await this.imageTools.toDataURL(options.image || ""), image = this.document.createElementNS("http://www.w3.org/2000/svg", "image");
|
|
914
|
+
if (image.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", imageUrl || ""),
|
|
915
|
+
imageUrl.startsWith("data:image/svg+xml;")) {
|
|
916
|
+
let data = imageUrl.substring(19), i = data.indexOf(","), encoding = data.substring(0, i);
|
|
917
|
+
if (data = data.substring(i + 1), "base64" === encoding) data = "function" == typeof atob ? atob(data) : Buffer.from(data, "base64").toString("utf8"); else data = "";
|
|
918
|
+
if (data) {
|
|
919
|
+
let container = (new DOMParser).parseFromString(data, "text/xml"), rootEl = Array.from(container.getElementsByTagName("svg"));
|
|
920
|
+
rootEl.length && (image = rootEl[0], image.setAttribute("overflow", "visible"));
|
|
921
|
+
}
|
|
882
922
|
}
|
|
883
|
-
image.setAttribute("x", numToAttr(dx)), image.setAttribute("y", numToAttr(
|
|
884
|
-
image.setAttribute("width", `${numToAttr(
|
|
923
|
+
image.setAttribute("x", numToAttr(dx)), image.setAttribute("y", numToAttr(dy)),
|
|
924
|
+
image.setAttribute("width", `${numToAttr(dw)}px`), image.setAttribute("height", `${numToAttr(dh)}px`),
|
|
885
925
|
this._element.appendChild(image);
|
|
886
926
|
}
|
|
887
|
-
createColor({options, color, additionalRotation
|
|
888
|
-
|
|
927
|
+
createColor({options, color, additionalRotation, x, y, height, width, name}) {
|
|
928
|
+
let gradientSize = width > height ? width : height;
|
|
889
929
|
x -= this.options.dotsOptions.size, y -= this.options.dotsOptions.size, width += 2 * this.options.dotsOptions.size,
|
|
890
930
|
height += 2 * this.options.dotsOptions.size;
|
|
891
931
|
let rect = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
|
@@ -897,35 +937,38 @@ class QRSVG {
|
|
|
897
937
|
gradient.setAttribute("id", name), gradient.setAttribute("gradientUnits", "userSpaceOnUse"),
|
|
898
938
|
gradient.setAttribute("fx", numToAttr(x + width / 2)), gradient.setAttribute("fy", numToAttr(y + height / 2)),
|
|
899
939
|
gradient.setAttribute("cx", numToAttr(x + width / 2)), gradient.setAttribute("cy", numToAttr(y + height / 2)),
|
|
900
|
-
gradient.setAttribute("r", numToAttr(
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
gradientSize_x0 += width / 2 / Math.tan(color), y -= height / 2, x -= width / 2 / Math.tan(color)),
|
|
940
|
+
gradient.setAttribute("r", numToAttr(gradientSize / 2)); else {
|
|
941
|
+
let rotation = ((options.rotation || 0) + additionalRotation) % (2 * Math.PI), positiveRotation = (rotation + 2 * Math.PI) % (2 * Math.PI), x0 = x + width / 2, y0 = y + height / 2, x1 = x + width / 2, y1 = y + height / 2;
|
|
942
|
+
positiveRotation >= 0 && positiveRotation <= .25 * Math.PI || positiveRotation > 1.75 * Math.PI && positiveRotation <= 2 * Math.PI ? (x0 -= width / 2,
|
|
943
|
+
y0 -= height / 2 * Math.tan(rotation), x1 += width / 2, y1 += height / 2 * Math.tan(rotation)) : positiveRotation > .25 * Math.PI && positiveRotation <= .75 * Math.PI ? (y0 -= height / 2,
|
|
944
|
+
x0 -= width / 2 / Math.tan(rotation), y1 += height / 2, x1 += width / 2 / Math.tan(rotation)) : positiveRotation > .75 * Math.PI && positiveRotation <= 1.25 * Math.PI ? (x0 += width / 2,
|
|
945
|
+
y0 += height / 2 * Math.tan(rotation), x1 -= width / 2, y1 -= height / 2 * Math.tan(rotation)) : positiveRotation > 1.25 * Math.PI && positiveRotation <= 1.75 * Math.PI && (y0 += height / 2,
|
|
946
|
+
x0 += width / 2 / Math.tan(rotation), y1 -= height / 2, x1 -= width / 2 / Math.tan(rotation)),
|
|
908
947
|
gradient = this.document.createElementNS("http://www.w3.org/2000/svg", "linearGradient"),
|
|
909
948
|
gradient.setAttribute("id", name), gradient.setAttribute("gradientUnits", "userSpaceOnUse"),
|
|
910
|
-
gradient.setAttribute("x1", numToAttr(
|
|
911
|
-
gradient.setAttribute("x2", numToAttr(
|
|
949
|
+
gradient.setAttribute("x1", numToAttr(x0)), gradient.setAttribute("y1", numToAttr(y0)),
|
|
950
|
+
gradient.setAttribute("x2", numToAttr(x1)), gradient.setAttribute("y2", numToAttr(y1));
|
|
912
951
|
}
|
|
913
|
-
options.colorStops.forEach(
|
|
952
|
+
options.colorStops.forEach(stopCfg => {
|
|
914
953
|
let stop = this.document.createElementNS("http://www.w3.org/2000/svg", "stop");
|
|
915
|
-
stop.setAttribute("offset", `${numToAttr(100 *
|
|
916
|
-
|
|
954
|
+
stop.setAttribute("offset", `${numToAttr(100 * stopCfg.offset)}%`);
|
|
955
|
+
let parsed = parseColor(stopCfg.color);
|
|
956
|
+
stop.setAttribute("stop-color", parsed.value), parsed.alpha < 1 && stop.setAttribute("stop-opacity", parsed.alpha.toFixed(7)),
|
|
917
957
|
gradient.appendChild(stop);
|
|
918
958
|
}), rect.setAttribute("fill", `url(#${name})`), this.defs.appendChild(gradient);
|
|
919
|
-
} else
|
|
920
|
-
|
|
959
|
+
} else if (color) {
|
|
960
|
+
let parsed = parseColor(color);
|
|
961
|
+
rect.setAttribute("fill", parsed.value), parsed.alpha < 1 && rect.setAttribute("opacity", parsed.alpha.toFixed(7));
|
|
962
|
+
}
|
|
921
963
|
this._element.appendChild(rect);
|
|
922
964
|
}
|
|
923
|
-
createMask(
|
|
965
|
+
createMask(id) {
|
|
924
966
|
let options = this.options, mask = this.document.createElementNS("http://www.w3.org/2000/svg", "mask");
|
|
925
|
-
|
|
926
|
-
mask.setAttribute("
|
|
927
|
-
mask.setAttribute("height", numToAttr(options.height))
|
|
928
|
-
|
|
967
|
+
mask.setAttribute("id", id), mask.setAttribute("maskUnits", "userSpaceOnUse"), mask.setAttribute("x", "0"),
|
|
968
|
+
mask.setAttribute("y", "0"), mask.setAttribute("width", numToAttr(options.width)),
|
|
969
|
+
mask.setAttribute("height", numToAttr(options.height));
|
|
970
|
+
let group = this.document.createElementNS("http://www.w3.org/2000/svg", "g");
|
|
971
|
+
return group.setAttribute("fill", "#fff"), mask.appendChild(group), [ mask, group ];
|
|
929
972
|
}
|
|
930
973
|
}
|
|
931
974
|
|
|
@@ -948,11 +991,12 @@ let QRCodeStyling$1 = class {
|
|
|
948
991
|
this.options = options ? sanitizeOptions(mergeDeep(defaultOptions, options)) : defaultOptions,
|
|
949
992
|
this.update();
|
|
950
993
|
}
|
|
951
|
-
update(
|
|
952
|
-
this.container && (this.container.innerHTML = ""), this.options =
|
|
953
|
-
this.options.data
|
|
954
|
-
|
|
955
|
-
|
|
994
|
+
update(options) {
|
|
995
|
+
if (this.container && (this.container.innerHTML = ""), this.options = options ? sanitizeOptions(mergeDeep(this.options, options)) : this.options,
|
|
996
|
+
!this.options.data) return;
|
|
997
|
+
this.options.stringToBytesFuncs && (Object.assign(QRCodeMinimal.stringToBytesFuncs, this.options.stringToBytesFuncs),
|
|
998
|
+
delete this.options.stringToBytesFuncs), this.qr = new QRCodeMinimal(this.options.qrOptions.typeNumber, this.options.qrOptions.errorCorrectionLevel);
|
|
999
|
+
let mode = this.options.qrOptions.mode || function(data) {
|
|
956
1000
|
switch (!0) {
|
|
957
1001
|
case /^[0-9]*$/.test(data):
|
|
958
1002
|
return Mode.numeric;
|
|
@@ -966,81 +1010,100 @@ let QRCodeStyling$1 = class {
|
|
|
966
1010
|
default:
|
|
967
1011
|
return Mode.byte;
|
|
968
1012
|
}
|
|
969
|
-
}(this.options.data)
|
|
970
|
-
this.setupSvg(), this.append(this.container)
|
|
1013
|
+
}(this.options.data);
|
|
1014
|
+
this.qr.addData(this.options.data, mode), this.qr.make(), this.setupSvg(), this.append(this.container);
|
|
971
1015
|
}
|
|
972
1016
|
append(container) {
|
|
973
1017
|
container && (this.qrSVG?.element && container.appendChild(this.qrSVG.element),
|
|
974
1018
|
this.container = container);
|
|
975
1019
|
}
|
|
976
1020
|
applyExtension(extension) {
|
|
977
|
-
if (!extension) throw Error("Extension function should be defined.");
|
|
1021
|
+
if (!extension) throw new Error("Extension function should be defined.");
|
|
978
1022
|
this.extension = extension, this.update();
|
|
979
1023
|
}
|
|
980
1024
|
deleteExtension() {
|
|
981
1025
|
this.extension = void 0, this.update();
|
|
982
1026
|
}
|
|
983
1027
|
async serialize() {
|
|
984
|
-
if (!this.qr) throw Error("QR code is empty");
|
|
1028
|
+
if (!this.qr) throw new Error("QR code is empty");
|
|
985
1029
|
if (this.qrSVG?.element && this.svgDrawingPromise || this.setupSvg(), await this.svgDrawingPromise,
|
|
986
|
-
this.qrSVG?.element) return
|
|
1030
|
+
!this.qrSVG?.element) return;
|
|
1031
|
+
let source = (new XMLSerializer).serializeToString(this.qrSVG.element);
|
|
1032
|
+
return source = '<?xml version="1.0" standalone="no"?>\r\n' + source, source;
|
|
987
1033
|
}
|
|
988
1034
|
setupSvg() {
|
|
989
|
-
if (this.qr)
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1035
|
+
if (!this.qr) return;
|
|
1036
|
+
let moduleCount = this.qr.getModuleCount();
|
|
1037
|
+
this.options.imageOptions.mode == ImageMode.background && this.options.shape != ShapeType.circle && (moduleCount += 2);
|
|
1038
|
+
let count = Math.ceil((this.options.shape == ShapeType.circle ? Math.sqrt(2) : 1) * moduleCount);
|
|
1039
|
+
count % 2 == 0 && (count -= 1);
|
|
1040
|
+
let margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0;
|
|
1041
|
+
this.options.imageOptions.mode == ImageMode.background && (margin += this.options.imageOptions.margin || 0);
|
|
1042
|
+
let size = Math.ceil(this.options.dotsOptions.size * (count + 2 * margin));
|
|
1043
|
+
this.qrSVG = new QRSVG({
|
|
1044
|
+
...this.options,
|
|
1045
|
+
width: size,
|
|
1046
|
+
height: size,
|
|
1047
|
+
errorCorrectionPercent: ErrorCorrectionPercents[this.options.qrOptions.errorCorrectionLevel]
|
|
1048
|
+
}), this.svgDrawingPromise = this.qrSVG.drawQR(this.qr).then(() => {
|
|
1049
|
+
this.qrSVG?.element && (this.options.plugins?.forEach(plugin => plugin.postProcess?.(this.qrSVG.element, {
|
|
996
1050
|
...this.options,
|
|
997
|
-
width:
|
|
998
|
-
height:
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1051
|
+
width: size,
|
|
1052
|
+
height: size
|
|
1053
|
+
})), this.extension?.(this.qrSVG.element, {
|
|
1054
|
+
...this.options,
|
|
1055
|
+
width: size,
|
|
1056
|
+
height: size
|
|
1057
|
+
}));
|
|
1058
|
+
});
|
|
1004
1059
|
}
|
|
1005
1060
|
};
|
|
1006
1061
|
|
|
1007
1062
|
var FileExtension;
|
|
1008
1063
|
|
|
1009
|
-
|
|
1010
|
-
|
|
1064
|
+
let browserUtils;
|
|
1065
|
+
|
|
1066
|
+
!function(FileExtension) {
|
|
1067
|
+
FileExtension.svg = "svg", FileExtension.png = "png", FileExtension.jpeg = "jpeg",
|
|
1068
|
+
FileExtension.webp = "webp";
|
|
1069
|
+
}(FileExtension || (FileExtension = {}));
|
|
1011
1070
|
|
|
1012
1071
|
class QRCodeStyling extends QRCodeStyling$1 {
|
|
1013
1072
|
constructor(options) {
|
|
1014
|
-
let dom = (new DOMImplementation).createDocument(null, ""), imageCache = new Map, loadImage = async
|
|
1015
|
-
if ("string" == typeof
|
|
1016
|
-
let pr = imageCache.get(
|
|
1017
|
-
return pr || (pr = fetch(
|
|
1073
|
+
let dom = (new DOMImplementation).createDocument(null, ""), imageCache = new Map, loadImage = async url => {
|
|
1074
|
+
if ("string" == typeof url) {
|
|
1075
|
+
let pr = imageCache.get(url);
|
|
1076
|
+
return pr || (pr = fetch(url).then(res => res.arrayBuffer().then(buff => Buffer.from(buff)).then(async data => ({
|
|
1018
1077
|
contentType: res.headers.get("Content-Type") || await fileTypeFromBuffer(data).then(r => r?.mime),
|
|
1019
1078
|
data
|
|
1020
|
-
}))), imageCache.set(
|
|
1079
|
+
}))), imageCache.set(url, pr), pr);
|
|
1080
|
+
}
|
|
1081
|
+
{
|
|
1082
|
+
const buff = Buffer.from(url);
|
|
1083
|
+
return {
|
|
1084
|
+
contentType: await fileTypeFromBuffer(buff).then(r => r?.mime),
|
|
1085
|
+
data: buff
|
|
1086
|
+
};
|
|
1021
1087
|
}
|
|
1022
|
-
return buff = Buffer.from(buff), {
|
|
1023
|
-
contentType: await fileTypeFromBuffer(buff).then(r => r?.mime),
|
|
1024
|
-
data: buff
|
|
1025
|
-
};
|
|
1026
1088
|
};
|
|
1027
1089
|
global.XMLSerializer = XMLSerializer$1, global.DOMParser = DOMParser$1, super({
|
|
1028
1090
|
...options,
|
|
1029
1091
|
document: options.document || dom,
|
|
1030
1092
|
imageTools: options.imageTools || {
|
|
1031
1093
|
toDataURL: url => "string" == typeof url && url.startsWith("data:") ? Promise.resolve(url) : loadImage(url).then(({contentType, data}) => `data:${contentType?.replace("application/xml", "image/svg+xml")};base64,${data.toString("base64")}`),
|
|
1032
|
-
getSize: async
|
|
1033
|
-
data
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1094
|
+
getSize: async src => {
|
|
1095
|
+
let {data} = Buffer.isBuffer(options.image) ? {
|
|
1096
|
+
data: options.image
|
|
1097
|
+
} : await loadImage(src), meta = await sharp(data).metadata();
|
|
1098
|
+
return {
|
|
1099
|
+
width: meta.width,
|
|
1100
|
+
height: meta.height
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1038
1103
|
}
|
|
1039
1104
|
});
|
|
1040
1105
|
}
|
|
1041
1106
|
}
|
|
1042
1107
|
|
|
1043
|
-
var browserUtils = void 0;
|
|
1044
|
-
|
|
1045
1108
|
export { CornerDotType, CornerSquareType, DotType, ErrorCorrectionPercents, FileExtension, GradientType, ImageMode, QRCodeStyling, ShapeType, browserUtils };
|
|
1046
1109
|
//# sourceMappingURL=qr-code-styling-node.js.map
|