node-qrcode-lite/lib/renderer/qrcode-draw.js
Vincenzo Greco 77064f5e5e Refactor/core ()
* Split core lib into multiple files

* Refactor data encoding methods

* Refactor data masking process

* Improve qr code generation process

* Increase minimum required node version to 0.10

* Add linter

* Add tests and tests coverage

* Update travis config to fix compilation issues

* Add examples folder

* Add missing license tag in package.json

* Update build script and add sourcemap support

* Publish only strictly needed files on npm

* Update readme
2016-12-16 23:45:08 +01:00

173 lines
4.8 KiB
JavaScript

/*
* 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)
}
}
}