diff --git a/lib/browser.js b/lib/browser.js index dc8a9998..4c552d9d 100644 --- a/lib/browser.js +++ b/lib/browser.js @@ -5,10 +5,15 @@ const QRCode = require('./core/qrcode') const CanvasRenderer = require('./renderer/canvas') const SvgRenderer = require('./renderer/svg-tag.js') +function renderFuncHasCallback (renderFunc) { + return renderFunc === CanvasRenderer.renderToBlob || renderFunc === CanvasRenderer.renderToArrayBuffer +} + function renderCanvas (renderFunc, canvas, text, opts, cb) { const args = [].slice.call(arguments, 1) const argsNum = args.length const isLastArgCb = typeof args[argsNum - 1] === 'function' + const renderFnHasCallback = renderFuncHasCallback(renderFunc) if (!isLastArgCb && !canPromise()) { throw new Error('Callback required as last argument') @@ -51,7 +56,14 @@ function renderCanvas (renderFunc, canvas, text, opts, cb) { return new Promise(function (resolve, reject) { try { const data = QRCode.create(text, opts) - resolve(renderFunc(data, canvas, opts)) + if (renderFnHasCallback) { + renderFunc(data, canvas, opts, (err, result) => { + if (err) reject(err) + else resolve(result) + }) + } else { + resolve(renderFunc(data, canvas, opts)) + } } catch (e) { reject(e) } @@ -60,7 +72,11 @@ function renderCanvas (renderFunc, canvas, text, opts, cb) { try { const data = QRCode.create(text, opts) - cb(null, renderFunc(data, canvas, opts)) + if (renderFnHasCallback) { + renderFunc(data, canvas, opts, cb) + } else { + cb(null, renderFunc(data, canvas, opts)) + } } catch (e) { cb(e) } @@ -69,6 +85,8 @@ function renderCanvas (renderFunc, canvas, text, opts, cb) { exports.create = QRCode.create exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render) exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL) +exports.toBlob = renderCanvas.bind(null, CanvasRenderer.renderToBlob) +exports.toArrayBuffer = renderCanvas.bind(null, CanvasRenderer.renderToArrayBuffer) // only svg for now. exports.toString = renderCanvas.bind(null, function (data, _, opts) { diff --git a/lib/renderer/canvas.js b/lib/renderer/canvas.js index 42050cf5..2d95461b 100644 --- a/lib/renderer/canvas.js +++ b/lib/renderer/canvas.js @@ -61,3 +61,53 @@ exports.renderToDataURL = function renderToDataURL (qrData, canvas, options) { return canvasEl.toDataURL(type, rendererOpts.quality) } + +exports.renderToBlob = function renderToBlob (qrData, canvas, options, callback) { + let opts = options + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!opts) opts = {} + + const canvasEl = exports.render(qrData, canvas, opts) + const type = opts.type || 'image/png' + const rendererOpts = opts.rendererOpts || {} + + canvasEl.toBlob((blobOrNull) => { + if (blobOrNull === null) { + callback(new Error('Failed to get canvas as blob')) + } else { + callback(null, blobOrNull) + } + }, type, rendererOpts.quality) +} + +exports.renderToArrayBuffer = function renderToArrayBuffer (qrData, canvas, options, callback) { + let opts = options + + if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) { + opts = canvas + canvas = undefined + } + + if (!opts) opts = {} + + const canvasEl = exports.render(qrData, canvas, opts) + const type = opts.type || 'image/png' + + canvasEl.toBlob(async (blobOrNull) => { + if (blobOrNull === null) { + callback(new Error('Failed to get canvas as blob')) + } else { + try { + const arrayBuffer = await blobOrNull.arrayBuffer() + callback(null, arrayBuffer) + } catch (e) { + callback(e) + } + } + }, type, opts.rendererOpts.quality) +}