node-qrcode-lite/lib/renderer/svg-tag.js
2020-04-16 22:50:11 +01:00

81 lines
1.9 KiB
JavaScript

const Utils = require('./utils')
function getColorAttrib (color, attrib) {
const alpha = color.a / 255
const str = attrib + '="' + color.hex + '"'
return alpha < 1
? str + ' ' + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"'
: str
}
function svgCmd (cmd, x, y) {
let str = cmd + x
if (typeof y !== 'undefined') str += ' ' + y
return str
}
function qrToPath (data, size, margin) {
let path = ''
let moveBy = 0
let newRow = false
let lineLength = 0
for (let i = 0; i < data.length; i++) {
const col = Math.floor(i % size)
const row = Math.floor(i / size)
if (!col && !newRow) newRow = true
if (data[i]) {
lineLength++
if (!(i > 0 && col > 0 && data[i - 1])) {
path += newRow
? svgCmd('M', col + margin, 0.5 + row + margin)
: svgCmd('m', moveBy, 0)
moveBy = 0
newRow = false
}
if (!(col + 1 < size && data[i + 1])) {
path += svgCmd('h', lineLength)
lineLength = 0
}
} else {
moveBy++
}
}
return path
}
exports.render = function render (qrData, options, cb) {
const opts = Utils.getOptions(options)
const size = qrData.modules.size
const data = qrData.modules.data
const qrcodesize = size + opts.margin * 2
const bg = !opts.color.light.a
? ''
: '<path ' + getColorAttrib(opts.color.light, 'fill') +
' d="M0 0h' + qrcodesize + 'v' + qrcodesize + 'H0z"/>'
const path =
'<path ' + getColorAttrib(opts.color.dark, 'stroke') +
' d="' + qrToPath(data, size, opts.margin) + '"/>'
const viewBox = 'viewBox="' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '"'
const width = !opts.width ? '' : 'width="' + opts.width + '" height="' + opts.width + '" '
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path + '</svg>\n'
if (typeof cb === 'function') {
cb(null, svgTag)
}
return svgTag
}