@liquid-js/qr-code-styling
Version:
Generate styled QR codes on web or in Node
972 lines (926 loc) • 69.6 kB
JavaScript
import { QRUtil } from "@liquid-js/qrcode-generator/lib/qrcode/QRUtil.js";
import { stringToBytes_UTF8 } from "@liquid-js/qrcode-generator/lib/text/stringToBytes_UTF8.js";
import { TypeNumber, ErrorCorrectionLevel, Mode, QRCodeMinimal } from "@liquid-js/qrcode-generator/lib/qrcode/QRCodeMinimal.js";
import sharp from "sharp";
import { fileTypeFromBuffer } from "file-type";
import { DOMImplementation, XMLSerializer as XMLSerializer$1, DOMParser as DOMParser$1 } from "@xmldom/xmldom";
export { ErrorCorrectionLevel, Mode, TypeNumber } from "@liquid-js/qrcode-generator/lib/qrcode/QRCodeMinimal.js";
let isObject = obj => !!obj && "object" == typeof obj && !Array.isArray(obj);
function mergeDeep(target, ...sources) {
if (!sources.length) return target;
let source = sources.shift();
return void 0 !== source && isObject(target) && isObject(source) ? (target = {
...target
}, Object.keys(source).forEach((key => {
let targetValue = target[key], sourceValue = source[key];
Array.isArray(targetValue) && Array.isArray(sourceValue) ? target[key] = sourceValue : isObject(targetValue) && isObject(sourceValue) ? target[key] = mergeDeep({
...targetValue
}, sourceValue) : target[key] = sourceValue;
})), mergeDeep(target, ...sources)) : target;
}
var GradientType, DotType, CornerDotType, CornerSquareType, ShapeType, ImageMode;
function sanitizeGradient(gradient_newGradient) {
if (!(gradient_newGradient = {
...gradient_newGradient
}).colorStops || !gradient_newGradient.colorStops.length) throw Error("Field 'colorStops' is required in gradient");
return gradient_newGradient.rotation = gradient_newGradient.rotation ? Number(gradient_newGradient.rotation) : 0,
gradient_newGradient.colorStops = gradient_newGradient.colorStops.map((colorStop => ({
...colorStop,
offset: Number(colorStop.offset)
}))), gradient_newGradient;
}
(GradientType = GradientType || (GradientType = {})).radial = "radial", GradientType.linear = "linear",
(DotType = DotType || (DotType = {})).dot = "dot", DotType.randomDot = "random-dot",
DotType.rounded = "rounded", DotType.extraRounded = "extra-rounded", DotType.verticalLine = "vertical-line",
DotType.horizontalLine = "horizontal-line", DotType.classy = "classy", DotType.classyRounded = "classy-rounded",
DotType.square = "square", DotType.smallSquare = "small-square", DotType.tinySquare = "tiny-square",
DotType.diamond = "diamond", (CornerDotType = CornerDotType || (CornerDotType = {})).dot = "dot",
CornerDotType.square = "square", CornerDotType.heart = "heart", CornerDotType.extraRounded = "extra-rounded",
CornerDotType.classy = "classy", CornerDotType.outpoint = "outpoint", CornerDotType.inpoint = "inpoint",
(CornerSquareType = CornerSquareType || (CornerSquareType = {})).dot = "dot", CornerSquareType.square = "square",
CornerSquareType.extraRounded = "extra-rounded", CornerSquareType.classy = "classy",
CornerSquareType.outpoint = "outpoint", CornerSquareType.inpoint = "inpoint", (ShapeType = ShapeType || (ShapeType = {})).square = "square",
ShapeType.circle = "circle", (ImageMode = ImageMode || (ImageMode = {})).center = "center",
ImageMode.overlay = "overlay", ImageMode.background = "background";
let defaultOptions = {
document: void 0,
shape: ShapeType.square,
width: void 0,
height: void 0,
data: "",
qrOptions: {
typeNumber: TypeNumber[0],
mode: void 0,
errorCorrectionLevel: ErrorCorrectionLevel.Q
},
imageOptions: {
mode: ImageMode.center,
imageSize: .4,
crossOrigin: void 0,
margin: 0,
fill: {
color: "rgba(255,255,255,1)"
}
},
dotsOptions: {
type: DotType.square,
color: "#000",
size: 10
}
};
function sanitizeOptions(newOptions_options) {
return (newOptions_options = {
...newOptions_options
}).imageOptions = {
...newOptions_options.imageOptions,
imageSize: Math.min(1, Number(newOptions_options.imageOptions.imageSize)) || 1,
margin: Number(newOptions_options.imageOptions.margin),
fill: {
...newOptions_options.imageOptions.fill
}
}, newOptions_options.imageOptions.mode == ImageMode.overlay && (newOptions_options.imageOptions.margin = 0),
newOptions_options.imageOptions.fill.gradient && (newOptions_options.imageOptions.fill.gradient = sanitizeGradient(newOptions_options.imageOptions.fill.gradient)),
newOptions_options.dotsOptions = {
...newOptions_options.dotsOptions
}, newOptions_options.dotsOptions.gradient && (newOptions_options.dotsOptions.gradient = sanitizeGradient(newOptions_options.dotsOptions.gradient)),
newOptions_options.dotsOptions.size = Math.round(Math.max(0, newOptions_options.dotsOptions.size) || 10),
newOptions_options.cornersSquareOptions && (newOptions_options.cornersSquareOptions = {
...newOptions_options.cornersSquareOptions
}, newOptions_options.cornersSquareOptions.gradient && (newOptions_options.cornersSquareOptions.gradient = sanitizeGradient(newOptions_options.cornersSquareOptions.gradient))),
newOptions_options.cornersDotOptions && (newOptions_options.cornersDotOptions = {
...newOptions_options.cornersDotOptions
}, newOptions_options.cornersDotOptions.gradient && (newOptions_options.cornersDotOptions.gradient = sanitizeGradient(newOptions_options.cornersDotOptions.gradient))),
newOptions_options.backgroundOptions && (newOptions_options.backgroundOptions = {
...newOptions_options.backgroundOptions
}, newOptions_options.backgroundOptions.gradient && (newOptions_options.backgroundOptions.gradient = sanitizeGradient(newOptions_options.backgroundOptions.gradient))),
newOptions_options.document || (newOptions_options.document = document), newOptions_options;
}
let ErrorCorrectionPercents = {
[ErrorCorrectionLevel.L]: .07,
[ErrorCorrectionLevel.M]: .15,
[ErrorCorrectionLevel.Q]: .25,
[ErrorCorrectionLevel.H]: .3
};
let rx = /\.?0+$/;
function numToAttr(value) {
return value.toFixed(7).replace(rx, "");
}
function svgPath(strings, ...values) {
return strings.reduce(((t, v, i) => {
let p = "";
return i && (p = values[i - 1]), "number" == typeof p && (p = numToAttr(p)), `${t}${p}${v}`;
}), "").trim().replace(/[\s\n\r]+/gim, " ");
}
class QRCornerDot {
get element() {
return this._element;
}
constructor(type, document) {
this.type = type, this.document = document;
}
draw(args) {
let drawFunction;
switch (this.type) {
case CornerDotType.square:
drawFunction = this.drawSquare;
break;
case CornerDotType.heart:
drawFunction = this.drawHeart;
break;
case CornerDotType.extraRounded:
drawFunction = this.drawRounded;
break;
case CornerDotType.classy:
drawFunction = this.drawClassy;
break;
case CornerDotType.inpoint:
drawFunction = this.drawInpoint;
break;
case CornerDotType.outpoint:
drawFunction = this.drawOutpoint;
break;
default:
drawFunction = this.drawDot;
}
drawFunction.call(this, args);
}
rotateFigure({x: cx, y: cy, size, rotation = 0, draw}) {
cx += size / 2, cy += size / 2, draw(), this._element?.setAttribute("transform", `rotate(${numToAttr(180 * rotation / Math.PI)},${cx},${cy})`);
}
basicDot(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "circle"),
this._element.setAttribute("cx", numToAttr(x + size / 2)), this._element.setAttribute("cy", numToAttr(y + size / 2)),
this._element.setAttribute("r", numToAttr(size / 2));
}
});
}
basicSquare(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect"),
this._element.setAttribute("x", numToAttr(x)), this._element.setAttribute("y", numToAttr(y)),
this._element.setAttribute("width", numToAttr(size)), this._element.setAttribute("height", numToAttr(size));
}
});
}
basicHeart(args) {
let {size, x, y} = args;
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path");
let move = !1, i = 0;
this._element.setAttribute("d", [ "M", 1, .3262506, "c", 0, .0383376, -.0064626, .0758377, -.0193751, .1125001, "s", -.0356247, .076875, -.0681248, .1206252, "c", -.0325, .0437499, -.0762503, .0931247, -.1312501, .1481249, "C", .7262502, .7625008, .6566626, .8279132, .5724999, .9037505, "L", .5, .9687506, "L", .4275001, .9037505, "C", .3433374, .8279132, .2737499, .7625005, .21875, .7075007, "C", .1637501, .6525008, .1199999, .6031258, .0874999, .5593758, "S", .0322876, .4754133, .0193751, .4387506, "S", 0, .3645881, 0, .3262506, "c", 0, -.0783374, .0262499, -.1437498, .07875, -.1962499, "s", .1179124, -.07875, .1962499, -.07875, "c", .0433376, 0, .0845875, .0091625, .12375, .0274999, "S", .4716623, .1229131, .5, .1562506, "c", .0283374, -.0333375, .0620874, -.0591625, .1012502, -.0775, "c", .0391627, -.0183375, .0804126, -.0274999, .12375, -.0274999, "c", .0783374, 0, .1437497, .0262499, .1962501, .07875, "S", 1, .2479131, 1, .3262506, "z" ].map((v => "string" == typeof v ? (i = 0,
move = v.toUpperCase() == v, v) : (i++, v *= size, move && (v += 1 == i % 2 ? x : y),
numToAttr(v)))).join(" "));
}
basicRounded(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect"),
this._element.setAttribute("x", numToAttr(x)), this._element.setAttribute("y", numToAttr(y)),
this._element.setAttribute("width", numToAttr(size)), this._element.setAttribute("height", numToAttr(size)),
this._element.setAttribute("rx", numToAttr(size / 4)), this._element.setAttribute("ry", numToAttr(size / 4));
}
});
}
basicClassy(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`);
}
});
}
basicInpoint(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`);
}
});
}
drawDot({x, y, size, rotation}) {
this.basicDot({
x,
y,
size,
rotation
});
}
drawSquare({x, y, size, rotation}) {
this.basicSquare({
x,
y,
size,
rotation
});
}
drawHeart({x, y, size, rotation}) {
this.basicHeart({
x,
y,
size,
rotation
});
}
drawRounded({x, y, size, rotation}) {
this.basicRounded({
x,
y,
size,
rotation
});
}
drawClassy({x, y, size, rotation}) {
this.basicClassy({
x,
y,
size,
rotation
});
}
drawInpoint({x, y, size, rotation}) {
this.basicInpoint({
x,
y,
size,
rotation
});
}
drawOutpoint({x, y, size, rotation}) {
this.basicInpoint({
x,
y,
size,
rotation: (rotation || 0) + Math.PI
});
}
}
class QRCornerSquare {
get element() {
return this._element;
}
get fill() {
return this._fill;
}
constructor(type, document) {
this.type = type, this.document = document;
}
draw(args) {
let drawFunction;
switch (this.type) {
case CornerSquareType.square:
drawFunction = this.drawSquare;
break;
case CornerSquareType.extraRounded:
drawFunction = this.drawExtraRounded;
break;
case CornerSquareType.classy:
drawFunction = this.drawClassy;
break;
case CornerSquareType.outpoint:
drawFunction = this.drawOutpoint;
break;
case CornerSquareType.inpoint:
drawFunction = this.drawInpoint;
break;
default:
drawFunction = this.drawDot;
}
drawFunction.call(this, args);
}
rotateFigure({x: cx, y: cy, size, rotation = 0, draw}) {
cx += size / 2, cy += size / 2, draw(), this._element?.setAttribute("transform", `rotate(${numToAttr(180 * rotation / Math.PI)},${cx},${cy})`),
this._fill?.setAttribute("transform", `rotate(${numToAttr(180 * rotation / Math.PI)},${cx},${cy})`);
}
basicDot(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`),
this._fill = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._fill.setAttribute("clip-rule", "evenodd"), this._fill.setAttribute("d", svgPath`M ${x + size / 2} ${y - dotSize} a ${size / 2 + dotSize} ${size / 2 + dotSize} 0 1 0 0.1 0 z`);
}
});
}
basicSquare(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`),
this._fill = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._fill.setAttribute("clip-rule", "evenodd"), this._fill.setAttribute("d", svgPath`M ${x - dotSize} ${y - dotSize} h ${size + 2 * dotSize} v ${size + 2 * dotSize} h ${-size - 2 * dotSize} z`);
}
});
}
basicExtraRounded(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`),
this._fill = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._fill.setAttribute("clip-rule", "evenodd"), this._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`);
}
});
}
basicClassy(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`),
this._fill = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._fill.setAttribute("clip-rule", "evenodd"), this._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`);
}
});
}
basicInpoint(args) {
let {size, x, y} = args, dotSize = size / 7;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("clip-rule", "evenodd"), this._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`),
this._fill = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._fill.setAttribute("clip-rule", "evenodd"), this._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`);
}
});
}
drawDot({x, y, size, rotation}) {
this.basicDot({
x,
y,
size,
rotation
});
}
drawSquare({x, y, size, rotation}) {
this.basicSquare({
x,
y,
size,
rotation
});
}
drawExtraRounded({x, y, size, rotation}) {
this.basicExtraRounded({
x,
y,
size,
rotation
});
}
drawClassy({x, y, size, rotation}) {
this.basicClassy({
x,
y,
size,
rotation
});
}
drawInpoint({x, y, size, rotation}) {
this.basicInpoint({
x,
y,
size,
rotation
});
}
drawOutpoint({x, y, size, rotation}) {
this.basicInpoint({
x,
y,
size,
rotation: (rotation || 0) + Math.PI
});
}
}
class QRDot {
get element() {
return this._element;
}
constructor(type, document) {
this.type = type, this.document = document;
}
draw(args) {
let drawFunction;
switch (this.type) {
case DotType.dot:
drawFunction = this.drawDot;
break;
case DotType.randomDot:
drawFunction = this.drawRandomDot;
break;
case DotType.classy:
drawFunction = this.drawClassy;
break;
case DotType.classyRounded:
drawFunction = this.drawClassyRounded;
break;
case DotType.rounded:
drawFunction = this.drawRounded;
break;
case DotType.verticalLine:
drawFunction = this.drawVerticalLine;
break;
case DotType.horizontalLine:
drawFunction = this.drawHorizontalLine;
break;
case DotType.extraRounded:
drawFunction = this.drawExtraRounded;
break;
case DotType.diamond:
drawFunction = this.drawDiamond;
break;
case DotType.smallSquare:
drawFunction = this.drawSmallSquare;
break;
case DotType.tinySquare:
drawFunction = this.drawTinySquare;
break;
default:
drawFunction = this.drawSquare;
}
drawFunction.call(this, args);
}
rotateFigure({x: cx, y: cy, size, rotation = 0, draw}) {
cx += size / 2, cy += size / 2, draw(), this._element?.setAttribute("transform", `rotate(${numToAttr(180 * rotation / Math.PI)},${cx},${cy})`);
}
basicDot(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "circle"),
this._element.setAttribute("cx", numToAttr(x + size / 2)), this._element.setAttribute("cy", numToAttr(y + size / 2)),
this._element.setAttribute("r", numToAttr(size / 2));
}
});
}
basicSquare(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect"),
this._element.setAttribute("x", numToAttr(x)), this._element.setAttribute("y", numToAttr(y)),
this._element.setAttribute("width", numToAttr(size)), this._element.setAttribute("height", numToAttr(size));
}
});
}
basicSideRounded(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size / 2} a ${size / 2} ${size / 2}, 0, 0, 0, 0 ${-size} z`);
}
});
}
basicCornerRounded(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._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`);
}
});
}
basicCornerExtraRounded(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._element.setAttribute("d", svgPath`M ${x} ${y} v ${size} h ${size} a ${size} ${size}, 0, 0, 0, ${-size} ${-size} z`);
}
});
}
basicCornersRounded(args) {
let {size, x, y} = args;
this.rotateFigure({
...args,
draw: () => {
this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "path"),
this._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`);
}
});
}
drawDot({x, y, size}) {
this.basicDot({
x,
y,
size,
rotation: 0
});
}
drawRandomDot({x, y, size}) {
this.basicDot({
x,
y,
size: size * (.25 * Math.random() + .75),
rotation: 0
});
}
drawSquare({x, y, size}) {
this.basicSquare({
x,
y,
size,
rotation: 0
});
}
drawSmallSquare({x, y, size}) {
let originalSize = size;
size = .7 * originalSize, x += .15 * originalSize, y += .15 * originalSize, this.basicSquare({
x,
y,
size,
rotation: 0
});
}
drawTinySquare({x, y, size}) {
let originalSize = size;
size = .3 * originalSize, x += .35 * originalSize, y += .35 * originalSize, this.basicSquare({
x,
y,
size,
rotation: 0
});
}
drawDiamond({x, y, size}) {
this.basicSquare({
x,
y,
size,
rotation: Math.PI / 4
});
}
drawRounded({x, y, size, getNeighbor: bottomNeighbor_getNeighbor}) {
var leftNeighbor_rotation = bottomNeighbor_getNeighbor ? +bottomNeighbor_getNeighbor(-1, 0) : 0;
let rightNeighbor = bottomNeighbor_getNeighbor ? +bottomNeighbor_getNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor_getNeighbor ? +bottomNeighbor_getNeighbor(0, -1) : 0;
var neighborsCount_rotation = leftNeighbor_rotation + rightNeighbor + topNeighbor + (bottomNeighbor_getNeighbor = bottomNeighbor_getNeighbor ? +bottomNeighbor_getNeighbor(0, 1) : 0);
0 === neighborsCount_rotation ? this.basicDot({
x,
y,
size,
rotation: 0
}) : 2 < neighborsCount_rotation || leftNeighbor_rotation && rightNeighbor || topNeighbor && bottomNeighbor_getNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : 2 === neighborsCount_rotation ? (neighborsCount_rotation = 0, leftNeighbor_rotation && topNeighbor ? neighborsCount_rotation = Math.PI / 2 : topNeighbor && rightNeighbor ? neighborsCount_rotation = Math.PI : rightNeighbor && bottomNeighbor_getNeighbor && (neighborsCount_rotation = -Math.PI / 2),
this.basicCornerRounded({
x,
y,
size,
rotation: neighborsCount_rotation
})) : 1 === neighborsCount_rotation && (leftNeighbor_rotation = 0, topNeighbor ? leftNeighbor_rotation = Math.PI / 2 : rightNeighbor ? leftNeighbor_rotation = Math.PI : bottomNeighbor_getNeighbor && (leftNeighbor_rotation = -Math.PI / 2),
this.basicSideRounded({
x,
y,
size,
rotation: leftNeighbor_rotation
}));
}
drawVerticalLine({x, y, size, getNeighbor: bottomNeighbor}) {
let leftNeighbor = bottomNeighbor ? +bottomNeighbor(-1, 0) : 0, rightNeighbor = bottomNeighbor ? +bottomNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor ? +bottomNeighbor(0, -1) : 0;
0 === leftNeighbor + rightNeighbor + topNeighbor + (bottomNeighbor = bottomNeighbor ? +bottomNeighbor(0, 1) : 0) || leftNeighbor && !topNeighbor && !bottomNeighbor || rightNeighbor && !topNeighbor && !bottomNeighbor ? this.basicDot({
x,
y,
size,
rotation: 0
}) : topNeighbor && bottomNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : topNeighbor && !bottomNeighbor ? this.basicSideRounded({
x,
y,
size,
rotation: Math.PI / 2
}) : bottomNeighbor && !topNeighbor && this.basicSideRounded({
x,
y,
size,
rotation: -Math.PI / 2
});
}
drawHorizontalLine({x, y, size, getNeighbor: bottomNeighbor}) {
let leftNeighbor = bottomNeighbor ? +bottomNeighbor(-1, 0) : 0, rightNeighbor = bottomNeighbor ? +bottomNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor ? +bottomNeighbor(0, -1) : 0;
0 === leftNeighbor + rightNeighbor + topNeighbor + (bottomNeighbor = bottomNeighbor ? +bottomNeighbor(0, 1) : 0) || topNeighbor && !leftNeighbor && !rightNeighbor || bottomNeighbor && !leftNeighbor && !rightNeighbor ? this.basicDot({
x,
y,
size,
rotation: 0
}) : leftNeighbor && rightNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : leftNeighbor && !rightNeighbor ? this.basicSideRounded({
x,
y,
size,
rotation: 0
}) : rightNeighbor && !leftNeighbor && this.basicSideRounded({
x,
y,
size,
rotation: Math.PI
});
}
drawExtraRounded({x, y, size, getNeighbor: bottomNeighbor}) {
var leftNeighbor = bottomNeighbor ? +bottomNeighbor(-1, 0) : 0;
let rightNeighbor = bottomNeighbor ? +bottomNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor ? +bottomNeighbor(0, -1) : 0;
var neighborsCount = leftNeighbor + rightNeighbor + topNeighbor + (bottomNeighbor = bottomNeighbor ? +bottomNeighbor(0, 1) : 0);
0 === neighborsCount ? this.basicDot({
x,
y,
size,
rotation: 0
}) : 2 < neighborsCount || leftNeighbor && rightNeighbor || topNeighbor && bottomNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : 2 === neighborsCount ? (neighborsCount = 0, leftNeighbor && topNeighbor ? neighborsCount = Math.PI / 2 : topNeighbor && rightNeighbor ? neighborsCount = Math.PI : rightNeighbor && bottomNeighbor && (neighborsCount = -Math.PI / 2),
this.basicCornerExtraRounded({
x,
y,
size,
rotation: neighborsCount
})) : 1 === neighborsCount && (leftNeighbor = 0, topNeighbor ? leftNeighbor = Math.PI / 2 : rightNeighbor ? leftNeighbor = Math.PI : bottomNeighbor && (leftNeighbor = -Math.PI / 2),
this.basicSideRounded({
x,
y,
size,
rotation: leftNeighbor
}));
}
drawClassy({x, y, size, getNeighbor: bottomNeighbor}) {
let leftNeighbor = bottomNeighbor ? +bottomNeighbor(-1, 0) : 0, rightNeighbor = bottomNeighbor ? +bottomNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor ? +bottomNeighbor(0, -1) : 0;
0 === leftNeighbor + rightNeighbor + topNeighbor + (bottomNeighbor = bottomNeighbor ? +bottomNeighbor(0, 1) : 0) ? this.basicCornersRounded({
x,
y,
size,
rotation: Math.PI / 2
}) : leftNeighbor || topNeighbor ? rightNeighbor || bottomNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : this.basicCornerRounded({
x,
y,
size,
rotation: Math.PI / 2
}) : this.basicCornerRounded({
x,
y,
size,
rotation: -Math.PI / 2
});
}
drawClassyRounded({x, y, size, getNeighbor: bottomNeighbor}) {
let leftNeighbor = bottomNeighbor ? +bottomNeighbor(-1, 0) : 0, rightNeighbor = bottomNeighbor ? +bottomNeighbor(1, 0) : 0, topNeighbor = bottomNeighbor ? +bottomNeighbor(0, -1) : 0;
0 === leftNeighbor + rightNeighbor + topNeighbor + (bottomNeighbor = bottomNeighbor ? +bottomNeighbor(0, 1) : 0) ? this.basicCornersRounded({
x,
y,
size,
rotation: Math.PI / 2
}) : leftNeighbor || topNeighbor ? rightNeighbor || bottomNeighbor ? this.basicSquare({
x,
y,
size,
rotation: 0
}) : this.basicCornerExtraRounded({
x,
y,
size,
rotation: Math.PI / 2
}) : this.basicCornerExtraRounded({
x,
y,
size,
rotation: -Math.PI / 2
});
}
}
let browserImageTools = {
toDataURL: url => "string" == typeof url && url.startsWith("data:") ? Promise.resolve(url) : new Promise(((resolve, reject) => {
if ("string" == typeof url) {
const xhr = new XMLHttpRequest;
xhr.onload = () => {
const reader = new FileReader;
reader.onloadend = () => {
resolve(reader.result);
}, reader.readAsDataURL(xhr.response);
}, xhr.onerror = xhr.onabort = xhr.ontimeout = reject, xhr.open("GET", url, !0),
xhr.responseType = "blob", xhr.send();
} else {
const reader = new FileReader;
reader.onloadend = () => {
resolve(reader.result);
}, reader.readAsDataURL(url);
}
})),
getSize: (src, crossOrigin) => new Promise(((resolve, reject) => {
const image = new Image;
"string" === crossOrigin && (image.crossOrigin = crossOrigin), image.onload = () => {
resolve({
width: image.width,
height: image.height
});
}, image.onerror = image.onabort = reject, "string" == typeof src ? image.src = src : browserImageTools.toDataURL(src).then((url => image.src = url)).catch(reject);
}))
};
function parseColor(base) {
var m_parts = [];
let alpha = 1;
if ("#" === (base = base.toLowerCase())[0]) {
let size = (base = base.slice(1)).length;
4 >= size ? (m_parts = [ parseInt(base[0] + base[0], 16), parseInt(base[1] + base[1], 16), parseInt(base[2] + base[2], 16) ],
4 === size && (alpha = parseInt(base[3] + base[3], 16) / 255)) : (m_parts = [ parseInt(base[0] + base[1], 16), parseInt(base[2] + base[3], 16), parseInt(base[4] + base[5], 16) ],
8 === size && (alpha = parseInt(base[6] + base[7], 16) / 255)), m_parts[0] || (m_parts[0] = 0),
m_parts[1] || (m_parts[1] = 0), m_parts[2] || (m_parts[2] = 0);
} else {
if (!(m_parts = /^((?:rgba?))\s*\(([^)]*)\)/.exec(base))) return {
value: base,
alpha
};
alpha = 3 < (m_parts = (m_parts = m_parts[2].trim().split(/\s*[,/]\s*|\s+/)).map(((v, i) => "%" === v[v.length - 1] ? (v = parseFloat(v) / 100,
3 === i ? v : 255 * v) : "none" === v ? 0 : parseFloat(v)))).length ? m_parts.pop() : 1;
}
return {
value: "#" + m_parts.map((v => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0"))).join(""),
alpha: Math.max(0, Math.min(1, alpha))
};
}
let squareMask = [ [ 1, 1, 1, 1, 1, 1, 1 ], [ 1, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0, 0, 1 ], [ 1, 1, 1, 1, 1, 1, 1 ] ], dotMask = [ [ 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 1, 1, 1, 0, 0 ], [ 0, 0, 1, 1, 1, 0, 0 ], [ 0, 0, 1, 1, 1, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0, 0 ] ];
class QRSVG {
get element() {
return this._element;
}
constructor(options) {
this.options = options, this.document = options.document, this._element = this.document.createElementNS("http://www.w3.org/2000/svg", "svg");
let width = numToAttr(options.width), height = numToAttr(options.height);
this._element.setAttribute("width", width), this._element.setAttribute("height", height),
this._element.setAttribute("viewBox", `0 0 ${width} ${height}`), this.defs = this.document.createElementNS("http://www.w3.org/2000/svg", "defs"),
this._element.appendChild(this.defs), this.imageTools = options.imageTools || browserImageTools;
}
get width() {
return this.options.width;
}
get height() {
return this.options.height;
}
async drawQR(qr_size) {
let count = qr_size.getModuleCount();
var alignment_maxWidth_typeNumber = parseInt(((count - 17) / 4).toFixed(0), 10);
let dotSize = this.options.dotsOptions.size, drawImageSize = {
hideXDots: 0,
hideYDots: 0,
width: 0,
height: 0
};
if (this.qr = qr_size, this.options.image) {
qr_size = await this.imageTools.getSize(this.options.image, this.options.imageOptions.crossOrigin);
let {imageOptions, errorCorrectionPercent} = this.options;
if (imageOptions.mode == ImageMode.background) {
var coverLevel_margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0;
alignment_maxWidth_typeNumber = (this.options.width - 2 * coverLevel_margin * dotSize) * imageOptions.imageSize,
coverLevel_margin = (this.options.height - 2 * coverLevel_margin * dotSize) * imageOptions.imageSize;
let {width, height} = qr_size;
height = height / width * alignment_maxWidth_typeNumber, width = alignment_maxWidth_typeNumber,
height > coverLevel_margin && (width = width / height * coverLevel_margin, height = coverLevel_margin),
drawImageSize = {
hideXDots: 0,
hideYDots: 0,
width,
height
};
} else coverLevel_margin = imageOptions.imageSize * errorCorrectionPercent, alignment_maxWidth_typeNumber = QRUtil.getPatternPosition(alignment_maxWidth_typeNumber),
drawImageSize = function({originalHeight, originalWidth, maxHiddenDots: JSCompiler_object_inline_x_16_hideMax_maxHiddenDots, maxHiddenAxisDots: JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper, dotSize, margin}) {
if (0 >= originalHeight || 0 >= originalWidth || 0 >= JSCompiler_object_inline_x_16_hideMax_maxHiddenDots || 0 >= dotSize || 4 * margin ** 2 > JSCompiler_object_inline_x_16_hideMax_maxHiddenDots) return {
height: 0,
width: 0,
hideYDots: 0,
hideXDots: 0
};
JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper && 0 == JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper % 2 && (JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = Math.max(1, JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper - 1));
var JSCompiler_object_inline_x_14_dimMax = Math.max(originalWidth, originalHeight), JSCompiler_object_inline_y_15_dimMin_hideMin = Math.min(originalWidth, originalHeight), lower_maxH_size = 0;
JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = (JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper || JSCompiler_object_inline_x_16_hideMax_maxHiddenDots) - 2 * margin;
do {
let newSize = lower_maxH_size + (JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper - lower_maxH_size) / 2, dotsMax = Math.max(1, Math.ceil(newSize + 2 * margin));
0 == dotsMax % 2 && dotsMax++;
let dotsMin = Math.max(1, Math.ceil(newSize * JSCompiler_object_inline_y_15_dimMin_hideMin / JSCompiler_object_inline_x_14_dimMax + 2 * margin));
0 == dotsMin % 2 && dotsMin++, dotsMax * dotsMin > JSCompiler_object_inline_x_16_hideMax_maxHiddenDots ? JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = newSize : lower_maxH_size = newSize;
} while (.001 < Math.abs(lower_maxH_size - JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper));
return 0 == (JSCompiler_object_inline_x_16_hideMax_maxHiddenDots = Math.max(1, Math.ceil(lower_maxH_size + 2 * margin))) % 2 && JSCompiler_object_inline_x_16_hideMax_maxHiddenDots++,
0 == (JSCompiler_object_inline_y_15_dimMin_hideMin = Math.max(1, Math.ceil(lower_maxH_size * JSCompiler_object_inline_y_15_dimMin_hideMin / JSCompiler_object_inline_x_14_dimMax + 2 * margin))) % 2 && JSCompiler_object_inline_y_15_dimMin_hideMin++,
originalWidth > originalHeight ? JSCompiler_object_inline_x_14_dimMax = JSCompiler_object_inline_x_16_hideMax_maxHiddenDots : (JSCompiler_object_inline_x_14_dimMax = JSCompiler_object_inline_y_15_dimMin_hideMin,
JSCompiler_object_inline_y_15_dimMin_hideMin = JSCompiler_object_inline_x_16_hideMax_maxHiddenDots),
JSCompiler_object_inline_x_16_hideMax_maxHiddenDots = JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = (JSCompiler_object_inline_x_14_dimMax - 2 * margin) * dotSize,
(JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper * originalHeight / originalWidth) > (lower_maxH_size = (JSCompiler_object_inline_y_15_dimMin_hideMin - 2 * margin) * dotSize) && (JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper = lower_maxH_size,
JSCompiler_object_inline_x_16_hideMax_maxHiddenDots = lower_maxH_size * originalWidth / originalHeight),
{
height: Math.round(JSCompiler_object_inline_y_17_maxHiddenAxisDots_maxW_upper + 2 * margin * dotSize),
width: Math.round(JSCompiler_object_inline_x_16_hideMax_maxHiddenDots + 2 * margin * dotSize),
hideYDots: JSCompiler_object_inline_y_15_dimMin_hideMin,
hideXDots: JSCompiler_object_inline_x_14_dimMax
};
}({
originalWidth: qr_size.width,
originalHeight: qr_size.height,
maxHiddenDots: Math.floor(coverLevel_margin * (count * count - 192 - 2 * (count - 16) - 25 * alignment_maxWidth_typeNumber.length ** 2)),
maxHiddenAxisDots: count - 14,
dotSize,
margin: imageOptions.margin
});
}
this.drawBackground(), this.options.imageOptions.mode != ImageMode.overlay && this.options.image && 0 < drawImageSize.width && 0 < drawImageSize.height && await this.drawImage({
width: drawImageSize.width,
height: drawImageSize.height,
count,
dotSize
}), 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 || 8 > i && 8 > j || i >= count - 8 && 8 > j || j >= count - 8 && 8 > i))),
this.options.imageOptions.mode == ImageMode.overlay && this.options.image && 0 < drawImageSize.width && 0 < drawImageSize.height && await this.drawImage({
width: drawImageSize.width,
height: drawImageSize.height,
count,
dotSize
}), this.drawCorners();
}
drawBackground() {
let options = this.options;
if (this._element && options.backgroundOptions) {
this.createColor({
options: options.backgroundOptions.gradient,
color: options.backgroundOptions.color,
additionalRotation: 0,
x: 0,
y: 0,
height: options.height,
width: options.width,
name: "background-color"
});
let size = Math.min(options.width, options.height), element = this.document.createElementNS("http://www.w3.org/2000/svg", "rect");
[this.backgroundMask, this.backgroundMaskGroup] = this.createMask("mask-background-color"),
this.defs.appendChild(this.backgroundMask), element.setAttribute("x", numToAttr((options.width - size) / 2)),
element.setAttribute("y", numToAttr((options.height - size) / 2)), element.setAttribute("width", numToAttr(size)),
element.setAttribute("height", numToAttr(size)), element.setAttribute("rx", numToAttr(size / 2 * (options.backgroundOptions.round || 0))),
this.backgroundMaskGroup.appendChild(element);
}
}
drawDots(alignment) {
if (!this.qr) throw Error("QR code is not defined");
let options = this.options;
var count = this.qr.getModuleCount();
if (count > options.width || count > options.height) throw Error("The canvas is too small");
let dotSize = this.options.dotsOptions.size;
var minSize_xFakeBeginning = Math.min(options.width, options.height);
options.imageOptions.mode == ImageMode.background && (minSize_xFakeBeginning -= 2 * dotSize * (options.imageOptions.margin || 0));
var colorCount_xBeginning = Math.floor((options.width - count * dotSize) / 2), yBeginning_yFakeBeginning = Math.floor((options.height - count * dotSize) / 2);
let dot = new QRDot(options.dotsOptions.type, this.document), overlayDot = new QRDot(DotType.tinySquare, this.document), markerDot = new QRDot(DotType.square, this.document);
[this.dotsMask, this.dotsMaskGroup] = this.createMask("mask-dot-color"), this.defs.appendChild(this.dotsMask),
options.imageOptions.mode == ImageMode.background && ([this.lightDotsMask, this.lightDotsMaskGroup] = this.createMask("mask-light-dot-color"),
this.defs.appendChild(this.lightDotsMask));
var fakeCount_margin = 0;
let additionalDots = 0;
fakeCount_margin = count, options.shape === ShapeType.circle ? (fakeCount_margin = this.options.backgroundOptions && this.options.backgroundOptions.margin || 0,
additionalDots = Math.floor((minSize_xFakeBeginning / dotSize - count - 2 * fakeCount_margin) / 2),
fakeCount_margin = count + 2 * additionalDots) : options.imageOptions.mode == ImageMode.background && (additionalDots = 1,
fakeCount_margin = count + 2 * additionalDots), minSize_xFakeBeginning = colorCount_xBeginning - additionalDots * dotSize,
yBeginning_yFakeBeginning -= additionalDots * dotSize, colorCount_xBeginning = count + 2 * additionalDots;
let fakeMatrix = Array(fakeCount_margin);
var center_jAlign = Math.floor(fakeCount_margin / 2);
for (let i = 0; i < fakeCount_margin; i++) {
fakeMatrix[i] = Array(fakeCount_margin);
for (let j = 0; j < fakeCount_margin; j++) if (i > additionalDots - 1 && i < fakeCount_margin - additionalDots && j > additionalDots - 1 && j < fakeCount_margin - additionalDots) {
let ii = i - additionalDots, jj = j - additionalDots;
alignment && !alignment(ii, jj) ? fakeMatrix[i][j] = void 0 : fakeMatrix[i][j] = !!this.qr.isDark(jj, ii);
} else fakeMatrix[i][j] = options.shape === ShapeType.circle && Math.sqrt((i - center_jAlign) * (i - center_jAlign) + (j - center_jAlign) * (j - center_jAlign)) > center_jAlign ? void 0 : i == additionalDots - 1 || i == fakeCount_margin - additionalDots || j == additionalDots - 1 || j == fakeCount_margin - additionalDots ? (j == additionalDots - 1 && (i < additionalDots + 8 || i > fakeCount_margin - additionalDots - 9) || j == fakeCount_margin - additionalDots && i < additionalDots + 8 || i == additionalDots - 1 && (j < additionalDots + 8 || j > fakeCount_margin - additionalDots - 9) || i == fakeCount_margin - additionalDots && j < additionalDots + 8) && void 0 : this.qr.isDark(0 > j - 2 * additionalDots ? j : j >= count ? j - 2 * additionalDots : j - additionalDots, 0 > i - 2 * additionalDots ? i : i >= count ? i - 2 * additionalDots : i - additionalDots);
}
alignment = QRUtil.getPatternPosition((c