/* * copyright 2010-2012 Ryan Day * http://github.com/soldair/node-qrcode * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * canvas example and fallback support example provided by Joshua Koo * http://jabtunes.com/labs/qrcode.html * "Instant QRCode Mashup by Joshua Koo!" * as far as i can tell the page and the code on the page are public domain * * original table example and library provided by Kazuhiko Arase * http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/ * */ var QRCodeLib = require('../core/qrcode') var ErrorCorrectionLevel = require('../core/error-correction-level') exports.QRCodeDraw = QRCodeDraw exports.QRErrorCorrectLevel = ErrorCorrectionLevel exports.QRCode = QRCodeLib function QRCodeDraw () {} QRCodeDraw.prototype = { scale: 4, // 4 px module size defaultMargin: 20, marginScaleFactor: 5, color: { dark: 'black', light: 'white' }, QRErrorCorrectLevel: ErrorCorrectionLevel, draw: function (canvas, text, options, cb) { var error var args = Array.prototype.slice.call(arguments) cb = args.pop() canvas = args.shift() text = args.shift() options = args.shift() || {} if (typeof cb !== 'function') { // enforce callback api just in case the processing can be made async in the future // or support proc open to libqrencode throw new Error('callback required') } if (typeof options !== 'object') { options.errorCorrectLevel = options } this.scale = options.scale || this.scale this.margin = typeof (options.margin) === 'undefined' ? this.defaultMargin : options.margin // create qrcode! try { var qr = new QRCodeLib(options.version, options.errorCorrectLevel) var scale = this.scale || 4 var ctx = canvas.getContext('2d') var width = 0 qr.addData(text) qr.make() var margin = this.marginWidth() var currenty = margin width = this.dataWidth(qr) + margin * 2 this.resetCanvas(canvas, ctx, width) for (var r = 0, rl = qr.getModuleCount(); r < rl; r++) { var currentx = margin for (var c = 0, cl = qr.getModuleCount(); c < cl; c++) { if (qr.isDark(r, c)) { ctx.fillStyle = this.color.dark ctx.fillRect(currentx, currenty, scale, scale) } else if (this.color.light) { // if falsy configured color ctx.fillStyle = this.color.light ctx.fillRect(currentx, currenty, scale, scale) } currentx += scale } currenty += scale } } catch (e) { error = e } cb(error, canvas, width) }, drawBitArray: function (/* text, errorCorrectLevel,options,cb */) { var args = Array.prototype.slice.call(arguments) var cb = args.pop() var text = args.shift() var options = args.shift() || {} var error // argument processing if (typeof cb !== 'function') { // enforce callback api just in case the processing can be made async in the future // or support proc open to libqrencode throw new Error('callback required as last argument') } // create qrcode! try { var qr = new QRCodeLib(options.version, options.errorCorrectLevel) var width = 0 var bits var bitc = 0 qr.addData(text) qr.make() width = this.dataWidth(qr, 1) bits = new Array(width * width) for (var r = 0, rl = qr.getModuleCount(); r < rl; r++) { for (var c = 0, cl = qr.getModuleCount(); c < cl; c++) { if (qr.isDark(r, c)) { bits[bitc] = 1 } else { bits[bitc] = 0 } bitc++ } } } catch (e) { error = e console.log(e.stack) } cb(error, bits, width) }, marginWidth: function () { var margin = this.margin this.scale = this.scale || 4 // elegant white space next to code is required by spec if ((this.scale * this.marginScaleFactor > margin) && margin > 0) { margin = this.scale * this.marginScaleFactor } return margin }, dataWidth: function (qr, scale) { return qr.getModuleCount() * (scale || this.scale || 4) }, resetCanvas: function (canvas, ctx, width) { ctx.clearRect(0, 0, canvas.width, canvas.height) if (!canvas.style) canvas.style = {} canvas.style.height = canvas.height = width// square! canvas.style.width = canvas.width = width if (this.color.light) { ctx.fillStyle = this.color.light ctx.fillRect(0, 0, canvas.width, canvas.height) } else { // support transparent backgrounds? // not exactly to spec but i really would like someone to be able to add a background with heavily reduced luminosity for simple branding // i could just ditch this because you could also just set #******00 as the color =P ctx.clearRect(0, 0, canvas.width, canvas.height) } } }