UNPKG

qrjs2

Version:

QR code generating with vanilla js (SVG Element, Data URI SVG String, Data URI PNG String, HTML Table Element).

1,000 lines (839 loc) 22.8 kB
/*! * @see {@link https://github.com/englishextra/qrjs2} * modified qr.js -- QR code generator in Javascript (revision 2011-01-19) * Written by Kang Seonghoon <public+qrjs@mearie.org>. * v0.0.20110119 * This source code is in the public domain; if your jurisdiction does not * recognize the public domain the terms of Creative Commons CC0 license * apply. In the other words, you can always do what you want. * added options properties: fillcolor and textcolor * svg now works in Edge 13 and IE 11 * @see {@link https://gist.github.com/englishextra/b46969e3382ef737c611bb59d837220b} * @see {@link https://github.com/lifthrasiir/qr.js/blob/v0.0.20110119/qr.js} * @params {String} data * @params {Object} settings object * element = QRCode.generateSVG(data, settings) * passes jshint with suppressing comments */ /*jslint browser: true */ /*jslint node: true */ /*jshint bitwise: false */ /*jshint shadow: true */ /*jshint sub:true */ /*jshint -W041 */ (function(root, document) { "use strict"; var length = "length"; var VERSIONS = [ null, [[10, 7, 17, 13], [1, 1, 1, 1], []], [[16, 10, 28, 22], [1, 1, 1, 1], [4, 16]], [[26, 15, 22, 18], [1, 1, 2, 2], [4, 20]], [[18, 20, 16, 26], [2, 1, 4, 2], [4, 24]], [[24, 26, 22, 18], [2, 1, 4, 4], [4, 28]], [[16, 18, 28, 24], [4, 2, 4, 4], [4, 32]], [[18, 20, 26, 18], [4, 2, 5, 6], [4, 20, 36]], [[22, 24, 26, 22], [4, 2, 6, 6], [4, 22, 40]], [[22, 30, 24, 20], [5, 2, 8, 8], [4, 24, 44]], [[26, 18, 28, 24], [5, 4, 8, 8], [4, 26, 48]], [[30, 20, 24, 28], [5, 4, 11, 8], [4, 28, 52]], [[22, 24, 28, 26], [8, 4, 11, 10], [4, 30, 56]], [[22, 26, 22, 24], [9, 4, 16, 12], [4, 32, 60]], [[24, 30, 24, 20], [9, 4, 16, 16], [4, 24, 44, 64]], [[24, 22, 24, 30], [10, 6, 18, 12], [4, 24, 46, 68]], [[28, 24, 30, 24], [10, 6, 16, 17], [4, 24, 48, 72]], [[28, 28, 28, 28], [11, 6, 19, 16], [4, 28, 52, 76]], [[26, 30, 28, 28], [13, 6, 21, 18], [4, 28, 54, 80]], [[26, 28, 26, 26], [14, 7, 25, 21], [4, 28, 56, 84]], [[26, 28, 28, 30], [16, 8, 25, 20], [4, 32, 60, 88]], [[26, 28, 30, 28], [17, 8, 25, 23], [4, 26, 48, 70, 92]], [[28, 28, 24, 30], [17, 9, 34, 23], [4, 24, 48, 72, 96]], [[28, 30, 30, 30], [18, 9, 30, 25], [4, 28, 52, 76, 100]], [[28, 30, 30, 30], [20, 10, 32, 27], [4, 26, 52, 78, 104]], [[28, 26, 30, 30], [21, 12, 35, 29], [4, 30, 56, 82, 108]], [[28, 28, 30, 28], [23, 12, 37, 34], [4, 28, 56, 84, 112]], [[28, 30, 30, 30], [25, 12, 40, 34], [4, 32, 60, 88, 116]], [[28, 30, 30, 30], [26, 13, 42, 35], [4, 24, 48, 72, 96, 120]], [[28, 30, 30, 30], [28, 14, 45, 38], [4, 28, 52, 76, 100, 124]], [[28, 30, 30, 30], [29, 15, 48, 40], [4, 24, 50, 76, 102, 128]], [[28, 30, 30, 30], [31, 16, 51, 43], [4, 28, 54, 80, 106, 132]], [[28, 30, 30, 30], [33, 17, 54, 45], [4, 32, 58, 84, 110, 136]], [[28, 30, 30, 30], [35, 18, 57, 48], [4, 28, 56, 84, 112, 140]], [[28, 30, 30, 30], [37, 19, 60, 51], [4, 32, 60, 88, 116, 144]], [[28, 30, 30, 30], [38, 19, 63, 53], [4, 28, 52, 76, 100, 124, 148]], [[28, 30, 30, 30], [40, 20, 66, 56], [4, 22, 48, 74, 100, 126, 152]], [[28, 30, 30, 30], [43, 21, 70, 59], [4, 26, 52, 78, 104, 130, 156]], [[28, 30, 30, 30], [45, 22, 74, 62], [4, 30, 56, 82, 108, 134, 160]], [[28, 30, 30, 30], [47, 24, 77, 65], [4, 24, 52, 80, 108, 136, 164]], [[28, 30, 30, 30], [49, 25, 81, 68], [4, 28, 56, 84, 112, 140, 168]] ]; var MODE_TERMINATOR = 0; var MODE_NUMERIC = 1, MODE_ALPHANUMERIC = 2, MODE_OCTET = 4, MODE_KANJI = 8; var NUMERIC_REGEXP = /^\d*$/; var ALPHANUMERIC_REGEXP = /^[A-Za-z0-9 $%*+\-./:]*$/; var ALPHANUMERIC_OUT_REGEXP = /^[A-Z0-9 $%*+\-./:]*$/; var ECCLEVEL_L = 1, ECCLEVEL_M = 0, ECCLEVEL_Q = 3, ECCLEVEL_H = 2; var GF256_MAP = [], GF256_INVMAP = [-1]; for (var i1 = 0, v = 1; i1 < 255; ++i1) { GF256_MAP.push(v); GF256_INVMAP[v] = i1; v = (v * 2) ^ (v >= 128 ? 0x11d : 0); } var GF256_GENPOLY = [[]]; for (var i2 = 0; i2 < 30; ++i2) { var prevpoly = GF256_GENPOLY[i2], poly = []; for (var j1 = 0; j1 <= i2; ++j1) { var a = j1 < i2 ? GF256_MAP[prevpoly[j1]] : 0; var b = GF256_MAP[(i2 + (prevpoly[j1 - 1] || 0)) % 255]; poly.push(GF256_INVMAP[a ^ b]); } GF256_GENPOLY.push(poly); } var ALPHANUMERIC_MAP = {}; for (var i = 0; i < 45; ++i) { ALPHANUMERIC_MAP[ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:".charAt(i) ] = i; } var MASKFUNCS = [ function(i, j) { return (i + j) % 2 === 0; }, function(i) { return i % 2 === 0; }, function(i, j) { return j % 3 === 0; }, function(i, j) { return (i + j) % 3 === 0; }, function(i, j) { return (((i / 2) | 0) + ((j / 3) | 0)) % 2 === 0; }, function(i, j) { return ((i * j) % 2) + ((i * j) % 3) === 0; }, function(i, j) { return (((i * j) % 2) + ((i * j) % 3)) % 2 === 0; }, function(i, j) { return (((i + j) % 2) + ((i * j) % 3)) % 2 === 0; } ]; var needsverinfo = function needsverinfo(ver) { return ver > 6; }; var getsizebyver = function getsizebyver(ver) { return 4 * ver + 17; }; var nfullbits = function nfullbits(ver) { var v = VERSIONS[ver]; var nbits = 16 * ver * ver + 128 * ver + 64; if (needsverinfo(ver)) { nbits -= 36; } if (v[2][length]) { nbits -= 25 * v[2][length] * v[2][length] - 10 * v[2][length] - 55; } return nbits; }; var ndatabits = function ndatabits(ver, ecclevel) { var nbits = nfullbits(ver) & ~7; var v = VERSIONS[ver]; nbits -= 8 * v[0][ecclevel] * v[1][ecclevel]; return nbits; }; var ndatalenbits = function ndatalenbits(ver, mode) { switch (mode) { case MODE_NUMERIC: return ver < 10 ? 10 : ver < 27 ? 12 : 14; case MODE_ALPHANUMERIC: return ver < 10 ? 9 : ver < 27 ? 11 : 13; case MODE_OCTET: return ver < 10 ? 8 : 16; case MODE_KANJI: return ver < 10 ? 8 : ver < 27 ? 10 : 12; } }; var getmaxdatalen = function getmaxdatalen(ver, mode, ecclevel) { var nbits = ndatabits(ver, ecclevel) - 4 - ndatalenbits(ver, mode); switch (mode) { case MODE_NUMERIC: return ( ((nbits / 10) | 0) * 3 + (nbits % 10 < 4 ? 0 : nbits % 10 < 7 ? 1 : 2) ); case MODE_ALPHANUMERIC: return ((nbits / 11) | 0) * 2 + (nbits % 11 < 6 ? 0 : 1); case MODE_OCTET: return (nbits / 8) | 0; case MODE_KANJI: return (nbits / 13) | 0; } }; var validatedata = function validatedata(mode, data) { switch (mode) { case MODE_NUMERIC: if (!data.match(NUMERIC_REGEXP)) { return null; } return data; case MODE_ALPHANUMERIC: if (!data.match(ALPHANUMERIC_REGEXP)) { return null; } return data.toUpperCase(); case MODE_OCTET: if (typeof data === "string") { var newdata = []; for (var i = 0; i < data[length]; ++i) { var ch = data.charCodeAt(i); if (ch < 0x80) { newdata.push(ch); } else if (ch < 0x800) { newdata.push(0xc0 | (ch >> 6), 0x80 | (ch & 0x3f)); } else if (ch < 0x10000) { newdata.push( 0xe0 | (ch >> 12), 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f) ); } else { newdata.push( 0xf0 | (ch >> 18), 0x80 | ((ch >> 12) & 0x3f), 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f) ); } } return newdata; } else { return data; } } }; var encode = function encode(ver, mode, data, maxbuflen) { var buf = []; var bits = 0, remaining = 8; var datalen = data[length]; var pack = function pack(x, n) { if (n >= remaining) { buf.push(bits | (x >> (n -= remaining))); while (n >= 8) { buf.push((x >> (n -= 8)) & 255); } bits = 0; remaining = 8; } if (n > 0) { bits |= (x & ((1 << n) - 1)) << (remaining -= n); } }; var nlenbits = ndatalenbits(ver, mode); pack(mode, 4); pack(datalen, nlenbits); switch (mode) { case MODE_NUMERIC: for (var i = 2; i < datalen; i += 3) { pack(parseInt(data.substring(i - 2, i + 1), 10), 10); } pack( parseInt(data.substring(i - 2), 10), [0, 4, 7][datalen % 3] ); break; case MODE_ALPHANUMERIC: for (var i2 = 1; i2 < datalen; i2 += 2) { pack( ALPHANUMERIC_MAP[data.charAt(i2 - 1)] * 45 + ALPHANUMERIC_MAP[data.charAt(i2)], 11 ); } if (datalen % 2 === 1) { pack(ALPHANUMERIC_MAP[data.charAt(i2 - 1)], 6); } break; case MODE_OCTET: for (var i3 = 0; i3 < datalen; ++i3) { pack(data[i3], 8); } break; } pack(MODE_TERMINATOR, 4); if (remaining < 8) { buf.push(bits); } while (buf[length] + 1 < maxbuflen) { buf.push(0xec, 0x11); } if (buf[length] < maxbuflen) { buf.push(0xec); } return buf; }; var calculateecc = function calculateecc(poly, genpoly) { var modulus = poly.slice(0); var polylen = poly[length], genpolylen = genpoly[length]; for (var k = 0; k < genpolylen; ++k) { modulus.push(0); } for (var i = 0; i < polylen; ) { var quotient = GF256_INVMAP[modulus[i++]]; if (quotient >= 0) { for (var j = 0; j < genpolylen; ++j) { modulus[i + j] ^= GF256_MAP[(quotient + genpoly[j]) % 255]; } } } return modulus.slice(polylen); }; var augumenteccs = function augumenteccs(poly, nblocks, genpoly) { var subsizes = []; var subsize = (poly[length] / nblocks) | 0, subsize0 = 0; var pivot = nblocks - (poly[length] % nblocks); for (var i = 0; i < pivot; ++i) { subsizes.push(subsize0); subsize0 += subsize; } for (var i2 = pivot; i2 < nblocks; ++i2) { subsizes.push(subsize0); subsize0 += subsize + 1; } subsizes.push(subsize0); var eccs = []; for (var i3 = 0; i3 < nblocks; ++i3) { eccs.push( calculateecc( poly.slice(subsizes[i3], subsizes[i3 + 1]), genpoly ) ); } var result = []; var nitemsperblock = (poly[length] / nblocks) | 0; for (var i4 = 0; i4 < nitemsperblock; ++i4) { for (var j = 0; j < nblocks; ++j) { result.push(poly[subsizes[j] + i4]); } } for (var j2 = pivot; j2 < nblocks; ++j2) { result.push(poly[subsizes[j2 + 1] - 1]); } for (var i5 = 0; i5 < genpoly[length]; ++i5) { for (var j3 = 0; j3 < nblocks; ++j3) { result.push(eccs[j3][i5]); } } return result; }; var augumentbch = function augumentbch(poly, p, genpoly, q) { var modulus = poly << q; for (var i = p - 1; i >= 0; --i) { if ((modulus >> (q + i)) & 1) { modulus ^= genpoly << i; } } return (poly << q) | modulus; }; var makebasematrix = function makebasematrix(ver) { var v = VERSIONS[ver], n = getsizebyver(ver); var matrix = [], reserved = []; for (var i = 0; i < n; ++i) { matrix.push([]); reserved.push([]); } var blit = function blit(y, x, h, w, bits) { for (var i = 0; i < h; ++i) { for (var j = 0; j < w; ++j) { matrix[y + i][x + j] = (bits[i] >> j) & 1; reserved[y + i][x + j] = 1; } } }; blit(0, 0, 9, 9, [ 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x17f, 0x00, 0x40 ]); blit(n - 8, 0, 8, 9, [0x100, 0x7f, 0x41, 0x5d, 0x5d, 0x5d, 0x41, 0x7f]); blit(0, n - 8, 9, 8, [ 0xfe, 0x82, 0xba, 0xba, 0xba, 0x82, 0xfe, 0x00, 0x00 ]); for (var i2 = 9; i2 < n - 8; ++i2) { matrix[6][i2] = matrix[i2][6] = ~i2 & 1; reserved[6][i2] = reserved[i2][6] = 1; } var aligns = v[2], m = aligns[length]; for (var i3 = 0; i3 < m; ++i3) { var minj = i3 === 0 || i3 === m - 1 ? 1 : 0, maxj = i3 === 0 ? m - 1 : m; for (var j = minj; j < maxj; ++j) { blit(aligns[i3], aligns[j], 5, 5, [ 0x1f, 0x11, 0x15, 0x11, 0x1f ]); } } if (needsverinfo(ver)) { var code = augumentbch(ver, 6, 0x1f25, 12); var k = 0; for (var i4 = 0; i4 < 6; ++i4) { for (var j2 = 0; j2 < 3; ++j2) { matrix[i4][n - 11 + j2] = matrix[n - 11 + j2][i4] = (code >> k++) & 1; reserved[i4][n - 11 + j2] = reserved[n - 11 + j2][i4] = 1; } } } return { matrix: matrix, reserved: reserved }; }; var putdata = function putdata(matrix, reserved, buf) { var n = matrix[length]; var k = 0, dir = -1; for (var i = n - 1; i >= 0; i -= 2) { if (i === 6) { --i; } var jj = dir < 0 ? n - 1 : 0; for (var j = 0; j < n; ++j) { for (var ii = i; ii > i - 2; --ii) { if (!reserved[jj][ii]) { matrix[jj][ii] = (buf[k >> 3] >> (~k & 7)) & 1; ++k; } } jj += dir; } dir = -dir; } return matrix; }; var maskdata = function maskdata(matrix, reserved, mask) { var maskf = MASKFUNCS[mask]; var n = matrix[length]; for (var i = 0; i < n; ++i) { for (var j = 0; j < n; ++j) { if (!reserved[i][j]) { matrix[i][j] ^= maskf(i, j); } } } return matrix; }; var putformatinfo = function putformatinfo( matrix, reserved, ecclevel, mask ) { var n = matrix[length]; var code = augumentbch((ecclevel << 3) | mask, 5, 0x537, 10) ^ 0x5412; for (var i = 0; i < 15; ++i) { var r = [ 0, 1, 2, 3, 4, 5, 7, 8, n - 7, n - 6, n - 5, n - 4, n - 3, n - 2, n - 1 ][i]; var c = [ n - 1, n - 2, n - 3, n - 4, n - 5, n - 6, n - 7, n - 8, 7, 5, 4, 3, 2, 1, 0 ][i]; matrix[r][8] = matrix[8][c] = (code >> i) & 1; } return matrix; }; var evaluatematrix = function evaluatematrix(matrix) { var PENALTY_CONSECUTIVE = 3; var PENALTY_TWOBYTWO = 3; var PENALTY_FINDERLIKE = 40; var PENALTY_DENSITY = 10; var evaluategroup = function evaluategroup(groups) { var score = 0; for (var i = 0; i < groups[length]; ++i) { if (groups[i] >= 5) { score += PENALTY_CONSECUTIVE + (groups[i] - 5); } } for (var i2 = 5; i2 < groups[length]; i2 += 2) { var p = groups[i2]; if ( groups[i2 - 1] === p && groups[i2 - 2] === 3 * p && groups[i2 - 3] === p && groups[i2 - 4] === p && (groups[i2 - 5] >= 4 * p || groups[i2 + 1] >= 4 * p) ) { score += PENALTY_FINDERLIKE; } } return score; }; var n = matrix[length]; var score = 0, nblacks = 0; for (var i = 0; i < n; ++i) { var row = matrix[i]; var groups; groups = [0]; for (var j = 0; j < n; ) { var k; for (k = 0; j < n && row[j]; ++k) { ++j; } groups.push(k); for (k = 0; j < n && !row[j]; ++k) { ++j; } groups.push(k); } score += evaluategroup(groups); groups = [0]; for (var j2 = 0; j2 < n; ) { var k2; for (k2 = 0; j2 < n && matrix[j2][i]; ++k2) { ++j2; } groups.push(k2); for (k2 = 0; j2 < n && !matrix[j2][i]; ++k2) { ++j2; } groups.push(k2); } score += evaluategroup(groups); var nextrow = matrix[i + 1] || []; nblacks += row[0]; for (var j3 = 1; j3 < n; ++j3) { var p = row[j3]; nblacks += p; if ( row[j3 - 1] === p && nextrow[j3] === p && nextrow[j3 - 1] === p ) { score += PENALTY_TWOBYTWO; } } } score += PENALTY_DENSITY * ((Math.abs(nblacks / n / n - 0.5) / 0.05) | 0); return score; }; var _generate = function generate(data, ver, mode, ecclevel, mask) { var v = VERSIONS[ver]; var buf = encode(ver, mode, data, ndatabits(ver, ecclevel) >> 3); buf = augumenteccs(buf, v[1][ecclevel], GF256_GENPOLY[v[0][ecclevel]]); var result = makebasematrix(ver); var matrix = result.matrix, reserved = result.reserved; putdata(matrix, reserved, buf); if (mask < 0) { maskdata(matrix, reserved, 0); putformatinfo(matrix, reserved, ecclevel, 0); var bestmask = 0, bestscore = evaluatematrix(matrix); maskdata(matrix, reserved, 0); for (mask = 1; mask < 8; ++mask) { maskdata(matrix, reserved, mask); putformatinfo(matrix, reserved, ecclevel, mask); var score = evaluatematrix(matrix); if (bestscore > score) { bestscore = score; bestmask = mask; } maskdata(matrix, reserved, mask); } mask = bestmask; } maskdata(matrix, reserved, mask); putformatinfo(matrix, reserved, ecclevel, mask); return matrix; }; var QRCode = { generate: function generate(data, settings) { var options = settings || {}; var MODES = { numeric: MODE_NUMERIC, alphanumeric: MODE_ALPHANUMERIC, octet: MODE_OCTET }; var ECCLEVELS = { L: ECCLEVEL_L, M: ECCLEVEL_M, Q: ECCLEVEL_Q, H: ECCLEVEL_H }; var ver = options.version || -1; var ecclevel = ECCLEVELS[(options.ecclevel || "L").toUpperCase()]; var mode = options.mode ? MODES[options.mode.toLowerCase()] : -1; var mask = "mask" in options ? options.mask : -1; if (mode < 0) { if (typeof data === "string") { if (data.match(NUMERIC_REGEXP)) { mode = MODE_NUMERIC; } else if (data.match(ALPHANUMERIC_OUT_REGEXP)) { mode = MODE_ALPHANUMERIC; } else { mode = MODE_OCTET; } } else { mode = MODE_OCTET; } } else if ( !( mode === MODE_NUMERIC || mode === MODE_ALPHANUMERIC || mode === MODE_OCTET ) ) { throw "invalid or unsupported mode"; } data = validatedata(mode, data); if (data === null) { throw "invalid data format"; } if (ecclevel < 0 || ecclevel > 3) { throw "invalid ECC level"; } if (ver < 0) { for (ver = 1; ver <= 40; ++ver) { if (data[length] <= getmaxdatalen(ver, mode, ecclevel)) { break; } } if (ver > 40) { throw "too large data"; } } else if (ver < 1 || ver > 40) { throw "invalid version"; } if (mask !== -1 && (mask < 0 || mask > 8)) { throw "invalid mask"; } return _generate(data, ver, mode, ecclevel, mask); }, generateHTML: function generateHTML(data, settings) { var options = settings || {}; var fillcolor = options.fillcolor ? options.fillcolor : "#FFFFFF"; var textcolor = options.textcolor ? options.textcolor : "#000000"; var matrix = QRCode.generate(data, options); var modsize = Math.max(options.modulesize || 5, 0.5); var margin = Math.max( options.margin !== null ? options.margin : 4, 0.0 ); var e = document.createElement("div"); var n = matrix[length]; var html = [ '<table border="0" cellspacing="0" cellpadding="0" style="border:' + modsize * margin + "px solid " + fillcolor + ";background:" + fillcolor + '">' ]; for (var i = 0; i < n; ++i) { html.push("<tr>"); for (var j = 0; j < n; ++j) { html.push( '<td style="width:' + modsize + "px;height:" + modsize + "px" + (matrix[i][j] ? ";background:" + textcolor : "") + '"></td>' ); } html.push("</tr>"); } e.className = "qrcode"; /* e.innerHTML = html.join("") + "</table>"; */ var range = document.createRange(); range.selectNodeContents(e); var frag = range.createContextualFragment( html.join("") + "</table>" ); e.appendChild(frag); return e; }, generateSVG: function generateSVG(data, settings) { var options = settings || {}; var fillcolor = options.fillcolor ? options.fillcolor : "#FFFFFF"; var textcolor = options.textcolor ? options.textcolor : "#000000"; var matrix = QRCode.generate(data, options); var n = matrix[length]; var modsize = Math.max(options.modulesize || 5, 0.5); var margin = Math.max(options.margin ? options.margin : 4, 0.0); var size = modsize * (n + 2 * margin); /* var common = ' class= "fg"' + ' width="' + modsize + '" height="' + modsize + '"/>'; */ var e = document.createElementNS( "http://www.w3.org/2000/svg", "svg" ); e.setAttributeNS(null, "viewBox", "0 0 " + size + " " + size); e.setAttributeNS(null, "style", "shape-rendering:crispEdges"); var qrcodeId = "qrcode" + Date.now(); e.setAttributeNS(null, "id", qrcodeId); var frag = document.createDocumentFragment(); /* var svg = ['<style scoped>.bg{fill:' + fillcolor + '}.fg{fill:' + textcolor + '}</style>', '<rect class="bg" x="0" y="0"', 'width="' + size + '" height="' + size + '"/>', ]; */ var style = document.createElementNS( "http://www.w3.org/2000/svg", "style" ); style.appendChild( document.createTextNode( "#" + qrcodeId + " .bg{fill:" + fillcolor + "}#" + qrcodeId + " .fg{fill:" + textcolor + "}" ) ); /* style.setAttributeNS(null, "scoped", "scoped"); */ frag.appendChild(style); var createRect = function createRect(c, f, x, y, s) { var fg = document.createElementNS( "http://www.w3.org/2000/svg", "rect" ) || ""; fg.setAttributeNS(null, "class", c); fg.setAttributeNS(null, "fill", f); fg.setAttributeNS(null, "x", x); fg.setAttributeNS(null, "y", y); fg.setAttributeNS(null, "width", s); fg.setAttributeNS(null, "height", s); return fg; }; frag.appendChild(createRect("bg", "none", 0, 0, size)); var yo = margin * modsize; for (var y = 0; y < n; ++y) { var xo = margin * modsize; for (var x = 0; x < n; ++x) { if (matrix[y][x]) { /* svg.push('<rect x="' + xo + '" y="' + yo + '"', common); */ frag.appendChild( createRect("fg", "none", xo, yo, modsize) ); } xo += modsize; } yo += modsize; } /* e.innerHTML = svg.join(""); */ e.appendChild(frag); return e; }, generatePNG: function generatePNG(data, settings) { var options = settings || {}; var fillcolor = options.fillcolor || "#FFFFFF"; var textcolor = options.textcolor || "#000000"; var matrix = QRCode.generate(data, options); var modsize = Math.max(options.modulesize || 5, 0.5); var margin = Math.max( options.margin !== null && options.margin !== undefined ? options.margin : 4, 0.0 ); var n = matrix[length]; var size = modsize * (n + 2 * margin); var canvas = document.createElement("canvas"), context; canvas.width = canvas.height = size; context = canvas.getContext("2d"); if (!context) { throw "canvas support is needed for PNG output"; } context.fillStyle = fillcolor; context.fillRect(0, 0, size, size); context.fillStyle = textcolor; for (var i = 0; i < n; ++i) { for (var j = 0; j < n; ++j) { if (matrix[i][j]) { context.fillRect( modsize * (margin + j), modsize * (margin + i), modsize, modsize ); } } } return canvas.toDataURL(); } }; root.QRCode = QRCode; })("undefined" !== typeof window ? window : this, document); /*jshint bitwise: true */ /*jshint shadow: false */ /*jshint sub: false */ /*jshint +W041 */