UNPKG

@liquid-js/qr-code-styling

Version:

Generate styled QR codes on web or in Node

972 lines (926 loc) 69.6 kB
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