UNPKG

awesome-qr

Version:

An awesome QR code generator written in JavaScript.

1,238 lines (1,147 loc) 96.1 kB
/** * Awesome-qr.js * https://github.com/SumiMakito/Awesome-qr.js * * Copyright © 2017 Makito <master@keep.moe>, https://www.keep.moe/ * * Licensed under Apache License 2.0 License. * Copyright (c) 2017 Makito, https://www.keep.moe * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @fileoverview * - Using the 'QRCode for Javascript library' * - Fixed dataset of 'QRCode for Javascript library' for support full-spec. * - this library has no dependencies. * * @author davidshimjs * @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a> * @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a> */ var AwesomeQRCode; var GIFE; require([__awesome_qr_base_path+'/gif'], function (gifEncoder) { GIFE = gifEncoder; }); // gifuct-js.js // https://raw.githubusercontent.com/matt-way/gifuct-js/master/dist/gifuct-js.js (function() { (function e(t, n, r) { function s(o, u) { if (!n[o]) { if (!t[o]) { var a = typeof require == "function" && require; if (!u && a) return a(o, !0); if (i) return i(o, !0); var f = new Error("Cannot find module '" + o + "'"); throw f.code = "MODULE_NOT_FOUND", f } var l = n[o] = { exports: {} }; t[o][0].call(l.exports, function(e) { var n = t[o][1][e]; return s(n ? n : e) }, l, l.exports, e, t, n, r) } return n[o].exports } var i = typeof require == "function" && require; for (var o = 0; o < r.length; o++) s(r[o]); return s })({ 1: [function(require, module, exports) { // Stream object for reading off bytes from a byte array function ByteStream(data) { this.data = data; this.pos = 0; } // read the next byte off the stream ByteStream.prototype.readByte = function() { return this.data[this.pos++]; }; // look at the next byte in the stream without updating the stream position ByteStream.prototype.peekByte = function() { return this.data[this.pos]; }; // read an array of bytes ByteStream.prototype.readBytes = function(n) { var bytes = new Array(n); for (var i = 0; i < n; i++) { bytes[i] = this.readByte(); } return bytes; }; // peek at an array of bytes without updating the stream position ByteStream.prototype.peekBytes = function(n) { var bytes = new Array(n); for (var i = 0; i < n; i++) { bytes[i] = this.data[this.pos + i]; } return bytes; }; // read a string from a byte set ByteStream.prototype.readString = function(len) { var str = ''; for (var i = 0; i < len; i++) { str += String.fromCharCode(this.readByte()); } return str; }; // read a single byte and return an array of bit booleans ByteStream.prototype.readBitArray = function() { var arr = []; var bite = this.readByte(); for (var i = 7; i >= 0; i--) { arr.push(!!(bite & (1 << i))); } return arr; }; // read an unsigned int with endian option ByteStream.prototype.readUnsigned = function(littleEndian) { var a = this.readBytes(2); if (littleEndian) { return (a[1] << 8) + a[0]; } else { return (a[0] << 8) + a[1]; } }; module.exports = ByteStream; }, {}], 2: [function(require, module, exports) { // Primary data parsing object used to parse byte arrays var ByteStream = require('./bytestream'); function DataParser(data) { this.stream = new ByteStream(data); // the final parsed object from the data this.output = {}; } DataParser.prototype.parse = function(schema) { // the top level schema is just the top level parts array this.parseParts(this.output, schema); return this.output; }; // parse a set of hierarchy parts providing the parent object, and the subschema DataParser.prototype.parseParts = function(obj, schema) { for (var i = 0; i < schema.length; i++) { var part = schema[i]; this.parsePart(obj, part); } }; DataParser.prototype.parsePart = function(obj, part) { var name = part.label; var value; // make sure the part meets any parse requirements if (part.requires && !part.requires(this.stream, this.output, obj)) { return; } if (part.loop) { // create a parse loop over the parts var items = []; while (part.loop(this.stream)) { var item = {}; this.parseParts(item, part.parts); items.push(item); } obj[name] = items; } else if (part.parts) { // process any child parts value = {}; this.parseParts(value, part.parts); obj[name] = value; } else if (part.parser) { // parse the value using a parser value = part.parser(this.stream, this.output, obj); if (!part.skip) { obj[name] = value; } } else if (part.bits) { // convert the next byte to a set of bit fields obj[name] = this.parseBits(part.bits); } }; // combine bits to calculate value function bitsToNum(bitArray) { return bitArray.reduce(function(s, n) { return s * 2 + n; }, 0); } // parse a byte as a bit set (flags and values) DataParser.prototype.parseBits = function(details) { var out = {}; var bits = this.stream.readBitArray(); for (var key in details) { var item = details[key]; if (item.length) { // convert the bit set to value out[key] = bitsToNum(bits.slice(item.index, item.index + item.length)); } else { out[key] = bits[item.index]; } } return out; }; module.exports = DataParser; }, { "./bytestream": 1 }], 3: [function(require, module, exports) { // a set of common parsers used with DataParser var Parsers = { // read a byte readByte: function() { return function(stream) { return stream.readByte(); }; }, // read an array of bytes readBytes: function(length) { return function(stream) { return stream.readBytes(length); }; }, // read a string from bytes readString: function(length) { return function(stream) { return stream.readString(length); }; }, // read an unsigned int (with endian) readUnsigned: function(littleEndian) { return function(stream) { return stream.readUnsigned(littleEndian); }; }, // read an array of byte sets readArray: function(size, countFunc) { return function(stream, obj, parent) { var count = countFunc(stream, obj, parent); var arr = new Array(count); for (var i = 0; i < count; i++) { arr[i] = stream.readBytes(size); } return arr; }; } }; module.exports = Parsers; }, {}], 4: [function(require, module, exports) { // export wrapper for exposing library var GIF = window.GIF || {}; GIF = require('./gif'); window.GIF = GIF; }, { "./gif": 5 }], 5: [function(require, module, exports) { // object used to represent array buffer data for a gif file var DataParser = require('../bower_components/js-binary-schema-parser/src/dataparser'); var gifSchema = require('./schema'); function GIF(arrayBuffer) { // convert to byte array var byteData = new Uint8Array(arrayBuffer); var parser = new DataParser(byteData); // parse the data this.raw = parser.parse(gifSchema); // set a flag to make sure the gif contains at least one image this.raw.hasImages = false; for (var f = 0; f < this.raw.frames.length; f++) { if (this.raw.frames[f].image) { this.raw.hasImages = true; break; } } } // process a single gif image frames data, decompressing it using LZW // if buildPatch is true, the returned image will be a clamped 8 bit image patch // for use directly with a canvas. GIF.prototype.decompressFrame = function(index, buildPatch) { // make sure a valid frame is requested if (index >= this.raw.frames.length) { return null; } var frame = this.raw.frames[index]; if (frame.image) { // get the number of pixels var totalPixels = frame.image.descriptor.width * frame.image.descriptor.height; // do lzw decompression var pixels = lzw(frame.image.data.minCodeSize, frame.image.data.blocks, totalPixels); // deal with interlacing if necessary if (frame.image.descriptor.lct.interlaced) { pixels = deinterlace(pixels, frame.image.descriptor.width); } // setup usable image object var image = { pixels: pixels, dims: { top: frame.image.descriptor.top, left: frame.image.descriptor.left, width: frame.image.descriptor.width, height: frame.image.descriptor.height } }; // color table if (frame.image.descriptor.lct && frame.image.descriptor.lct.exists) { image.colorTable = frame.image.lct; } else { image.colorTable = this.raw.gct; } // add per frame relevant gce information if (frame.gce) { image.delay = (frame.gce.delay || 10) * 10; // convert to ms image.disposalType = frame.gce.extras.disposal; // transparency if (frame.gce.extras.transparentColorGiven) { image.transparentIndex = frame.gce.transparentColorIndex; } } // create canvas usable imagedata if desired if (buildPatch) { image.patch = generatePatch(image); } return image; } // frame does not contains image return null; /** * javascript port of java LZW decompression * Original java author url: https://gist.github.com/devunwired/4479231 */ function lzw(minCodeSize, data, pixelCount) { var MAX_STACK_SIZE = 4096; var nullCode = -1; var npix = pixelCount; var available, clear, code_mask, code_size, end_of_information, in_code, old_code, bits, code, i, datum, data_size, first, top, bi, pi; var dstPixels = new Array(pixelCount); var prefix = new Array(MAX_STACK_SIZE); var suffix = new Array(MAX_STACK_SIZE); var pixelStack = new Array(MAX_STACK_SIZE + 1); // Initialize GIF data stream decoder. data_size = minCodeSize; clear = 1 << data_size; end_of_information = clear + 1; available = clear + 2; old_code = nullCode; code_size = data_size + 1; code_mask = (1 << code_size) - 1; for (code = 0; code < clear; code++) { prefix[code] = 0; suffix[code] = code; } // Decode GIF pixel stream. datum = bits = count = first = top = pi = bi = 0; for (i = 0; i < npix;) { if (top === 0) { if (bits < code_size) { // get the next byte datum += data[bi] << bits; bits += 8; bi++; continue; } // Get the next code. code = datum & code_mask; datum >>= code_size; bits -= code_size; // Interpret the code if ((code > available) || (code == end_of_information)) { break; } if (code == clear) { // Reset decoder. code_size = data_size + 1; code_mask = (1 << code_size) - 1; available = clear + 2; old_code = nullCode; continue; } if (old_code == nullCode) { pixelStack[top++] = suffix[code]; old_code = code; first = code; continue; } in_code = code; if (code == available) { pixelStack[top++] = first; code = old_code; } while (code > clear) { pixelStack[top++] = suffix[code]; code = prefix[code]; } first = suffix[code] & 0xff; pixelStack[top++] = first; // add a new string to the table, but only if space is available // if not, just continue with current table until a clear code is found // (deferred clear code implementation as per GIF spec) if (available < MAX_STACK_SIZE) { prefix[available] = old_code; suffix[available] = first; available++; if (((available & code_mask) === 0) && (available < MAX_STACK_SIZE)) { code_size++; code_mask += available; } } old_code = in_code; } // Pop a pixel off the pixel stack. top--; dstPixels[pi++] = pixelStack[top]; i++; } for (i = pi; i < npix; i++) { dstPixels[i] = 0; // clear missing pixels } return dstPixels; } // deinterlace function from https://github.com/shachaf/jsgif function deinterlace(pixels, width) { var newPixels = new Array(pixels.length); var rows = pixels.length / width; var cpRow = function(toRow, fromRow) { var fromPixels = pixels.slice(fromRow * width, (fromRow + 1) * width); newPixels.splice.apply(newPixels, [toRow * width, width].concat(fromPixels)); }; // See appendix E. var offsets = [0, 4, 2, 1]; var steps = [8, 8, 4, 2]; var fromRow = 0; for (var pass = 0; pass < 4; pass++) { for (var toRow = offsets[pass]; toRow < rows; toRow += steps[pass]) { cpRow(toRow, fromRow); fromRow++; } } return newPixels; } // create a clamped byte array patch for the frame image to be used directly with a canvas // TODO: could potentially squeeze some performance by doing a direct 32bit write per iteration function generatePatch(image) { var totalPixels = image.pixels.length; var patchData = new Uint8ClampedArray(totalPixels * 4); for (var i = 0; i < totalPixels; i++) { var pos = i * 4; var colorIndex = image.pixels[i]; var color = image.colorTable[colorIndex]; patchData[pos] = color[0]; patchData[pos + 1] = color[1]; patchData[pos + 2] = color[2]; patchData[pos + 3] = colorIndex !== image.transparentIndex ? 255 : 0; } return patchData; } }; // returns all frames decompressed GIF.prototype.decompressFrames = function(buildPatch) { var frames = []; for (var i = 0; i < this.raw.frames.length; i++) { var frame = this.raw.frames[i]; if (frame.image) { frames.push(this.decompressFrame(i, buildPatch)); } } return frames; }; module.exports = GIF; }, { "../bower_components/js-binary-schema-parser/src/dataparser": 2, "./schema": 6 }], 6: [function(require, module, exports) { // Schema for the js file parser to use to parse gif files // For js object convenience (re-use), the schema objects are approximately reverse ordered // common parsers available var Parsers = require('../bower_components/js-binary-schema-parser/src/parsers'); // a set of 0x00 terminated subblocks var subBlocks = { label: 'blocks', parser: function(stream) { var out = []; var terminator = 0x00; for (var size = stream.readByte(); size !== terminator; size = stream.readByte()) { out = out.concat(stream.readBytes(size)); } return out; } }; // global control extension var gce = { label: 'gce', requires: function(stream) { // just peek at the top two bytes, and if true do this var codes = stream.peekBytes(2); return codes[0] === 0x21 && codes[1] === 0xF9; }, parts: [ { label: 'codes', parser: Parsers.readBytes(2), skip: true }, { label: 'byteSize', parser: Parsers.readByte() }, { label: 'extras', bits: { future: { index: 0, length: 3 }, disposal: { index: 3, length: 3 }, userInput: { index: 6 }, transparentColorGiven: { index: 7 } } }, { label: 'delay', parser: Parsers.readUnsigned(true) }, { label: 'transparentColorIndex', parser: Parsers.readByte() }, { label: 'terminator', parser: Parsers.readByte(), skip: true } ] }; // image pipeline block var image = { label: 'image', requires: function(stream) { // peek at the next byte var code = stream.peekByte(); return code === 0x2C; }, parts: [ { label: 'code', parser: Parsers.readByte(), skip: true }, { label: 'descriptor', // image descriptor parts: [ { label: 'left', parser: Parsers.readUnsigned(true) }, { label: 'top', parser: Parsers.readUnsigned(true) }, { label: 'width', parser: Parsers.readUnsigned(true) }, { label: 'height', parser: Parsers.readUnsigned(true) }, { label: 'lct', bits: { exists: { index: 0 }, interlaced: { index: 1 }, sort: { index: 2 }, future: { index: 3, length: 2 }, size: { index: 5, length: 3 } } } ] }, { label: 'lct', // optional local color table requires: function(stream, obj, parent) { return parent.descriptor.lct.exists; }, parser: Parsers.readArray(3, function(stream, obj, parent) { return Math.pow(2, parent.descriptor.lct.size + 1); }) }, { label: 'data', // the image data blocks parts: [ { label: 'minCodeSize', parser: Parsers.readByte() }, subBlocks ] } ] }; // plain text block var text = { label: 'text', requires: function(stream) { // just peek at the top two bytes, and if true do this var codes = stream.peekBytes(2); return codes[0] === 0x21 && codes[1] === 0x01; }, parts: [ { label: 'codes', parser: Parsers.readBytes(2), skip: true }, { label: 'blockSize', parser: Parsers.readByte() }, { label: 'preData', parser: function(stream, obj, parent) { return stream.readBytes(parent.text.blockSize); } }, subBlocks ] }; // application block var application = { label: 'application', requires: function(stream, obj, parent) { // make sure this frame doesn't already have a gce, text, comment, or image // as that means this block should be attached to the next frame //if(parent.gce || parent.text || parent.image || parent.comment){ return false; } // peek at the top two bytes var codes = stream.peekBytes(2); return codes[0] === 0x21 && codes[1] === 0xFF; }, parts: [ { label: 'codes', parser: Parsers.readBytes(2), skip: true }, { label: 'blockSize', parser: Parsers.readByte() }, { label: 'id', parser: function(stream, obj, parent) { return stream.readString(parent.blockSize); } }, subBlocks ] }; // comment block var comment = { label: 'comment', requires: function(stream, obj, parent) { // make sure this frame doesn't already have a gce, text, comment, or image // as that means this block should be attached to the next frame //if(parent.gce || parent.text || parent.image || parent.comment){ return false; } // peek at the top two bytes var codes = stream.peekBytes(2); return codes[0] === 0x21 && codes[1] === 0xFE; }, parts: [ { label: 'codes', parser: Parsers.readBytes(2), skip: true }, subBlocks ] }; // frames of ext and image data var frames = { label: 'frames', parts: [ gce, application, comment, image, text ], loop: function(stream) { var nextCode = stream.peekByte(); // rather than check for a terminator, we should check for the existence // of an ext or image block to avoid infinite loops //var terminator = 0x3B; //return nextCode !== terminator; return nextCode === 0x21 || nextCode === 0x2C; } }; // main GIF schema var schemaGIF = [{ label: 'header', // gif header parts: [ { label: 'signature', parser: Parsers.readString(3) }, { label: 'version', parser: Parsers.readString(3) } ] }, { label: 'lsd', // local screen descriptor parts: [ { label: 'width', parser: Parsers.readUnsigned(true) }, { label: 'height', parser: Parsers.readUnsigned(true) }, { label: 'gct', bits: { exists: { index: 0 }, resolution: { index: 1, length: 3 }, sort: { index: 4 }, size: { index: 5, length: 3 } } }, { label: 'backgroundColorIndex', parser: Parsers.readByte() }, { label: 'pixelAspectRatio', parser: Parsers.readByte() } ] }, { label: 'gct', // global color table requires: function(stream, obj) { return obj.lsd.gct.exists; }, parser: Parsers.readArray(3, function(stream, obj) { return Math.pow(2, obj.lsd.gct.size + 1); }) }, frames // content frames ]; module.exports = schemaGIF; }, { "../bower_components/js-binary-schema-parser/src/parsers": 3 }] }, {}, [4]) })(); // QR CODE CORE LIBRARY DEFINITION (function() { // QR CODE CORE LIBRARY DEFINITION START // SHOULD NOT BE MODIFIED // // QRCode for JavaScript // // Copyright (c) 2009 Kazuhiko Arase // // URL: http://www.d-project.com/ // // Licensed under the MIT license: // http://www.opensource.org/licenses/mit-license.php // // The word "QR Code" is registered trademark of DENSO WAVE INCORPORATED // http://www.denso-wave.com/qrcode/faqpatent-e.html // function QR8bitByte(data) { this.mode = QRMode.MODE_8BIT_BYTE; this.data = data; this.parsedData = []; for (var i = 0, l = this.data.length; i < l; i++) { var byteArray = []; var code = this.data.charCodeAt(i); if (code > 0x10000) { byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); byteArray[3] = 0x80 | (code & 0x3F) } else if (code > 0x800) { byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); byteArray[2] = 0x80 | (code & 0x3F) } else if (code > 0x80) { byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); byteArray[1] = 0x80 | (code & 0x3F) } else { byteArray[0] = code } this.parsedData.push(byteArray) } this.parsedData = Array.prototype.concat.apply([], this.parsedData); if (this.parsedData.length != this.data.length) { this.parsedData.unshift(191); this.parsedData.unshift(187); this.parsedData.unshift(239) } } QR8bitByte.prototype = { getLength: function(buffer) { return this.parsedData.length }, write: function(buffer) { for (var i = 0, l = this.parsedData.length; i < l; i++) { buffer.put(this.parsedData[i], 8) } } }; function QRCodeModel(typeNumber, errorCorrectLevel) { this.typeNumber = typeNumber; this.errorCorrectLevel = errorCorrectLevel; this.modules = null; this.moduleCount = 0; this.dataCache = null; this.dataList = [] } QRCodeModel.prototype = { addData: function(data) { var newData = new QR8bitByte(data); this.dataList.push(newData); this.dataCache = null }, isDark: function(row, col) { if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) { throw new Error(row + "," + col) } return this.modules[row][col] }, getModuleCount: function() { return this.moduleCount }, make: function() { ///////////////////////////////////////////// if (this.typeNumber < 1) { var typeNumber = 1; for (typeNumber = 1; typeNumber < 40; typeNumber++) { var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel); var buffer = new QRBitBuffer(); var totalDataCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalDataCount += rsBlocks[i].dataCount; } for (var i = 0; i < this.dataList.length; i++) { var data = this.dataList[i]; buffer.put(data.mode, 4); buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); data.write(buffer); } if (buffer.getLengthInBits() <= totalDataCount * 8) break; } this.typeNumber = typeNumber; } ///////////////////////////////////////////// this.makeImpl(!1, this.getBestMaskPattern()) }, makeImpl: function(test, maskPattern) { this.moduleCount = this.typeNumber * 4 + 17; this.modules = new Array(this.moduleCount); for (var row = 0; row < this.moduleCount; row++) { this.modules[row] = new Array(this.moduleCount); for (var col = 0; col < this.moduleCount; col++) { this.modules[row][col] = null } } this.setupPositionProbePattern(0, 0); this.setupPositionProbePattern(this.moduleCount - 7, 0); this.setupPositionProbePattern(0, this.moduleCount - 7); this.setupPositionAdjustPattern(); this.setupTimingPattern(); this.setupTypeInfo(test, maskPattern); if (this.typeNumber >= 7) { this.setupTypeNumber(test) } if (this.dataCache == null) { this.dataCache = QRCodeModel.createData(this.typeNumber, this.errorCorrectLevel, this.dataList) } this.mapData(this.dataCache, maskPattern) }, setupPositionProbePattern: function(row, col) { for (var r = -1; r <= 7; r++) { if (row + r <= -1 || this.moduleCount <= row + r) continue; for (var c = -1; c <= 7; c++) { if (col + c <= -1 || this.moduleCount <= col + c) continue; if ((0 <= r && r <= 6 && (c == 0 || c == 6)) || (0 <= c && c <= 6 && (r == 0 || r == 6)) || (2 <= r && r <= 4 && 2 <= c && c <= 4)) { this.modules[row + r][col + c] = !0 } else { this.modules[row + r][col + c] = !1 } } } }, getBestMaskPattern: function() { var minLostPoint = 0; var pattern = 0; for (var i = 0; i < 8; i++) { this.makeImpl(!0, i); var lostPoint = QRUtil.getLostPoint(this); if (i == 0 || minLostPoint > lostPoint) { minLostPoint = lostPoint; pattern = i } } return pattern }, createMovieClip: function(target_mc, instance_name, depth) { var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth); var cs = 1; this.make(); for (var row = 0; row < this.modules.length; row++) { var y = row * cs; for (var col = 0; col < this.modules[row].length; col++) { var x = col * cs; var dark = this.modules[row][col]; if (dark) { qr_mc.beginFill(0, 100); qr_mc.moveTo(x, y); qr_mc.lineTo(x + cs, y); qr_mc.lineTo(x + cs, y + cs); qr_mc.lineTo(x, y + cs); qr_mc.endFill() } } } return qr_mc }, setupTimingPattern: function() { for (var r = 8; r < this.moduleCount - 8; r++) { if (this.modules[r][6] != null) { continue } this.modules[r][6] = (r % 2 == 0) } for (var c = 8; c < this.moduleCount - 8; c++) { if (this.modules[6][c] != null) { continue } this.modules[6][c] = (c % 2 == 0) } }, setupPositionAdjustPattern: function() { var pos = QRUtil.getPatternPosition(this.typeNumber); for (var i = 0; i < pos.length; i++) { for (var j = 0; j < pos.length; j++) { var row = pos[i]; var col = pos[j]; if (this.modules[row][col] != null) { continue } for (var r = -2; r <= 2; r++) { for (var c = -2; c <= 2; c++) { if (r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0)) { this.modules[row + r][col + c] = !0 } else { this.modules[row + r][col + c] = !1 } } } } } }, setupTypeNumber: function(test) { var bits = QRUtil.getBCHTypeNumber(this.typeNumber); for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod } for (var i = 0; i < 18; i++) { var mod = (!test && ((bits >> i) & 1) == 1); this.modules[i % 3 + this.moduleCount - 8 - 3][Math.floor(i / 3)] = mod } }, setupTypeInfo: function(test, maskPattern) { var data = (this.errorCorrectLevel << 3) | maskPattern; var bits = QRUtil.getBCHTypeInfo(data); for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 6) { this.modules[i][8] = mod } else if (i < 8) { this.modules[i + 1][8] = mod } else { this.modules[this.moduleCount - 15 + i][8] = mod } } for (var i = 0; i < 15; i++) { var mod = (!test && ((bits >> i) & 1) == 1); if (i < 8) { this.modules[8][this.moduleCount - i - 1] = mod } else if (i < 9) { this.modules[8][15 - i - 1 + 1] = mod } else { this.modules[8][15 - i - 1] = mod } } this.modules[this.moduleCount - 8][8] = (!test) }, mapData: function(data, maskPattern) { var inc = -1; var row = this.moduleCount - 1; var bitIndex = 7; var byteIndex = 0; for (var col = this.moduleCount - 1; col > 0; col -= 2) { if (col == 6) col--; while (!0) { for (var c = 0; c < 2; c++) { if (this.modules[row][col - c] == null) { var dark = !1; if (byteIndex < data.length) { dark = (((data[byteIndex] >>> bitIndex) & 1) == 1) } var mask = QRUtil.getMask(maskPattern, row, col - c); if (mask) { dark = !dark } this.modules[row][col - c] = dark; bitIndex--; if (bitIndex == -1) { byteIndex++; bitIndex = 7 } } } row += inc; if (row < 0 || this.moduleCount <= row) { row -= inc; inc = -inc; break } } } } }; QRCodeModel.PAD0 = 0xEC; QRCodeModel.PAD1 = 0x11; QRCodeModel.createData = function(typeNumber, errorCorrectLevel, dataList) { var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel); var buffer = new QRBitBuffer(); for (var i = 0; i < dataList.length; i++) { var data = dataList[i]; buffer.put(data.mode, 4); buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber)); data.write(buffer) } var totalDataCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalDataCount += rsBlocks[i].dataCount } if (buffer.getLengthInBits() > totalDataCount * 8) { throw new Error("code length overflow. (" + buffer.getLengthInBits() + ">" + totalDataCount * 8 + ")") } if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) { buffer.put(0, 4) } while (buffer.getLengthInBits() % 8 != 0) { buffer.putBit(!1) } while (!0) { if (buffer.getLengthInBits() >= totalDataCount * 8) { break } buffer.put(QRCodeModel.PAD0, 8); if (buffer.getLengthInBits() >= totalDataCount * 8) { break } buffer.put(QRCodeModel.PAD1, 8) } return QRCodeModel.createBytes(buffer, rsBlocks) }; QRCodeModel.createBytes = function(buffer, rsBlocks) { var offset = 0; var maxDcCount = 0; var maxEcCount = 0; var dcdata = new Array(rsBlocks.length); var ecdata = new Array(rsBlocks.length); for (var r = 0; r < rsBlocks.length; r++) { var dcCount = rsBlocks[r].dataCount; var ecCount = rsBlocks[r].totalCount - dcCount; maxDcCount = Math.max(maxDcCount, dcCount); maxEcCount = Math.max(maxEcCount, ecCount); dcdata[r] = new Array(dcCount); for (var i = 0; i < dcdata[r].length; i++) { dcdata[r][i] = 0xff & buffer.buffer[i + offset] } offset += dcCount; var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount); var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1); var modPoly = rawPoly.mod(rsPoly); ecdata[r] = new Array(rsPoly.getLength() - 1); for (var i = 0; i < ecdata[r].length; i++) { var modIndex = i + modPoly.getLength() - ecdata[r].length; ecdata[r][i] = (modIndex >= 0) ? modPoly.get(modIndex) : 0 } } var totalCodeCount = 0; for (var i = 0; i < rsBlocks.length; i++) { totalCodeCount += rsBlocks[i].totalCount } var data = new Array(totalCodeCount); var index = 0; for (var i = 0; i < maxDcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < dcdata[r].length) { data[index++] = dcdata[r][i] } } } for (var i = 0; i < maxEcCount; i++) { for (var r = 0; r < rsBlocks.length; r++) { if (i < ecdata[r].length) { data[index++] = ecdata[r][i] } } } return data }; var QRMode = { MODE_NUMBER: 1 << 0, MODE_ALPHA_NUM: 1 << 1, MODE_8BIT_BYTE: 1 << 2, MODE_KANJI: 1 << 3 }; var QRErrorCorrectLevel = { L: 1, M: 0, Q: 3, H: 2 }; var QRMaskPattern = { PATTERN000: 0, PATTERN001: 1, PATTERN010: 2, PATTERN011: 3, PATTERN100: 4, PATTERN101: 5, PATTERN110: 6, PATTERN111: 7 }; var QRUtil = { PATTERN_POSITION_TABLE: [ [], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170] ], G15: (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0), G18: (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0), G15_MASK: (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1), getBCHTypeInfo: function(data) { var d = data << 10; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) { d ^= (QRUtil.G15 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15))) } return ((data << 10) | d) ^ QRUtil.G15_MASK }, getBCHTypeNumber: function(data) { var d = data << 12; while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) { d ^= (QRUtil.G18 << (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18))) } return (data << 12) | d }, getBCHDigit: function(data) { var digit = 0; while (data != 0) { digit++; data >>>= 1 } return digit }, getPatternPosition: function(typeNumber) { return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1] }, getMask: function(maskPattern, i, j) { switch (maskPattern) { case QRMaskPattern.PATTERN000: return (i + j) % 2 == 0; case QRMaskPattern.PATTERN001: return i % 2 == 0; case QRMaskPattern.PATTERN010: return j % 3 == 0; case QRMaskPattern.PATTERN011: return (i + j) % 3 == 0; case QRMaskPattern.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; case QRMaskPattern.PATTERN101: return (i * j) % 2 + (i * j) % 3 == 0; case QRMaskPattern.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 == 0; case QRMaskPattern.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 == 0; default: throw new Error("bad maskPattern:" + maskPattern) } }, getErrorCorrectPolynomial: function(errorCorrectLength) { var a = new QRPolynomial([1], 0); for (var i = 0; i < errorCorrectLength; i++) { a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0)) } return a }, getLengthInBits: function(mode, type) { if (1 <= type && type < 10) { switch (mode) { case QRMode.MODE_NUMBER: return 10; case QRMode.MODE_ALPHA_NUM: return 9; case QRMode.MODE_8BIT_BYTE: return 8; case QRMode.MODE_KANJI: