/* *copyright Ryan Day 2012 * * Licensed under the MIT license: * http://www.opensource.org/licenses/mit-license.php * * this is the main server side application file for node-qrcode. * these exports use serverside canvas api methods for file IO and buffers * */ var QRCodeLib = require('./renderer/qrcode-draw') var terminalRender = require('./renderer/terminal') var svgRender = require('./renderer/svg') var Canvas = require('canvas') var fs = require('fs') var QRCodeDraw = QRCodeLib.QRCodeDraw // EXPORTS // // breaking change to 0.1 this used to be an instance. now it returns the constructor. // exports.QRCodeDraw = QRCodeDraw // // export error correct levels. // exports.errorCorrectLevels = QRCodeLib.QRErrorCorrectLevel // // export original canvas to be used with draw method, esp. Canvas.Image // exports.canvas = Canvas /* * provide an api to return the max characters allowed for given dimensions, and miniumum error correction level * the qr code library will always use the maximum error correction level for the given numbar of chars constrained by size */ exports.getMaxChars = function (minErrorCorrectionLevel, width, moduleScale) { // TODO THIS NEEDS TO WORK console.log('this doesnt work yet. comming soon =)') } var parseOptions = function (options) { var textKeys = { 'minimum': QRCodeLib.QRErrorCorrectLevel.L, 'medium': QRCodeLib.QRErrorCorrectLevel.M, 'high': QRCodeLib.QRErrorCorrectLevel.Q, 'max': QRCodeLib.QRErrorCorrectLevel.H } if (options.errorCorrectLevel) { var ec = options.errorCorrectLevel if (textKeys[ec]) { options.errorCorrectLevel = textKeys[ec] } } return options } // returns Canvas Object with qr code drawn on it /* * String text, optional Object options, Function callback */ var draw = exports.draw = function (text, options, cb) { var args = Array.prototype.slice.call(arguments) cb = args.pop() if (typeof cb !== 'function') { throw new TypeError('last argument must be a function') } text = args.shift() options = args.shift() || {} options = parseOptions(options) // NOTE the width and height are determined from within the qr code lib and are not configurable from the outside yet var drawInstance = new QRCodeDraw() drawInstance.draw(new Canvas(200, 200), text, options, function (error, canvas, qrWidth) { cb(error, canvas, qrWidth) }) } // returns data uri for drawn qrcode png exports.toDataURL = exports.toDataURI = function (text, options, cb) { if (typeof options === 'function') { cb = options options = {} } draw(text, options, function (error, canvas) { if (error) { cb(error) } else { canvas.toDataURL(cb) } }) } // synchronous PNGStream exports.toPNGStream = function (text, WSpath, options, cb) { if (typeof options === 'function') { cb = options options = {} } var out = fs.createWriteStream(WSpath) draw(text, options, function (error, canvas) { var stream if (error) { cb(error, '') } else { stream = canvas.createPNGStream() } stream.pipe(out) stream.on('end', function () { cb(error, '') }) stream.pipe(out) }) return out } // returns bytes written to file exports.save = function (path, text, options, cb) { if (typeof options === 'function') { cb = options options = {} } var fileExt = path.slice((path.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase() if (fileExt === 'svg') { saveSvg(path, text, options, cb) } else { savePng(path, text, options, cb) } } function savePng (path, text, options, cb) { draw(text, options, function (error, canvas) { if (error) { throw new Error(error) } var fd var buf var fdAndBuf = function () { fs.write(fd, buf, 0, buf.length, 0, function (fsErr, written) { fs.close(fd) if (cb) cb(fsErr, written) }) } // run non dependent async calls at the same time ish canvas.toBuffer(function (canvasErr, _buf) { if (canvasErr) return cb(canvasErr) buf = _buf if (fd) fdAndBuf() }) fs.open(path, 'w', function (fsErr, _fd) { if (fsErr) return cb(fsErr) fd = _fd if (buf) fdAndBuf() }) }) } function saveSvg (path, text, options, cb) { exports.drawSvg(text, function (error, code) { if (!error) { fs.writeFile(path, code, function (fsErr) { return cb(fsErr, fsErr ? null : code) }) } }) } // // this returns an array of points that have either a 0 or 1 value representing 0 for light and 1 for dark // these values include points in the white edge of the qrcode because that edge is actually part of the spec // exports.drawBitArray = function (text, options, cb) { if (typeof options === 'function') { cb = options options = {} } options = parseOptions(options) var drawInstance = new QRCodeDraw() drawInstance.drawBitArray(text, options, function (error, bits, width) { cb(error, bits, width) }) } // // draw qr in your terminal! // exports.drawText = function (text, options, cb) { if (typeof options === 'function') { cb = options options = {} } var drawInstance = new QRCodeDraw() drawInstance.drawBitArray(text, function (error, bits, width) { if (!error) { var code = terminalRender.renderBits(bits, width) cb(error, code) } else { cb(error, null) } }) } exports.drawSvg = function (text, options, cb) { if (typeof options === 'function') { cb = options options = {} } var drawInstance = new QRCodeDraw() drawInstance.drawBitArray(text, function (error, bits, width) { if (!error) { var code = svgRender.renderBits(bits, width, options) cb(error, code) } else { cb(error, null) } }) }