diff --git a/.gitignore b/.gitignore
index 3c3629e..2e513f1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,7 @@
node_modules
+**/.DS_Store
+**/*.js
+**/*.d.ts
+
+!qr.d.ts
+!rollup.config.js
diff --git a/Readme.md b/README.md
similarity index 64%
rename from Readme.md
rename to README.md
index 80f6b05..9eb6c4b 100644
--- a/Readme.md
+++ b/README.md
@@ -4,14 +4,16 @@ This is a very simple QR-Code generator that outputs a PNG-Buffer. It's written
## Usage
- var qr=require('qrpng');
- qr('this is a sample code', function(err, png) {
- // png contains the PNG as a buffer. You can write it to a file for example.
- });
+```
+ import qrcode from 'qrpng;
+
+ const uint8array = qrcode('my text for the code');
+ document.getElementById('qrimg').src = 'image/png;base64,' + btoa(String.fromCharCode.apply(null, uint8array));
+```
It has only one function:
- function qr(content[, scale], callback)
+ function generate(content[, scale])
scale is the pixel extent of a QR-Code data pixel.
diff --git a/lib/crc32.ts b/lib/crc32.ts
new file mode 100644
index 0000000..f15b87a
--- /dev/null
+++ b/lib/crc32.ts
@@ -0,0 +1,279 @@
+const CRC_TABLE = new Int32Array([
+ 0x00000000,
+ 0x77073096,
+ 0xee0e612c,
+ 0x990951ba,
+ 0x076dc419,
+ 0x706af48f,
+ 0xe963a535,
+ 0x9e6495a3,
+ 0x0edb8832,
+ 0x79dcb8a4,
+ 0xe0d5e91e,
+ 0x97d2d988,
+ 0x09b64c2b,
+ 0x7eb17cbd,
+ 0xe7b82d07,
+ 0x90bf1d91,
+ 0x1db71064,
+ 0x6ab020f2,
+ 0xf3b97148,
+ 0x84be41de,
+ 0x1adad47d,
+ 0x6ddde4eb,
+ 0xf4d4b551,
+ 0x83d385c7,
+ 0x136c9856,
+ 0x646ba8c0,
+ 0xfd62f97a,
+ 0x8a65c9ec,
+ 0x14015c4f,
+ 0x63066cd9,
+ 0xfa0f3d63,
+ 0x8d080df5,
+ 0x3b6e20c8,
+ 0x4c69105e,
+ 0xd56041e4,
+ 0xa2677172,
+ 0x3c03e4d1,
+ 0x4b04d447,
+ 0xd20d85fd,
+ 0xa50ab56b,
+ 0x35b5a8fa,
+ 0x42b2986c,
+ 0xdbbbc9d6,
+ 0xacbcf940,
+ 0x32d86ce3,
+ 0x45df5c75,
+ 0xdcd60dcf,
+ 0xabd13d59,
+ 0x26d930ac,
+ 0x51de003a,
+ 0xc8d75180,
+ 0xbfd06116,
+ 0x21b4f4b5,
+ 0x56b3c423,
+ 0xcfba9599,
+ 0xb8bda50f,
+ 0x2802b89e,
+ 0x5f058808,
+ 0xc60cd9b2,
+ 0xb10be924,
+ 0x2f6f7c87,
+ 0x58684c11,
+ 0xc1611dab,
+ 0xb6662d3d,
+ 0x76dc4190,
+ 0x01db7106,
+ 0x98d220bc,
+ 0xefd5102a,
+ 0x71b18589,
+ 0x06b6b51f,
+ 0x9fbfe4a5,
+ 0xe8b8d433,
+ 0x7807c9a2,
+ 0x0f00f934,
+ 0x9609a88e,
+ 0xe10e9818,
+ 0x7f6a0dbb,
+ 0x086d3d2d,
+ 0x91646c97,
+ 0xe6635c01,
+ 0x6b6b51f4,
+ 0x1c6c6162,
+ 0x856530d8,
+ 0xf262004e,
+ 0x6c0695ed,
+ 0x1b01a57b,
+ 0x8208f4c1,
+ 0xf50fc457,
+ 0x65b0d9c6,
+ 0x12b7e950,
+ 0x8bbeb8ea,
+ 0xfcb9887c,
+ 0x62dd1ddf,
+ 0x15da2d49,
+ 0x8cd37cf3,
+ 0xfbd44c65,
+ 0x4db26158,
+ 0x3ab551ce,
+ 0xa3bc0074,
+ 0xd4bb30e2,
+ 0x4adfa541,
+ 0x3dd895d7,
+ 0xa4d1c46d,
+ 0xd3d6f4fb,
+ 0x4369e96a,
+ 0x346ed9fc,
+ 0xad678846,
+ 0xda60b8d0,
+ 0x44042d73,
+ 0x33031de5,
+ 0xaa0a4c5f,
+ 0xdd0d7cc9,
+ 0x5005713c,
+ 0x270241aa,
+ 0xbe0b1010,
+ 0xc90c2086,
+ 0x5768b525,
+ 0x206f85b3,
+ 0xb966d409,
+ 0xce61e49f,
+ 0x5edef90e,
+ 0x29d9c998,
+ 0xb0d09822,
+ 0xc7d7a8b4,
+ 0x59b33d17,
+ 0x2eb40d81,
+ 0xb7bd5c3b,
+ 0xc0ba6cad,
+ 0xedb88320,
+ 0x9abfb3b6,
+ 0x03b6e20c,
+ 0x74b1d29a,
+ 0xead54739,
+ 0x9dd277af,
+ 0x04db2615,
+ 0x73dc1683,
+ 0xe3630b12,
+ 0x94643b84,
+ 0x0d6d6a3e,
+ 0x7a6a5aa8,
+ 0xe40ecf0b,
+ 0x9309ff9d,
+ 0x0a00ae27,
+ 0x7d079eb1,
+ 0xf00f9344,
+ 0x8708a3d2,
+ 0x1e01f268,
+ 0x6906c2fe,
+ 0xf762575d,
+ 0x806567cb,
+ 0x196c3671,
+ 0x6e6b06e7,
+ 0xfed41b76,
+ 0x89d32be0,
+ 0x10da7a5a,
+ 0x67dd4acc,
+ 0xf9b9df6f,
+ 0x8ebeeff9,
+ 0x17b7be43,
+ 0x60b08ed5,
+ 0xd6d6a3e8,
+ 0xa1d1937e,
+ 0x38d8c2c4,
+ 0x4fdff252,
+ 0xd1bb67f1,
+ 0xa6bc5767,
+ 0x3fb506dd,
+ 0x48b2364b,
+ 0xd80d2bda,
+ 0xaf0a1b4c,
+ 0x36034af6,
+ 0x41047a60,
+ 0xdf60efc3,
+ 0xa867df55,
+ 0x316e8eef,
+ 0x4669be79,
+ 0xcb61b38c,
+ 0xbc66831a,
+ 0x256fd2a0,
+ 0x5268e236,
+ 0xcc0c7795,
+ 0xbb0b4703,
+ 0x220216b9,
+ 0x5505262f,
+ 0xc5ba3bbe,
+ 0xb2bd0b28,
+ 0x2bb45a92,
+ 0x5cb36a04,
+ 0xc2d7ffa7,
+ 0xb5d0cf31,
+ 0x2cd99e8b,
+ 0x5bdeae1d,
+ 0x9b64c2b0,
+ 0xec63f226,
+ 0x756aa39c,
+ 0x026d930a,
+ 0x9c0906a9,
+ 0xeb0e363f,
+ 0x72076785,
+ 0x05005713,
+ 0x95bf4a82,
+ 0xe2b87a14,
+ 0x7bb12bae,
+ 0x0cb61b38,
+ 0x92d28e9b,
+ 0xe5d5be0d,
+ 0x7cdcefb7,
+ 0x0bdbdf21,
+ 0x86d3d2d4,
+ 0xf1d4e242,
+ 0x68ddb3f8,
+ 0x1fda836e,
+ 0x81be16cd,
+ 0xf6b9265b,
+ 0x6fb077e1,
+ 0x18b74777,
+ 0x88085ae6,
+ 0xff0f6a70,
+ 0x66063bca,
+ 0x11010b5c,
+ 0x8f659eff,
+ 0xf862ae69,
+ 0x616bffd3,
+ 0x166ccf45,
+ 0xa00ae278,
+ 0xd70dd2ee,
+ 0x4e048354,
+ 0x3903b3c2,
+ 0xa7672661,
+ 0xd06016f7,
+ 0x4969474d,
+ 0x3e6e77db,
+ 0xaed16a4a,
+ 0xd9d65adc,
+ 0x40df0b66,
+ 0x37d83bf0,
+ 0xa9bcae53,
+ 0xdebb9ec5,
+ 0x47b2cf7f,
+ 0x30b5ffe9,
+ 0xbdbdf21c,
+ 0xcabac28a,
+ 0x53b39330,
+ 0x24b4a3a6,
+ 0xbad03605,
+ 0xcdd70693,
+ 0x54de5729,
+ 0x23d967bf,
+ 0xb3667a2e,
+ 0xc4614ab8,
+ 0x5d681b02,
+ 0x2a6f2b94,
+ 0xb40bbe37,
+ 0xc30c8ea1,
+ 0x5a05df1b,
+ 0x2d02ef8d,
+]);
+
+export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Int8Array | Int16Array | Int32Array;
+
+export function signed(data: TypedArray) {
+ if (!ArrayBuffer.isView(data)) throw new Error("invalid view");
+ const bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
+ let crc = -1;
+ for (let byte of bytes.values()) {
+ crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8);
+ }
+ return crc ^ -1;
+}
+
+export function unsigned(data: TypedArray) {
+ return signed(data) >>> 0;
+}
+
+export function bytearray(data: TypedArray) {
+ const result = new Int32Array([signed(data)]);
+ return new Uint8Array(result.buffer, result.byteOffset, result.byteLength);
+}
diff --git a/lib/makepng.js b/lib/makepng.js
deleted file mode 100644
index 1ec2202..0000000
--- a/lib/makepng.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-** © 2013 by Philipp Dunkel
. Licensed under MIT License.
-*/
-
-module.exports = makepng;
-
-var crc32 = require('buffer-crc32');
-var zlib = require('zlib');
-
-function makepng(data, callback) {
- var width = data[0].length;
- var height = data.length;
- data = IDAT(data, function(err, data) {
- if(err) return callback(err);
- data = [
- header(),
- IHDR(0, 1, width, height),
- data,
- IEND()];
- data = Buffer.concat(data);
- callback(undefined, data);
- });
-}
-
-function header() {
- return Buffer('89504E470D0A1A0A', 'hex');
-}
-
-function IHDR(colortype, bitdepth, width, height) {
- var ihdr = Buffer(13);
- ihdr.writeUInt32BE(width, 0); // Width: 4 bytes
- ihdr.writeUInt32BE(height, 4); // Height: 4 bytes
- ihdr.writeUInt8(bitdepth, 8); // Bit depth: 1 byte
- ihdr.writeUInt8(colortype, 9); // Color type: 1 byte 0=grayscale
- ihdr.writeUInt8(0, 10); // Compression method: 1 byte
- ihdr.writeUInt8(0, 11); // Filter method: 1 byte
- ihdr.writeUInt8(0, 12); // Interlace method: 1 byte
- return chunkify('IHDR', ihdr);
-}
-
-function IDAT(data, callback) {
- data = data.map(function(line) {
- line = bitmap(line);
- line.unshift(0);
- return Buffer(line);
- });
- data = Buffer.concat(data);
- zlib.deflate(data, function(err, data) {
- if(err) return callback(err);
- callback(undefined, chunkify('IDAT', data));
- });
-}
-
-function bitmap(data) {
- var res = [];
- while(data.length) {
- res.push(bitmapChunk(data.slice(0, 8)));
- data = data.slice(8);
- }
- return res;
-}
-
-function bitmapChunk(dat) {
- /*jslint bitwise:true */
- var dbyte = 0;
- dat.forEach(function(bit, idx) {
- bit = !bit ? 0x01 : 0x00;
- dbyte = dbyte | (bit << (7 - idx));
- });
- return dbyte;
-}
-
-function IEND() {
- return chunkify('IEND', Buffer(0));
-}
-
-function chunkify(type, buf) {
- var len = bufInt32(buf.length);
- buf = Buffer.concat([Buffer(type.substr(0, 4), 'ascii'), buf], buf.length + 4);
- var crc = bufInt32(crc32.unsigned(buf));
- return Buffer.concat([len, buf, crc], len.length + buf.length + crc.length);
-}
-
-function bufInt32(val) {
- var res = Buffer(4);
- res.writeUInt32BE(val, 0);
- return res;
-}
diff --git a/lib/png.ts b/lib/png.ts
new file mode 100644
index 0000000..67a8cb8
--- /dev/null
+++ b/lib/png.ts
@@ -0,0 +1,115 @@
+import { unsigned as crc32 } from "./crc32";
+import { deflate } from "pako";
+
+const SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
+const HEADER = [
+ 0,
+ 0,
+ 0,
+ 13, // HEADER.length - IHDR & CRC
+ 0x49,
+ 0x48,
+ 0x44,
+ 0x52, // IHDR
+ 0,
+ 0,
+ 0,
+ 0, // width
+ 0,
+ 0,
+ 0,
+ 0, // height
+ 1,
+ 0, // bitdepth , colortype
+ 0,
+ 0,
+ 0, // compression, filter, interlace
+ 0,
+ 0,
+ 0,
+ 0, // CRC
+];
+const DATA = [
+ 0,
+ 0,
+ 0,
+ 0, // data.length
+ 0x49,
+ 0x44,
+ 0x41,
+ 0x54,
+];
+
+const FOOTER = [
+ 0,
+ 0,
+ 0,
+ 0, // FOOTER.length - IEND & CRC
+ 0x49,
+ 0x45,
+ 0x4e,
+ 0x44, // IEND
+ 0,
+ 0,
+ 0,
+ 0, // CRC
+];
+
+export function bitmap(pixels: boolean[][]) {
+ const { width, height, data } = compileData(pixels);
+
+ const result = new ArrayBuffer(SIGNATURE.length + HEADER.length + DATA.length + (data.length + 4) + FOOTER.length);
+
+ let baseOffset = 0;
+
+ new Uint8Array(result, baseOffset, SIGNATURE.length).set(SIGNATURE);
+ baseOffset = SIGNATURE.length;
+
+ new Uint8Array(result, baseOffset, HEADER.length).set(HEADER);
+ setUint32(result, baseOffset + 8, width);
+ setUint32(result, baseOffset + 12, height);
+ setUint32(result, baseOffset + HEADER.length - 4, crc32(new Uint8Array(result, baseOffset + 4, HEADER.length - 8)));
+ baseOffset += HEADER.length;
+
+ new Uint8Array(result, baseOffset, DATA.length).set(DATA);
+ setUint32(result, baseOffset, data.length);
+ new Uint8Array(result, baseOffset + DATA.length, data.length).set(data);
+ setUint32(result, baseOffset + DATA.length + data.byteLength, crc32(new Uint8Array(result, baseOffset + 4, DATA.length + data.byteLength + 4 - 8)));
+ baseOffset += DATA.length + data.byteLength + 4;
+
+ new Uint8Array(result, baseOffset, FOOTER.length).set(FOOTER);
+ setUint32(result, baseOffset + FOOTER.length - 4, crc32(new Uint8Array(result, baseOffset + 4, FOOTER.length - 8)));
+
+ return new Uint8Array(result, 0, result.byteLength);
+}
+
+function setUint32(buffer: ArrayBuffer, offset: number, value: number) {
+ const view = new DataView(buffer, offset, 4);
+ view.setUint32(0, value, false);
+}
+
+function compileData(data: boolean[][]): { width: number; height: number; data: Uint8Array } {
+ console.error(printmap(data));
+ const height = Math.ceil(data.length / 8) * 8;
+ const width = Math.ceil(data[0].length / 8) * 8;
+ const buffer = new Uint8Array(((width + 1) * height) / 8);
+
+ let byteOff = 0;
+ for (let line = 0; line < height; line++) {
+ buffer[byteOff] = 0; // filter-type for scanline
+ byteOff++;
+ for (let off = 0; off < width; off += 8) {
+ const linedata = data[line] || [];
+ const byte = (!linedata[off + 0] ? 0b10_00_00_00 : 0) | (!linedata[off + 1] ? 0b01_00_00_00 : 0) | (!linedata[off + 2] ? 0b00_10_00_00 : 0) | (!linedata[off + 3] ? 0b00_01_00_00 : 0) | (!linedata[off + 4] ? 0b00_00_10_00 : 0) | (!linedata[off + 5] ? 0b00_00_01_00 : 0) | (!linedata[off + 6] ? 0b00_00_00_10 : 0) | (!linedata[off + 7] ? 0b00_00_00_01 : 0);
+ buffer[byteOff] = byte;
+ byteOff++;
+ }
+ }
+
+ const result = deflate(buffer);
+ return { width, height, data: result };
+}
+
+function printmap(data: boolean[][]) {
+ return data.map((l) => l.map((p) => (p ? "*" : " ")).join("")).join("\n");
+}
diff --git a/lib/qr.ts b/lib/qr.ts
new file mode 100644
index 0000000..e431bc1
--- /dev/null
+++ b/lib/qr.ts
@@ -0,0 +1,56 @@
+import { QRCode } from "./qr/code";
+import { bitmap } from "./png";
+
+function generate(text: string, scale: number = 8): Uint8Array {
+ if (text.length > 1273) throw new Error("text too long");
+ const qr = new QRCode(level(text), 2);
+ qr.addData(text);
+ qr.make();
+ const pixels = code(qr, scale);
+ return bitmap(pixels);
+}
+
+export default generate;
+
+function code(qr: QRCode, scale: number = 1) {
+ var res: boolean[][] = [];
+ var mods = qr.getModuleCount();
+
+ for (let cnt = 3; cnt; cnt--) for (let cnt = scale; cnt; cnt--) res.push(new Array((mods + 2 * 3) * scale).fill(false));
+
+ for (let idx = 0; idx < mods; idx += 1) {
+ const lp = line(qr, idx, scale);
+ res.push(...new Array(scale).fill(lp));
+ }
+
+ for (let cnt = 3; cnt; cnt--) for (let cnt = scale; cnt; cnt--) res.push(new Array((mods + 2 * 3) * scale).fill(false));
+
+ return res;
+}
+
+function line(qr: QRCode, l: number, scale: number) {
+ var mods = qr.getModuleCount();
+ var res: boolean[] = [];
+
+ for (let cnt = 3; cnt; cnt--) res.push(...new Array(scale).fill(false));
+
+ for (let idx = 0; idx < mods; idx += 1) {
+ res.push(...new Array(scale).fill(qr.isDark(l, idx)));
+ }
+
+ for (let cnt = 3; cnt; cnt--) res.push(...new Array(scale).fill(false));
+
+ return res;
+}
+
+var levels = [7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194, 220, 250, 280, 310, 338, 382, 403, 439, 461, 511, 535, 593, 625, 658, 698, 742, 790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273];
+
+function level(text: string): number {
+ var res = 9999;
+ levels.forEach(function (max, lev) {
+ if (max < text.length) return;
+ res = Math.min(lev, res);
+ });
+ if (res >= levels.length) throw new Error("text too long (max: " + levels[levels.length - 1] + ")");
+ return res + 1;
+}
diff --git a/lib/qr/bitbuffer.ts b/lib/qr/bitbuffer.ts
new file mode 100644
index 0000000..d89ddd3
--- /dev/null
+++ b/lib/qr/bitbuffer.ts
@@ -0,0 +1,27 @@
+export class QRBitBuffer {
+ public buffer: number[] = [];
+ public length: number = 0;
+
+ get(index: number) {
+ var bufIndex = Math.floor(index / 8);
+ return ((this.buffer[bufIndex] >>> (7 - (index % 8))) & 1) == 1;
+ }
+ put(num: number, length: number) {
+ for (var i = 0; i < length; i++) {
+ this.putBit(((num >>> (length - i - 1)) & 1) == 1);
+ }
+ }
+ get bitLength() {
+ return this.length;
+ }
+ putBit(bit: boolean) {
+ var bufIndex = Math.floor(this.length / 8);
+ if (this.buffer.length <= bufIndex) {
+ this.buffer.push(0);
+ }
+ if (bit) {
+ this.buffer[bufIndex] |= 0x80 >>> this.length % 8;
+ }
+ this.length++;
+ }
+}
diff --git a/lib/qr/block.ts b/lib/qr/block.ts
new file mode 100644
index 0000000..2e9602a
--- /dev/null
+++ b/lib/qr/block.ts
@@ -0,0 +1,257 @@
+const RS_BLOCK_TABLE: number[][] = [
+ // L
+ // M
+ // Q
+ // H
+
+ // 1
+ [1, 26, 19],
+ [1, 26, 16],
+ [1, 26, 13],
+ [1, 26, 9],
+ // 2
+ [1, 44, 34],
+ [1, 44, 28],
+ [1, 44, 22],
+ [1, 44, 16],
+ // 3
+ [1, 70, 55],
+ [1, 70, 44],
+ [2, 35, 17],
+ [2, 35, 13],
+ // 4
+ [1, 100, 80],
+ [2, 50, 32],
+ [2, 50, 24],
+ [4, 25, 9],
+ // 5
+ [1, 134, 108],
+ [2, 67, 43],
+ [2, 33, 15, 2, 34, 16],
+ [2, 33, 11, 2, 34, 12],
+ // 6
+ [2, 86, 68],
+ [4, 43, 27],
+ [4, 43, 19],
+ [4, 43, 15],
+ // 7
+ [2, 98, 78],
+ [4, 49, 31],
+ [2, 32, 14, 4, 33, 15],
+ [4, 39, 13, 1, 40, 14],
+ // 8
+ [2, 121, 97],
+ [2, 60, 38, 2, 61, 39],
+ [4, 40, 18, 2, 41, 19],
+ [4, 40, 14, 2, 41, 15],
+ // 9
+ [2, 146, 116],
+ [3, 58, 36, 2, 59, 37],
+ [4, 36, 16, 4, 37, 17],
+ [4, 36, 12, 4, 37, 13],
+ // 10
+ [2, 86, 68, 2, 87, 69],
+ [4, 69, 43, 1, 70, 44],
+ [6, 43, 19, 2, 44, 20],
+ [6, 43, 15, 2, 44, 16],
+ //NOTE added by Ryan Day.to make greater than version 10 qrcodes
+ // this table starts on page 40 of the spec PDF. google ISO/IEC 18004
+ // 11
+ [4, 101, 81],
+ [1, 80, 50, 4, 81, 51],
+ [4, 50, 22, 4, 51, 23],
+ [3, 36, 12, 8, 37, 13],
+ //12
+ [2, 116, 92, 2, 117, 93],
+ [6, 58, 36, 2, 59, 37],
+ [4, 46, 20, 6, 47, 21],
+ [7, 42, 14, 4, 43, 15],
+ //13
+ [4, 133, 107],
+ [8, 59, 37, 1, 60, 38],
+ [8, 44, 20, 4, 45, 21],
+ [12, 33, 11, 4, 34, 12],
+ //14
+ [3, 145, 115, 1, 146, 116],
+ [4, 64, 40, 5, 65, 41],
+ [11, 36, 16, 5, 37, 17],
+ [11, 36, 12, 5, 37, 13],
+ //15
+ [5, 109, 87, 1, 110, 88],
+ [5, 65, 41, 5, 66, 42],
+ [5, 54, 24, 7, 55, 25],
+ [11, 36, 12, 7, 37, 13],
+ //16
+ [5, 122, 98, 1, 123, 99],
+ [7, 73, 45, 3, 74, 46],
+ [15, 43, 19, 2, 44, 20],
+ [3, 45, 15, 13, 46, 16],
+ //17
+ [1, 135, 107, 5, 136, 108],
+ [10, 74, 46, 1, 75, 47],
+ [1, 50, 22, 15, 51, 23],
+ [2, 42, 14, 17, 43, 15],
+ //18
+ [5, 150, 120, 1, 151, 121],
+ [9, 69, 43, 4, 70, 44],
+ [17, 50, 22, 1, 51, 23],
+ [2, 42, 14, 19, 43, 15],
+ //19
+ [3, 141, 113, 4, 142, 114],
+ [3, 70, 44, 11, 71, 45],
+ [17, 47, 21, 4, 48, 22],
+ [9, 39, 13, 16, 40, 14],
+ //20
+ [3, 135, 107, 5, 136, 108],
+ [3, 67, 41, 13, 68, 42],
+ [15, 54, 24, 5, 55, 25],
+ [15, 43, 15, 10, 44, 16],
+ //21
+ [4, 144, 116, 4, 145, 117],
+ [17, 68, 42],
+ [17, 50, 22, 6, 51, 23],
+ [19, 46, 16, 6, 47, 17],
+ //22
+ [2, 139, 111, 7, 140, 112],
+ [17, 74, 46],
+ [7, 54, 24, 16, 55, 25],
+ [34, 37, 13],
+ //23
+ [4, 151, 121, 5, 152, 122],
+ [4, 75, 47, 14, 76, 48],
+ [11, 54, 24, 14, 55, 25],
+ [16, 45, 15, 14, 46, 16],
+ //24
+ [6, 147, 117, 4, 148, 118],
+ [6, 73, 45, 14, 74, 46],
+ [11, 54, 24, 16, 55, 25],
+ [30, 46, 16, 2, 47, 17],
+ //25
+ [8, 132, 106, 4, 133, 107],
+ [8, 75, 47, 13, 76, 48],
+ [7, 54, 24, 22, 55, 25],
+ [22, 45, 15, 13, 46, 16],
+ //26
+ [10, 142, 114, 2, 143, 115],
+ [19, 74, 46, 4, 75, 47],
+ [28, 50, 22, 6, 51, 23],
+ [33, 46, 16, 4, 47, 17],
+ //27
+ [8, 152, 122, 4, 153, 123],
+ [22, 73, 45, 3, 74, 46],
+ [8, 53, 23, 26, 54, 24],
+ [12, 45, 15, 28, 46, 16],
+ //28
+ [3, 147, 117, 10, 148, 118],
+ [3, 73, 45, 23, 74, 46],
+ [4, 54, 24, 31, 55, 25],
+ [11, 45, 15, 31, 46, 16],
+ //29
+ [7, 146, 116, 7, 147, 117],
+ [21, 73, 45, 7, 74, 46],
+ [1, 53, 23, 37, 54, 24],
+ [19, 45, 15, 26, 46, 16],
+ //30
+ [5, 145, 115, 10, 146, 116],
+ [19, 75, 47, 10, 76, 48],
+ [15, 54, 24, 25, 55, 25],
+ [23, 45, 15, 25, 46, 16],
+ //31
+ [13, 145, 115, 3, 146, 116],
+ [2, 74, 46, 29, 75, 47],
+ [42, 54, 24, 1, 55, 25],
+ [23, 45, 15, 28, 46, 16],
+ //32
+ [17, 145, 115],
+ [10, 74, 46, 23, 75, 47],
+ [10, 54, 24, 35, 55, 25],
+ [19, 45, 15, 35, 46, 16],
+ //33
+ [17, 145, 115, 1, 146, 116],
+ [14, 74, 46, 21, 75, 47],
+ [29, 54, 24, 19, 55, 25],
+ [11, 45, 15, 46, 46, 16],
+ //34
+ [13, 145, 115, 6, 146, 116],
+ [14, 74, 46, 23, 75, 47],
+ [44, 54, 24, 7, 55, 25],
+ [59, 46, 16, 1, 47, 17],
+ //35
+ [12, 151, 121, 7, 152, 122],
+ [12, 75, 47, 26, 76, 48],
+ [39, 54, 24, 14, 55, 25],
+ [22, 45, 15, 41, 46, 16],
+ //36
+ [6, 151, 121, 14, 152, 122],
+ [6, 75, 47, 34, 76, 48],
+ [46, 54, 24, 10, 55, 25],
+ [2, 45, 15, 64, 46, 16],
+ //37
+ [17, 152, 122, 4, 153, 123],
+ [29, 74, 46, 14, 75, 47],
+ [49, 54, 24, 10, 55, 25],
+ [24, 45, 15, 46, 46, 16],
+ //38
+ [4, 152, 122, 18, 153, 123],
+ [13, 74, 46, 32, 75, 47],
+ [48, 54, 24, 14, 55, 25],
+ [42, 45, 15, 32, 46, 16],
+ //39
+ [20, 147, 117, 4, 148, 118],
+ [40, 75, 47, 7, 76, 48],
+ [43, 54, 24, 22, 55, 25],
+ [10, 45, 15, 67, 46, 16],
+ //40
+ [19, 148, 118, 6, 149, 119],
+ [18, 75, 47, 31, 76, 48],
+ [34, 54, 24, 34, 55, 25],
+ [20, 45, 15, 61, 46, 16],
+];
+
+import { ErrorCorrectLevel } from "./const";
+
+export class QRRSBlock {
+ constructor(totalCount: number, dataCount: number) {
+ this.totalCount = totalCount;
+ this.dataCount = dataCount;
+ }
+ public totalCount: number;
+ public dataCount: number;
+ static getRSBlocks(typeNumber: number, errorCorrectLevel: number) {
+ var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
+
+ if (rsBlock == undefined) {
+ throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
+ }
+
+ var length = rsBlock.length / 3;
+
+ var list = new Array();
+
+ for (var i = 0; i < length; i++) {
+ var count = rsBlock[i * 3 + 0];
+ var totalCount = rsBlock[i * 3 + 1];
+ var dataCount = rsBlock[i * 3 + 2];
+
+ for (var j = 0; j < count; j++) {
+ list.push(new QRRSBlock(totalCount, dataCount));
+ }
+ }
+
+ return list;
+ }
+ static getRsBlockTable(typeNumber: number, errorCorrectLevel: number) {
+ switch (errorCorrectLevel) {
+ case ErrorCorrectLevel.L:
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
+ case ErrorCorrectLevel.M:
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
+ case ErrorCorrectLevel.Q:
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
+ case ErrorCorrectLevel.H:
+ return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
+ default:
+ return undefined;
+ }
+ }
+}
diff --git a/lib/qr/byte.ts b/lib/qr/byte.ts
new file mode 100644
index 0000000..df838ae
--- /dev/null
+++ b/lib/qr/byte.ts
@@ -0,0 +1,19 @@
+import { Mode } from "./const";
+import { QRBitBuffer } from "./bitbuffer";
+
+export class QR8bitByte {
+ constructor(data: string) {
+ this.data = data;
+ }
+ private data: string;
+ public readonly mode = Mode.MODE_8BIT_BYTE;
+ public get length() {
+ return this.data.length;
+ }
+ write(buffer: QRBitBuffer) {
+ for (var i = 0; i < this.data.length; i++) {
+ // not JIS ...
+ buffer.put(this.data.charCodeAt(i), 8);
+ }
+ }
+}
diff --git a/lib/qr/code.ts b/lib/qr/code.ts
new file mode 100644
index 0000000..1da6bfc
--- /dev/null
+++ b/lib/qr/code.ts
@@ -0,0 +1,342 @@
+import * as QRUtil from "./utils";
+import { Grid } from "./grid";
+import { QRPolynomial } from "./polynomial";
+import { QRRSBlock } from "./block";
+import { QRBitBuffer } from "./bitbuffer";
+import { QR8bitByte } from "./byte";
+
+export class QRCode {
+ constructor(typeNumber: number, errorCorrectLevel: number) {
+ this.typeNumber = typeNumber;
+ this.errorCorrectLevel = errorCorrectLevel;
+ }
+ private typeNumber: number;
+ private errorCorrectLevel: number;
+ private modules: Grid = new Grid(0);
+ private moduleCount: number = 0;
+ private dataCache?: Uint32Array;
+ private dataList: QR8bitByte[] = [];
+
+ public addData(data: string): void {
+ let newData = new QR8bitByte(data);
+ this.dataList.push(newData);
+ this.dataCache = undefined;
+ }
+
+ isDark(row: number, col: number) {
+ if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
+ throw new Error(row + "," + col);
+ }
+ return this.modules.get(row, col);
+ }
+
+ getModuleCount() {
+ return this.moduleCount;
+ }
+
+ make() {
+ this.makeImpl(false, this.getBestMaskPattern());
+ }
+
+ makeImpl(test, maskPattern) {
+ this.moduleCount = this.typeNumber * 4 + 17;
+ this.modules = new Grid(this.moduleCount);
+
+ 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 = createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
+ }
+
+ this.mapData(this.dataCache, maskPattern);
+ }
+
+ setupPositionProbePattern(row: number, col: number) {
+ 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.set(row + r, col + c, true);
+ } else {
+ this.modules.set(row + r, col + c, false);
+ }
+ }
+ }
+ }
+
+ getBestMaskPattern() {
+ var minLostPoint = 0;
+ var pattern = 0;
+
+ for (var i = 0; i < 8; i++) {
+ this.makeImpl(true, i);
+
+ var lostPoint = QRUtil.getLostPoint(this);
+
+ if (i == 0 || minLostPoint > lostPoint) {
+ minLostPoint = lostPoint;
+ pattern = i;
+ }
+ }
+
+ return pattern;
+ }
+
+ setupTimingPattern() {
+ for (var r = 8; r < this.moduleCount - 8; r++) {
+ if (this.modules.get(r, 6) !== undefined) {
+ continue;
+ }
+ this.modules.set(r, 6, r % 2 == 0);
+ }
+
+ for (var c = 8; c < this.moduleCount - 8; c++) {
+ if (this.modules.get(6, c) !== undefined) {
+ continue;
+ }
+ this.modules.set(6, c, c % 2 == 0);
+ }
+ }
+
+ setupPositionAdjustPattern() {
+ let 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.get(row, col) !== undefined) {
+ 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.set(row + r, col + c, true);
+ } else {
+ this.modules.set(row + r, col + c, false);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ setupTypeNumber(test) {
+ var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
+
+ for (var i = 0; i < 18; i++) {
+ var mod = !test && ((bits >> i) & 1) == 1;
+ this.modules.set(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.set((i % 3) + this.moduleCount - 8 - 3, Math.floor(i / 3), mod);
+ }
+ }
+
+ setupTypeInfo(test, maskPattern) {
+ var data = (this.errorCorrectLevel << 3) | maskPattern;
+ var bits = QRUtil.getBCHTypeInfo(data);
+
+ // vertical
+ for (var i = 0; i < 15; i++) {
+ var mod = !test && ((bits >> i) & 1) == 1;
+
+ if (i < 6) {
+ this.modules.set(i, 8, mod);
+ } else if (i < 8) {
+ this.modules.set(i + 1, 8, mod);
+ } else {
+ this.modules.set(this.moduleCount - 15 + i, 8, mod);
+ }
+ }
+
+ // horizontal
+ for (var i = 0; i < 15; i++) {
+ var mod = !test && ((bits >> i) & 1) == 1;
+
+ if (i < 8) {
+ this.modules.set(8, this.moduleCount - i - 1, mod);
+ } else if (i < 9) {
+ this.modules.set(8, 15 - i - 1 + 1, mod);
+ } else {
+ this.modules.set(8, 15 - i - 1, mod);
+ }
+ }
+
+ // fixed module
+ this.modules.set(this.moduleCount - 8, 8, !test);
+ }
+
+ mapData(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 (true) {
+ for (var c = 0; c < 2; c++) {
+ if (this.modules.get(row, col - c) == undefined) {
+ var dark = false;
+
+ if (byteIndex < data.length) {
+ dark = ((data[byteIndex] >>> bitIndex) & 1) == 1;
+ }
+
+ var mask = QRUtil.getMask(maskPattern, row, col - c);
+
+ if (mask) {
+ dark = !dark;
+ }
+
+ this.modules.set(row, col - c, dark);
+ bitIndex--;
+
+ if (bitIndex == -1) {
+ byteIndex++;
+ bitIndex = 7;
+ }
+ }
+ }
+
+ row += inc;
+
+ if (row < 0 || this.moduleCount <= row) {
+ row -= inc;
+ inc = -inc;
+ break;
+ }
+ }
+ }
+ }
+}
+
+const PAD0 = 0xec;
+const PAD1 = 0x11;
+
+function createData(typeNumber: number, errorCorrectLevel: number, dataList: QR8bitByte[]) {
+ 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.length, QRUtil.getLengthInBits(data.mode, typeNumber));
+ data.write(buffer);
+ }
+
+ // calc num max data.
+ var totalDataCount = 0;
+ for (var i = 0; i < rsBlocks.length; i++) {
+ totalDataCount += rsBlocks[i].dataCount;
+ }
+
+ if (buffer.bitLength > totalDataCount * 8) {
+ throw new Error("code length overflow. (" + buffer.bitLength + ">" + totalDataCount * 8 + ")");
+ }
+
+ // end code
+ if (buffer.bitLength + 4 <= totalDataCount * 8) {
+ buffer.put(0, 4);
+ }
+
+ // padding
+ while (buffer.bitLength % 8 != 0) {
+ buffer.putBit(false);
+ }
+
+ // padding
+ while (true) {
+ if (buffer.bitLength >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(PAD0, 8);
+
+ if (buffer.bitLength >= totalDataCount * 8) {
+ break;
+ }
+ buffer.put(PAD1, 8);
+ }
+
+ return createBytes(buffer, rsBlocks);
+}
+
+function createBytes(buffer: QRBitBuffer, rsBlocks: QRRSBlock[]): Uint32Array {
+ 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.length - 1);
+
+ var modPoly = rawPoly.mod(rsPoly);
+ ecdata[r] = new Array(rsPoly.length - 1);
+ for (var i = 0; i < ecdata[r].length; i++) {
+ var modIndex = i + modPoly.length - 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 Uint32Array(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;
+}
diff --git a/lib/qr/const.ts b/lib/qr/const.ts
new file mode 100644
index 0000000..4bf1e95
--- /dev/null
+++ b/lib/qr/const.ts
@@ -0,0 +1,22 @@
+export const Mode = {
+ MODE_NUMBER: 1 << 0,
+ MODE_ALPHA_NUM: 1 << 1,
+ MODE_8BIT_BYTE: 1 << 2,
+ MODE_KANJI: 1 << 3,
+};
+export const ErrorCorrectLevel = {
+ L: 1,
+ M: 0,
+ Q: 3,
+ H: 2,
+};
+export const MaskPattern = {
+ PATTERN000: 0,
+ PATTERN001: 1,
+ PATTERN010: 2,
+ PATTERN011: 3,
+ PATTERN100: 4,
+ PATTERN101: 5,
+ PATTERN110: 6,
+ PATTERN111: 7,
+};
diff --git a/lib/qr/grid.ts b/lib/qr/grid.ts
new file mode 100644
index 0000000..f0aa703
--- /dev/null
+++ b/lib/qr/grid.ts
@@ -0,0 +1,38 @@
+export class Grid {
+ constructor(rows: number, cols: number = rows) {
+ this.rowCount = rows;
+ this.colCount = cols;
+ }
+ private dataHash: { [key: string]: T } = {};
+ private rowCount: number = 0;
+ private colCount: number = 0;
+ public get rows() {
+ return this.rowCount;
+ }
+ public get columns() {
+ return this, this.colCount;
+ }
+ public get(row: number, col: number): T | undefined {
+ return this.dataHash[`${row}/${col}`];
+ }
+ public set(row: number, col: number, val: T) {
+ this.dataHash[`${row}/${col}`] = val;
+ }
+ public has(row: number, col: number): boolean {
+ return "undefined" !== typeof this.get(row, col);
+ }
+ public delete(row: number, col: number) {
+ delete this.dataHash[`${row}/${col}`];
+ }
+ public get data() {
+ const data = [];
+ for (let row = 0; row < this.rows; row++) {
+ const rowdata: (T | undefined)[] = [];
+ data.push(rowdata);
+ for (let col = 0; col < this.columns; col++) {
+ rowdata.push(this.get(row, col));
+ }
+ }
+ return data;
+ }
+}
diff --git a/lib/qr/math.ts b/lib/qr/math.ts
new file mode 100644
index 0000000..bcc76cc
--- /dev/null
+++ b/lib/qr/math.ts
@@ -0,0 +1,18 @@
+const EXP_TABLE: number[] = new Array(256);
+const LOG_TABLE: number[] = new Array(256);
+for (var i = 0; i < 8; i++) EXP_TABLE[i] = 1 << i;
+for (var i = 8; i < 256; i++) EXP_TABLE[i] = EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8];
+for (var i = 0; i < 255; i++) LOG_TABLE[EXP_TABLE[i]] = i;
+
+export function glog(n: number) {
+ if (n < 1) {
+ throw new Error("glog(" + n + ")");
+ }
+ return LOG_TABLE[n];
+}
+
+export function gexp(n: number) {
+ while (n < 0) n += 255;
+ while (n >= 256) n -= 255;
+ return EXP_TABLE[n];
+}
diff --git a/lib/qr/polynomial.ts b/lib/qr/polynomial.ts
new file mode 100644
index 0000000..dfc7832
--- /dev/null
+++ b/lib/qr/polynomial.ts
@@ -0,0 +1,51 @@
+import * as QRMath from "./math";
+
+export class QRPolynomial {
+ constructor(num: number[], shift: number) {
+ if (num.length == undefined) {
+ throw new Error(num.length + "/" + shift);
+ }
+
+ let offset = 0;
+ while (offset < num.length && num[offset] == 0) {
+ offset++;
+ }
+
+ this.num = new Array(num.length - offset + shift);
+ for (var i = 0; i < num.length - offset; i++) {
+ this.num[i] = num[i + offset];
+ }
+ }
+ private num: number[];
+
+ get length() {
+ return this.num.length;
+ }
+ get(index: number): number {
+ return this.num[index];
+ }
+ multiply(e: QRPolynomial): QRPolynomial {
+ let num = new Array(this.length + e.length - 1);
+
+ for (let i = 0; i < this.length; i++) {
+ for (let j = 0; j < e.length; j++) {
+ num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
+ }
+ }
+ return new QRPolynomial(num, 0);
+ }
+ mod(e: QRPolynomial): QRPolynomial {
+ if (this.length - e.length < 0) {
+ return this;
+ }
+
+ let ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
+ let num = new Array(this.length);
+
+ for (let i = 0; i < this.length; i++) num[i] = this.get(i);
+ for (let i = 0; i < e.length; i++) num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
+
+ // recursive call
+ return new QRPolynomial(num, 0).mod(e);
+ }
+}
diff --git a/lib/qr/utils.ts b/lib/qr/utils.ts
new file mode 100644
index 0000000..f318a86
--- /dev/null
+++ b/lib/qr/utils.ts
@@ -0,0 +1,256 @@
+import { QRPolynomial } from "./polynomial";
+import { MaskPattern, Mode } from "./const";
+import * as QRMath from "./math";
+import { QRCode } from "./code";
+
+const 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],
+];
+
+const G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
+const G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
+const G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
+
+export function getBCHTypeInfo(data: number) {
+ var d = data << 10;
+ while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
+ d ^= G15 << (getBCHDigit(d) - getBCHDigit(G15));
+ }
+ return ((data << 10) | d) ^ G15_MASK;
+}
+
+export function getBCHTypeNumber(data: number) {
+ var d = data << 12;
+ while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
+ d ^= G18 << (getBCHDigit(d) - getBCHDigit(G18));
+ }
+ return (data << 12) | d;
+}
+
+export function getBCHDigit(data: number) {
+ var digit = 0;
+
+ while (data != 0) {
+ digit++;
+ data >>>= 1;
+ }
+
+ return digit;
+}
+
+export function getPatternPosition(typeNumber: number) {
+ return PATTERN_POSITION_TABLE[typeNumber - 1] || [];
+}
+
+export function getMask(maskPattern: number, i: number, j: number) {
+ switch (maskPattern) {
+ case MaskPattern.PATTERN000:
+ return (i + j) % 2 == 0;
+ case MaskPattern.PATTERN001:
+ return i % 2 == 0;
+ case MaskPattern.PATTERN010:
+ return j % 3 == 0;
+ case MaskPattern.PATTERN011:
+ return (i + j) % 3 == 0;
+ case MaskPattern.PATTERN100:
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0;
+ case MaskPattern.PATTERN101:
+ return ((i * j) % 2) + ((i * j) % 3) == 0;
+ case MaskPattern.PATTERN110:
+ return (((i * j) % 2) + ((i * j) % 3)) % 2 == 0;
+ case MaskPattern.PATTERN111:
+ return (((i * j) % 3) + ((i + j) % 2)) % 2 == 0;
+
+ default:
+ throw new Error("bad maskPattern:" + maskPattern);
+ }
+}
+
+export function getErrorCorrectPolynomial(errorCorrectLength: number) {
+ 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;
+}
+
+export function getLengthInBits(mode: number, type: number) {
+ if (1 <= type && type < 10) {
+ // 1 - 9
+
+ switch (mode) {
+ case Mode.MODE_NUMBER:
+ return 10;
+ case Mode.MODE_ALPHA_NUM:
+ return 9;
+ case Mode.MODE_8BIT_BYTE:
+ return 8;
+ case Mode.MODE_KANJI:
+ return 8;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else if (type < 27) {
+ // 10 - 26
+
+ switch (mode) {
+ case Mode.MODE_NUMBER:
+ return 12;
+ case Mode.MODE_ALPHA_NUM:
+ return 11;
+ case Mode.MODE_8BIT_BYTE:
+ return 16;
+ case Mode.MODE_KANJI:
+ return 10;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else if (type < 41) {
+ // 27 - 40
+
+ switch (mode) {
+ case Mode.MODE_NUMBER:
+ return 14;
+ case Mode.MODE_ALPHA_NUM:
+ return 13;
+ case Mode.MODE_8BIT_BYTE:
+ return 16;
+ case Mode.MODE_KANJI:
+ return 12;
+ default:
+ throw new Error("mode:" + mode);
+ }
+ } else {
+ throw new Error("type:" + type);
+ }
+}
+
+export function getLostPoint(qrCode: QRCode) {
+ let moduleCount = qrCode.getModuleCount();
+
+ let lostPoint = 0;
+
+ // LEVEL1
+
+ for (var row = 0; row < moduleCount; row++) {
+ for (var col = 0; col < moduleCount; col++) {
+ var sameCount = 0;
+ var dark = qrCode.isDark(row, col);
+
+ for (var r = -1; r <= 1; r++) {
+ if (row + r < 0 || moduleCount <= row + r) {
+ continue;
+ }
+
+ for (var c = -1; c <= 1; c++) {
+ if (col + c < 0 || moduleCount <= col + c) {
+ continue;
+ }
+
+ if (r == 0 && c == 0) {
+ continue;
+ }
+
+ if (dark == qrCode.isDark(row + r, col + c)) {
+ sameCount++;
+ }
+ }
+ }
+
+ if (sameCount > 5) {
+ lostPoint += 3 + sameCount - 5;
+ }
+ }
+ }
+
+ // LEVEL2
+
+ for (var row = 0; row < moduleCount - 1; row++) {
+ for (var col = 0; col < moduleCount - 1; col++) {
+ var count = 0;
+ if (qrCode.isDark(row, col)) count++;
+ if (qrCode.isDark(row + 1, col)) count++;
+ if (qrCode.isDark(row, col + 1)) count++;
+ if (qrCode.isDark(row + 1, col + 1)) count++;
+ if (count == 0 || count == 4) {
+ lostPoint += 3;
+ }
+ }
+ }
+
+ // LEVEL3
+
+ for (var row = 0; row < moduleCount; row++) {
+ for (var col = 0; col < moduleCount - 6; col++) {
+ if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount - 6; row++) {
+ if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) {
+ lostPoint += 40;
+ }
+ }
+ }
+
+ // LEVEL4
+
+ var darkCount = 0;
+
+ for (var col = 0; col < moduleCount; col++) {
+ for (var row = 0; row < moduleCount; row++) {
+ if (qrCode.isDark(row, col)) {
+ darkCount++;
+ }
+ }
+ }
+
+ var ratio = Math.abs((100 * darkCount) / moduleCount / moduleCount - 50) / 5;
+ lostPoint += ratio * 10;
+
+ return lostPoint;
+}
diff --git a/lib/qrcode.js b/lib/qrcode.js
deleted file mode 100644
index 4d72841..0000000
--- a/lib/qrcode.js
+++ /dev/null
@@ -1,1194 +0,0 @@
-/**
- * QRCode for JavaScript
- *
- * modified by Ryan Day for nodejs support
- * Copyright (c) 2011 Ryan Day
- *
- * Licensed under the MIT license:
- * http://www.opensource.org/licenses/mit-license.php
- *
- * EXPORTS:
- * {
- * QRCode:QRCode
- * QRErrorCorrectLevel:QRErrorCorrectLevel
- * }
-//---------------------------------------------------------------------
-// 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
-//
-//---------------------------------------------------------------------
-*/
-
-//---------------------------------------------------------------------
-// QRCode
-//---------------------------------------------------------------------
-
-exports = module.exports = QRCode;
-exports.QRCode = QRCode;
-
-var QRDataArray = (typeof Uint32Array == 'undefined' ? Uint32Array : Array);
-
-function QRCode(typeNumber, errorCorrectLevel) {
- this.typeNumber = typeNumber;
- this.errorCorrectLevel = errorCorrectLevel;
- this.modules = null;
- this.moduleCount = 0;
- this.dataCache = null;
- this.dataList = new QRDataArray();
-}
-
-QRCode.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() {
- this.makeImpl(false, this.getBestMaskPattern());
- },
-
- makeImpl: function(test, maskPattern) {
-
- this.moduleCount = this.typeNumber * 4 + 17;
- this.modules = new QRDataArray(this.moduleCount);
-
- for(var row = 0; row < this.moduleCount; row++) {
-
- this.modules[row] = new QRDataArray(this.moduleCount);
-
- for(var col = 0; col < this.moduleCount; col++) {
- this.modules[row][col] = null; //(col + row) % 3;
- }
- }
-
- 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 = QRCode.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] = true;
- } else {
- this.modules[row + r][col + c] = false;
- }
- }
- }
- },
-
- getBestMaskPattern: function() {
-
- var minLostPoint = 0;
- var pattern = 0;
-
- for(var i = 0; i < 8; i++) {
-
- this.makeImpl(true, i);
-
- var lostPoint = QRUtil.getLostPoint(this);
-
- if(i == 0 || minLostPoint > lostPoint) {
- minLostPoint = lostPoint;
- pattern = i;
- }
- }
-
- return pattern;
- },
-
- 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);
- pos = pos || '';
- 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] = true;
- } else {
- this.modules[row + r][col + c] = false;
- }
- }
- }
- }
- }
- },
-
- 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);
-
- // vertical
- 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;
- }
- }
-
- // horizontal
- 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;
- }
- }
-
- // fixed module
- 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(true) {
-
- for(var c = 0; c < 2; c++) {
-
- if(this.modules[row][col - c] == null) {
-
- var dark = false;
-
- 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;
- }
- }
- }
-
- }
-
-};
-
-QRCode.PAD0 = 0xEC;
-QRCode.PAD1 = 0x11;
-
-QRCode.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);
- }
-
- // calc num max data.
- 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 + ")");
- }
-
- // end code
- if(buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
- buffer.put(0, 4);
- }
-
- // padding
- while(buffer.getLengthInBits() % 8 != 0) {
- buffer.putBit(false);
- }
-
- // padding
- while(true) {
-
- if(buffer.getLengthInBits() >= totalDataCount * 8) {
- break;
- }
- buffer.put(QRCode.PAD0, 8);
-
- if(buffer.getLengthInBits() >= totalDataCount * 8) {
- break;
- }
- buffer.put(QRCode.PAD1, 8);
- }
-
- return QRCode.createBytes(buffer, rsBlocks);
-};
-
-QRCode.createBytes = function(buffer, rsBlocks) {
-
- var offset = 0;
-
- var maxDcCount = 0;
- var maxEcCount = 0;
-
- var dcdata = new QRDataArray(rsBlocks.length);
- var ecdata = new QRDataArray(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 QRDataArray(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 QRDataArray(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 QRDataArray(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;
-
-};
-
-//---------------------------------------------------------------------
-// QR8bitByte
-//---------------------------------------------------------------------
-
-function QR8bitByte(data) {
- this.mode = QRMode.MODE_8BIT_BYTE;
- this.data = data;
-}
-
-QR8bitByte.prototype = {
-
- getLength: function(buffer) {
- return this.data.length;
- },
-
- write: function(buffer) {
- for(var i = 0; i < this.data.length; i++) {
- // not JIS ...
- buffer.put(this.data.charCodeAt(i), 8);
- }
- }
-};
-
-//---------------------------------------------------------------------
-// QRMode
-//---------------------------------------------------------------------
-
-var QRMode = {
- MODE_NUMBER: 1 << 0,
- MODE_ALPHA_NUM: 1 << 1,
- MODE_8BIT_BYTE: 1 << 2,
- MODE_KANJI: 1 << 3
-};
-
-//---------------------------------------------------------------------
-// QRErrorCorrectLevel
-//---------------------------------------------------------------------
-//exported
-
-var QRErrorCorrectLevel = exports.QRErrorCorrectLevel = {
- L: 1,
- M: 0,
- Q: 3,
- H: 2
-};
-
-//---------------------------------------------------------------------
-// QRMaskPattern
-//---------------------------------------------------------------------
-
-var QRMaskPattern = {
- PATTERN000: 0,
- PATTERN001: 1,
- PATTERN010: 2,
- PATTERN011: 3,
- PATTERN100: 4,
- PATTERN101: 5,
- PATTERN110: 6,
- PATTERN111: 7
-};
-
-//---------------------------------------------------------------------
-// QRUtil
-//---------------------------------------------------------------------
-
-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) {
-
- // 1 - 9
-
- 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:
- return 8;
- default:
- throw new Error("mode:" + mode);
- }
-
- } else if(type < 27) {
-
- // 10 - 26
-
- switch(mode) {
- case QRMode.MODE_NUMBER:
- return 12;
- case QRMode.MODE_ALPHA_NUM:
- return 11;
- case QRMode.MODE_8BIT_BYTE:
- return 16;
- case QRMode.MODE_KANJI:
- return 10;
- default:
- throw new Error("mode:" + mode);
- }
-
- } else if(type < 41) {
-
- // 27 - 40
-
- switch(mode) {
- case QRMode.MODE_NUMBER:
- return 14;
- case QRMode.MODE_ALPHA_NUM:
- return 13;
- case QRMode.MODE_8BIT_BYTE:
- return 16;
- case QRMode.MODE_KANJI:
- return 12;
- default:
- throw new Error("mode:" + mode);
- }
-
- } else {
- throw new Error("type:" + type);
- }
- },
-
- getLostPoint: function(qrCode) {
-
- var moduleCount = qrCode.getModuleCount();
-
- var lostPoint = 0;
-
- // LEVEL1
-
- for(var row = 0; row < moduleCount; row++) {
-
- for(var col = 0; col < moduleCount; col++) {
-
- var sameCount = 0;
- var dark = qrCode.isDark(row, col);
-
- for(var r = -1; r <= 1; r++) {
-
- if(row + r < 0 || moduleCount <= row + r) {
- continue;
- }
-
- for(var c = -1; c <= 1; c++) {
-
- if(col + c < 0 || moduleCount <= col + c) {
- continue;
- }
-
- if(r == 0 && c == 0) {
- continue;
- }
-
- if(dark == qrCode.isDark(row + r, col + c)) {
- sameCount++;
- }
- }
- }
-
- if(sameCount > 5) {
- lostPoint += (3 + sameCount - 5);
- }
- }
- }
-
- // LEVEL2
-
- for(var row = 0; row < moduleCount - 1; row++) {
- for(var col = 0; col < moduleCount - 1; col++) {
- var count = 0;
- if(qrCode.isDark(row, col)) count++;
- if(qrCode.isDark(row + 1, col)) count++;
- if(qrCode.isDark(row, col + 1)) count++;
- if(qrCode.isDark(row + 1, col + 1)) count++;
- if(count == 0 || count == 4) {
- lostPoint += 3;
- }
- }
- }
-
- // LEVEL3
-
- for(var row = 0; row < moduleCount; row++) {
- for(var col = 0; col < moduleCount - 6; col++) {
- if(qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) {
- lostPoint += 40;
- }
- }
- }
-
- for(var col = 0; col < moduleCount; col++) {
- for(var row = 0; row < moduleCount - 6; row++) {
- if(qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) {
- lostPoint += 40;
- }
- }
- }
-
- // LEVEL4
-
- var darkCount = 0;
-
- for(var col = 0; col < moduleCount; col++) {
- for(var row = 0; row < moduleCount; row++) {
- if(qrCode.isDark(row, col)) {
- darkCount++;
- }
- }
- }
-
- var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
- lostPoint += ratio * 10;
-
- return lostPoint;
- }
-
-};
-
-//---------------------------------------------------------------------
-// QRMath
-//---------------------------------------------------------------------
-
-var QRMath = {
-
- glog: function(n) {
-
- if(n < 1) {
- throw new Error("glog(" + n + ")");
- }
-
- return QRMath.LOG_TABLE[n];
- },
-
- gexp: function(n) {
-
- while(n < 0) {
- n += 255;
- }
-
- while(n >= 256) {
- n -= 255;
- }
-
- return QRMath.EXP_TABLE[n];
- },
-
- EXP_TABLE: new Array(256),
-
- LOG_TABLE: new Array(256)
-
-};
-
-for(var i = 0; i < 8; i++) {
- QRMath.EXP_TABLE[i] = 1 << i;
-}
-for(var i = 8; i < 256; i++) {
- QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
-}
-for(var i = 0; i < 255; i++) {
- QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
-}
-
-//---------------------------------------------------------------------
-// QRPolynomial
-//---------------------------------------------------------------------
-
-function QRPolynomial(num, shift) {
-
- if(num.length == undefined) {
- throw new Error(num.length + "/" + shift);
- }
-
- var offset = 0;
-
- while(offset < num.length && num[offset] == 0) {
- offset++;
- }
-
- this.num = new Array(num.length - offset + shift);
- for(var i = 0; i < num.length - offset; i++) {
- this.num[i] = num[i + offset];
- }
-}
-
-QRPolynomial.prototype = {
-
- get: function(index) {
- return this.num[index];
- },
-
- getLength: function() {
- return this.num.length;
- },
-
- multiply: function(e) {
-
- var num = new Array(this.getLength() + e.getLength() - 1);
-
- for(var i = 0; i < this.getLength(); i++) {
- for(var j = 0; j < e.getLength(); j++) {
- num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
- }
- }
-
- return new QRPolynomial(num, 0);
- },
-
- mod: function(e) {
-
- if(this.getLength() - e.getLength() < 0) {
- return this;
- }
-
- var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
-
- var num = new Array(this.getLength());
-
- for(var i = 0; i < this.getLength(); i++) {
- num[i] = this.get(i);
- }
-
- for(var i = 0; i < e.getLength(); i++) {
- num[i] ^= QRMath.gexp(QRMath.glog(e.get(i)) + ratio);
- }
-
- // recursive call
- return new QRPolynomial(num, 0).mod(e);
- }
-};
-
-//---------------------------------------------------------------------
-// QRRSBlock
-//---------------------------------------------------------------------
-
-function QRRSBlock(totalCount, dataCount) {
- this.totalCount = totalCount;
- this.dataCount = dataCount;
-}
-
-QRRSBlock.RS_BLOCK_TABLE = [
-// L
-// M
-// Q
-// H
-
-// 1
-[1, 26, 19],
- [1, 26, 16],
- [1, 26, 13],
- [1, 26, 9],
- // 2
- [1, 44, 34],
- [1, 44, 28],
- [1, 44, 22],
- [1, 44, 16],
- // 3
- [1, 70, 55],
- [1, 70, 44],
- [2, 35, 17],
- [2, 35, 13],
- // 4
- [1, 100, 80],
- [2, 50, 32],
- [2, 50, 24],
- [4, 25, 9],
- // 5
- [1, 134, 108],
- [2, 67, 43],
- [2, 33, 15, 2, 34, 16],
- [2, 33, 11, 2, 34, 12],
- // 6
- [2, 86, 68],
- [4, 43, 27],
- [4, 43, 19],
- [4, 43, 15],
- // 7
- [2, 98, 78],
- [4, 49, 31],
- [2, 32, 14, 4, 33, 15],
- [4, 39, 13, 1, 40, 14],
- // 8
- [2, 121, 97],
- [2, 60, 38, 2, 61, 39],
- [4, 40, 18, 2, 41, 19],
- [4, 40, 14, 2, 41, 15],
- // 9
- [2, 146, 116],
- [3, 58, 36, 2, 59, 37],
- [4, 36, 16, 4, 37, 17],
- [4, 36, 12, 4, 37, 13],
- // 10
- [2, 86, 68, 2, 87, 69],
- [4, 69, 43, 1, 70, 44],
- [6, 43, 19, 2, 44, 20],
- [6, 43, 15, 2, 44, 16]
- //NOTE added by Ryan Day.to make greater than version 10 qrcodes
- // this table starts on page 40 of the spec PDF. google ISO/IEC 18004
- // 11
- ,
- [4, 101, 81],
- [1, 80, 50, 4, 81, 51],
- [4, 50, 22, 4, 51, 23],
- [3, 36, 12, 8, 37, 13]
- //12
- ,
- [2, 116, 92, 2, 117, 93],
- [6, 58, 36, 2, 59, 37],
- [4, 46, 20, 6, 47, 21],
- [7, 42, 14, 4, 43, 15]
- //13
- ,
- [4, 133, 107],
- [8, 59, 37, 1, 60, 38],
- [8, 44, 20, 4, 45, 21],
- [12, 33, 11, 4, 34, 12]
- //14
- ,
- [3, 145, 115, 1, 146, 116],
- [4, 64, 40, 5, 65, 41],
- [11, 36, 16, 5, 37, 17],
- [11, 36, 12, 5, 37, 13]
- //15
- ,
- [5, 109, 87, 1, 110, 88],
- [5, 65, 41, 5, 66, 42],
- [5, 54, 24, 7, 55, 25],
- [11, 36, 12, 7, 37, 13]
- //16
- ,
- [5, 122, 98, 1, 123, 99],
- [7, 73, 45, 3, 74, 46],
- [15, 43, 19, 2, 44, 20],
- [3, 45, 15, 13, 46, 16]
- //17
- ,
- [1, 135, 107, 5, 136, 108],
- [10, 74, 46, 1, 75, 47],
- [1, 50, 22, 15, 51, 23],
- [2, 42, 14, 17, 43, 15]
- //18
- ,
- [5, 150, 120, 1, 151, 121],
- [9, 69, 43, 4, 70, 44],
- [17, 50, 22, 1, 51, 23],
- [2, 42, 14, 19, 43, 15]
- //19
- ,
- [3, 141, 113, 4, 142, 114],
- [3, 70, 44, 11, 71, 45],
- [17, 47, 21, 4, 48, 22],
- [9, 39, 13, 16, 40, 14]
- //20
- ,
- [3, 135, 107, 5, 136, 108],
- [3, 67, 41, 13, 68, 42],
- [15, 54, 24, 5, 55, 25],
- [15, 43, 15, 10, 44, 16]
- //21
- ,
- [4, 144, 116, 4, 145, 117],
- [17, 68, 42],
- [17, 50, 22, 6, 51, 23],
- [19, 46, 16, 6, 47, 17]
- //22
- ,
- [2, 139, 111, 7, 140, 112],
- [17, 74, 46],
- [7, 54, 24, 16, 55, 25],
- [34, 37, 13]
- //23
- ,
- [4, 151, 121, 5, 152, 122],
- [4, 75, 47, 14, 76, 48],
- [11, 54, 24, 14, 55, 25],
- [16, 45, 15, 14, 46, 16]
- //24
- ,
- [6, 147, 117, 4, 148, 118],
- [6, 73, 45, 14, 74, 46],
- [11, 54, 24, 16, 55, 25],
- [30, 46, 16, 2, 47, 17]
- //25
- ,
- [8, 132, 106, 4, 133, 107],
- [8, 75, 47, 13, 76, 48],
- [7, 54, 24, 22, 55, 25],
- [22, 45, 15, 13, 46, 16]
- //26
- ,
- [10, 142, 114, 2, 143, 115],
- [19, 74, 46, 4, 75, 47],
- [28, 50, 22, 6, 51, 23],
- [33, 46, 16, 4, 47, 17]
- //27
- ,
- [8, 152, 122, 4, 153, 123],
- [22, 73, 45, 3, 74, 46],
- [8, 53, 23, 26, 54, 24],
- [12, 45, 15, 28, 46, 16]
- //28
- ,
- [3, 147, 117, 10, 148, 118],
- [3, 73, 45, 23, 74, 46],
- [4, 54, 24, 31, 55, 25],
- [11, 45, 15, 31, 46, 16]
- //29
- ,
- [7, 146, 116, 7, 147, 117],
- [21, 73, 45, 7, 74, 46],
- [1, 53, 23, 37, 54, 24],
- [19, 45, 15, 26, 46, 16]
- //30
- ,
- [5, 145, 115, 10, 146, 116],
- [19, 75, 47, 10, 76, 48],
- [15, 54, 24, 25, 55, 25],
- [23, 45, 15, 25, 46, 16]
- //31
- ,
- [13, 145, 115, 3, 146, 116],
- [2, 74, 46, 29, 75, 47],
- [42, 54, 24, 1, 55, 25],
- [23, 45, 15, 28, 46, 16]
- //32
- ,
- [17, 145, 115],
- [10, 74, 46, 23, 75, 47],
- [10, 54, 24, 35, 55, 25],
- [19, 45, 15, 35, 46, 16]
- //33
- ,
- [17, 145, 115, 1, 146, 116],
- [14, 74, 46, 21, 75, 47],
- [29, 54, 24, 19, 55, 25],
- [11, 45, 15, 46, 46, 16]
- //34
- ,
- [13, 145, 115, 6, 146, 116],
- [14, 74, 46, 23, 75, 47],
- [44, 54, 24, 7, 55, 25],
- [59, 46, 16, 1, 47, 17]
- //35
- ,
- [12, 151, 121, 7, 152, 122],
- [12, 75, 47, 26, 76, 48],
- [39, 54, 24, 14, 55, 25],
- [22, 45, 15, 41, 46, 16]
- //36
- ,
- [6, 151, 121, 14, 152, 122],
- [6, 75, 47, 34, 76, 48],
- [46, 54, 24, 10, 55, 25],
- [2, 45, 15, 64, 46, 16]
- //37
- ,
- [17, 152, 122, 4, 153, 123],
- [29, 74, 46, 14, 75, 47],
- [49, 54, 24, 10, 55, 25],
- [24, 45, 15, 46, 46, 16]
- //38
- ,
- [4, 152, 122, 18, 153, 123],
- [13, 74, 46, 32, 75, 47],
- [48, 54, 24, 14, 55, 25],
- [42, 45, 15, 32, 46, 16]
- //39
- ,
- [20, 147, 117, 4, 148, 118],
- [40, 75, 47, 7, 76, 48],
- [43, 54, 24, 22, 55, 25],
- [10, 45, 15, 67, 46, 16]
- //40
- ,
- [19, 148, 118, 6, 149, 119],
- [18, 75, 47, 31, 76, 48],
- [34, 54, 24, 34, 55, 25],
- [20, 45, 15, 61, 46, 16]
-];
-
-QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
-
- var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
-
- if(rsBlock == undefined) {
- throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
- }
-
- var length = rsBlock.length / 3;
-
- var list = new Array();
-
- for(var i = 0; i < length; i++) {
-
- var count = rsBlock[i * 3 + 0];
- var totalCount = rsBlock[i * 3 + 1];
- var dataCount = rsBlock[i * 3 + 2];
-
- for(var j = 0; j < count; j++) {
- list.push(new QRRSBlock(totalCount, dataCount));
- }
- }
-
- return list;
-}
-
-QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
-
- switch(errorCorrectLevel) {
- case QRErrorCorrectLevel.L:
- return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
- case QRErrorCorrectLevel.M:
- return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
- case QRErrorCorrectLevel.Q:
- return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
- case QRErrorCorrectLevel.H:
- return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
- default:
- return undefined;
- }
-}
-
-//---------------------------------------------------------------------
-// QRBitBuffer
-//---------------------------------------------------------------------
-
-function QRBitBuffer() {
- this.buffer = new Array();
- this.length = 0;
-}
-
-QRBitBuffer.prototype = {
-
- get: function(index) {
- var bufIndex = Math.floor(index / 8);
- return((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
- },
-
- put: function(num, length) {
- for(var i = 0; i < length; i++) {
- this.putBit(((num >>> (length - i - 1)) & 1) == 1);
- }
- },
-
- getLengthInBits: function() {
- return this.length;
- },
-
- putBit: function(bit) {
-
- var bufIndex = Math.floor(this.length / 8);
- if(this.buffer.length <= bufIndex) {
- this.buffer.push(0);
- }
-
- if(bit) {
- this.buffer[bufIndex] |= (0x80 >>> (this.length % 8));
- }
-
- this.length++;
- }
-};
diff --git a/package.json b/package.json
index ae033c8..a4691b2 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,17 @@
{
"name": "qrpng",
- "version": "0.1.2",
+ "version": "1.0.0",
"description": "Quickly create a QR-Code PNG in pure JavaScript",
"main": "./qr.js",
+ "files": [
+ "qr.js",
+ "qr.d.ts",
+ "Readme.md"
+ ],
+ "scripts": {
+ "build": "tsc && rollup -c rollup.config.js",
+ "prepublishOnly": "npm run build"
+ },
"repository": {
"type": "git",
"url": "https://github.com/pipobscure/qrpng.git"
@@ -13,5 +22,15 @@
},
"dependencies": {
"buffer-crc32": "*"
- }
+ },
+ "devDependencies": {
+ "@rollup/plugin-commonjs": "^15.1.0",
+ "@rollup/plugin-node-resolve": "^9.0.0",
+ "@types/node": "^14.11.2",
+ "@types/pako": "^1.0.1",
+ "pako": "^1.0.11",
+ "rollup": "^2.28.2",
+ "typescript": "^4.0.3"
+ },
+ "license": "MIT"
}
diff --git a/qr.d.ts b/qr.d.ts
new file mode 100644
index 0000000..ddc7125
--- /dev/null
+++ b/qr.d.ts
@@ -0,0 +1,4 @@
+declare module "qr" {
+ function generate(test: string, scale?: number): Uint8Array;
+ export = generate;
+}
diff --git a/qr.js b/qr.js
deleted file mode 100644
index dc1da49..0000000
--- a/qr.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
-** © 2013 by Philipp Dunkel . Licensed under MIT License.
-*/
-
-module.exports = makeQR;
-
-var QRCode = require('./lib/qrcode.js').QRCode;
-var PNG = require('./lib/makepng.js');
-
-function makeQR(text, scale, callback) {
- if(('function' === typeof scale) && !callback) {
- callback = scale;
- scale = 1;
- }
- text = text.substr(0, 1273);
- var qr = new QRCode(level(text), 2);
- qr.addData(text);
- qr.make();
- qr = code(qr, scale);
- PNG(qr, callback);
-}
-
-function code(qr, scale) {
- var res = [];
- var mods = qr.getModuleCount();
- var idx, idy;
- var l;
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(blankline(qr, scale));
- }
- for(idx = 0; idx < mods; idx += 1) {
- for(idy = 0; idy < scale; idy += 1) {
- l = line(qr, idx, scale);
- res.push(l);
- }
- }
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(blankline(qr, scale));
- }
- return res;
-}
-
-function blankline(qr, scale) {
- var mods = qr.getModuleCount();
- var res = [];
- var idx, idy;
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(0);
- }
- for(idx = 0; idx < mods; idx += 1) {
- for(idy = 0; idy < scale; idy += 1) {
- res.push(0);
- }
- }
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(0);
- }
- return res;
-}
-
-function line(qr, l, scale) {
- var mods = qr.getModuleCount();
- var res = [];
- var idx, idy;
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(0);
- }
- for(idx = 0; idx < mods; idx += 1) {
- for(idy = 0; idy < scale; idy += 1) {
- res.push(qr.isDark(l, idx) ? 1 : 0);
- }
- }
- for(idy = 0; idy < scale * 2; idy += 1) {
- res.push(0);
- }
- return res;
-}
-
-var levels = [7, 14, 24, 34, 44, 58, 64, 84, 98, 119, 137, 155, 177, 194, 220, 250, 280, 310, 338, 382, 403, 439, 461, 511, 535, 593, 625, 658, 698, 742, 790, 842, 898, 958, 983, 1051, 1093, 1139, 1219, 1273];
-
-function level(text) {
- var res = 9999;
- levels.forEach(function(max, lev) {
- if(max < text.length) return;
- res = Math.min(lev, res);
- });
- if(res >= levels.length) throw(new Error('text too long (max: ' + levels[levels.length - 1] + ')'));
- return res + 1;
-}
diff --git a/rollup.config.js b/rollup.config.js
new file mode 100644
index 0000000..8972384
--- /dev/null
+++ b/rollup.config.js
@@ -0,0 +1,15 @@
+import noderesolve from "@rollup/plugin-node-resolve";
+import commonjs from "@rollup/plugin-commonjs";
+
+const config = {
+ input: "lib/qr.js",
+ output: {
+ name: "qrpng",
+ file: "qr.js",
+ format: "cjs",
+ exports: "default",
+ },
+ plugins: [noderesolve(), commonjs()],
+};
+
+export default config;
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..8723218
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,60 @@
+{
+ "compilerOptions": {
+ /* Basic Options */
+ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
+ "module": "ESNext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
+ // "lib": [], /* Specify library files to be included in the compilation. */
+ // "allowJs": true, /* Allow javascript files to be compiled. */
+ // "checkJs": true, /* Report errors in .js files. */
+ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
+ "declaration": false /* Generates corresponding '.d.ts' file. */,
+ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
+ "sourceMap": false /* Generates corresponding '.map' file. */,
+ // "outFile": "./", /* Concatenate and emit output to single file. */
+ // "outDir": "./dist/debug" /* Redirect output structure to the directory. */,
+ // "rootDir": "./lib", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+ // "composite": true, /* Enable project compilation */
+ // "removeComments": true, /* Do not emit comments to output. */
+ // "noEmit": true, /* Do not emit outputs. */
+ // "importHelpers": true, /* Import emit helpers from 'tslib'. */
+ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
+ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
+
+ /* Strict Type-Checking Options */
+ "strict": false /* Enable all strict type-checking options. */,
+ //"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
+ // "strictNullChecks": true, /* Enable strict null checks. */
+ // "strictFunctionTypes": true, /* Enable strict checking of function types. */
+ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
+ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
+ "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
+ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
+
+ /* Additional Checks */
+ "noUnusedLocals": true /* Report errors on unused locals. */,
+ "noUnusedParameters": true /* Report errors on unused parameters. */,
+ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
+ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
+
+ /* Module Resolution Options */
+ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
+ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
+ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
+ "rootDirs": ["lib/"] /* List of root folders whose combined content represents the structure of the project at runtime. */,
+ // "typeRoots": [], /* List of folders to include type definitions from. */
+ // "types": [], /* Type declaration files to be included in compilation. */
+ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
+ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
+
+ /* Source Map Options */
+ // "sourceRoot": "src", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
+ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
+ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
+ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
+
+ /* Experimental Options */
+ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
+ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
+ }
+}