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 }