Full Code of nimiq/qr-creator for AI

master 2ee3528ca263 cached
12 files
197.7 KB
52.2k tokens
56 symbols
1 requests
Download .txt
Showing preview only (205K chars total). Download the full file or copy to clipboard to get everything.
Repository: nimiq/qr-creator
Branch: master
Commit: 2ee3528ca263
Files: 12
Total size: 197.7 KB

Directory structure:
gitextract_rfzm3utl/

├── .gitignore
├── LICENSE
├── README.md
├── demo/
│   ├── index.html
│   └── style.css
├── package.json
├── src/
│   └── qr-creator.js
├── test/
│   ├── index.html
│   ├── qr-code.larsjung.js
│   ├── qr-code.org.js
│   └── style.css
└── types/
    └── qr-creator.d.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
node_modules
dist
.idea
.DS_Store
tmp


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 The Nimiq Foundation.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# QR Code Encoder

<img src="https://nimiq.github.io/qr-creator/demo/qr-code-example.png"/>

A lightweight library generating stylish QR codes that also support gradient fills and rounded corners in only 12.2kB minified (4.75kB gzipped).
Try out the [demo](https://nimiq.github.io/qr-creator/demo)!

## Origin
This library is a trimmed down version of [Lars Jung's jQuery.qrcode library](https://larsjung.de/jquery-qrcode/). Our library is however not based on jQuery anymore and doesnt make use of it. Lars Jung's library itself is based on this [QR code Generator](https://github.com/kazuhikoarase/qrcode-generator).

All parts are licensed under the MIT License.

## Installation

To install via npm:
```bash
npm install --save qr-creator
```
To install via yarn:
```bash
yarn add qr-creator
```
Or use a cdn like [jsdelivr](http://www.jsdelivr.com/package/npm/qr-creator) or
[unpkg](https://unpkg.com/browse/qr-creator@1.0.0/) (see [usage](#usage)).

## Usage
The library is available as a module and non-module version.
To import it as a module:
```javascript
  // from installed package for bundling with a module bundler like webpack:
  import QrCreator from 'qr-creator';
  // from cdn:
  import QrCreator from 'https://cdn.jsdelivr.net/npm/qr-creator/dist/qr-creator.es6.min.js';
```
To use the non-module version:
```html
  <!-- from your project's code base -->
  <script src="path/to/qr-creator.min.js"></script>
  <!-- from cdn -->
  <script src="https://cdn.jsdelivr.net/npm/qr-creator/dist/qr-creator.min.js"></script>
```

Call the QrCreator API with a configuration object and a DOM element or canvas to render the QR code into:
```javascript
  QrCreator.render({
    text: 'some text',
    radius: 0.5, // 0.0 to 0.5
    ecLevel: 'H', // L, M, Q, H
    fill: '#536DFE', // foreground color
    background: null, // color or null for transparent
    size: 128 // in pixels
  }, document.querySelector('#qr-code'));
```

Attribute | Options | Default | Description
----------|---------|---------|------------
text | String | "" | Any kind of text, also links, email addresses, any thing. The library will figure out the size of the QR code to fit all the text inside.
radius | 0 .. 0.5 | 0.5 | Defines how round the blocks should be. Numbers from 0 (squares) to 0.5 (maximum round) are supported.
ecLevel | L, M, Q, H | L | Means "Error correction levels". The four values L, M, Q, and H will use %7, 15%, 25%, and 30% of the QR code for error correction respectively. So on one hand the code will get bigger but chances are also higher that it will be read without errors later on.
fill | color or gradient | #000000 | What color you want your QR code to be. Use the demo to try different colors.
background | color code | null | The background color or null for transparent background.
size | int | 200 | The total size of the final QR code in pixels - it will be a square.

If you want to fill the QR code with a gradient, use the following format:
```js
{
    type: 'radial-gradient', // or 'linear-gradient'
    position: [ ... ],
    colorStops: [
        [ offset0, color0 ],
        [ offset1, color1 ],
        ...
    ]
}
```
Where the position is specified as in [createLinearGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient) / [createRadialGradient](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createRadialGradient). However, each value is relative to the QR code size, i.e. will be multiplied by that size to yield the absolute position.

## Trimmed down to be low weight
The goal of the library is to generate QR codes only. For that reason we have removed all additional code such as GIF image generation, background image support, rendering a label on top, removed some dead code, and freed it from depending on jQuery. Also, the resulting library does not use any global variables, is all strict mode, and relies on modern browser standards instead.

The result | Original | New
:--- | ---: | ---:
Lines of code | 2332 | 1556 (-33%)
Size | 64kB | 50kB (-22%)
Minified | 20.6kB | 11.95kB (-40%)
Gzipped | 7.3kB | 4.77kB (-35%)

## Building

To install the dependencies run:
```bash
npm install
```
and then to build the project:
```bash
npm run build
```


================================================
FILE: demo/index.html
================================================
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>QR code creator demo</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
</head>

<body class="state-loading">
  <header>
    <h1>QR code creator demo</h1>
  </header>
  <main>
    <section>
    </section>
    <section id="qr-code">
    </section>
    <section id="stats">
    </section>
    <section id="tools">
      <label>Text: <input id="text" type="text" value="Hello world of QR codes!"></label>
      <label>Radius: <input id="radius" type="range" value="0.5" step="0.025" min="0" max="0.5"></label>
      <label>Error correction:
      <select id="ecLevel">
        <option value="L" label="Low, 7%">
        <option value="M" label="Medium, 15%">
        <option value="Q" label="Quarter, 25%">
        <option value="H" label="High, 30%" selected>
      </select></label>
      <label>Color: <input id="fill" type="color" value="#0064a8"></label>
      <label>Background: <input id="background" type="color"><input id="transparent" type="checkbox" checked> transparent</label>
      <label>Size: <input id="size" type="range" value="250" step="10" min="20" max="1000"></label>
    </section>
    <section id="parameters">
      <label>Parameters:</label>
      <pre id="json"></pre>
    </section>
  </main>
  <link rel="stylesheet" href="style.css">
  <script type="module">
    import QrCreator from 'https://cdn.jsdelivr.net/npm/qr-creator/dist/qr-creator.es6.min.js';
    let availableSettings = ['text', 'radius', 'ecLevel', 'fill', 'background', 'size'];

    function readSettings() {
      let settings = {}, el;
      for (let setting of availableSettings) {
        settings[setting] = document.querySelector('#'+setting).value;
      }
      if (document.querySelector('#transparent').checked) {
        settings.background = null;
      }
      return settings;
    }

    function renderQrCode() {
      let time = new Date(),
          container = document.querySelector('#qr-code'),
          settings = readSettings();
      container.innerHTML = '';
      QrCreator.render(settings, container);
      document.querySelector('#stats').innerText = 'Rendered in ' + (new Date()-time) + 'ms';
      document.querySelector('#json').innerText = JSON.stringify(settings, null, 2);
    }

    for (let input of document.querySelectorAll('input, select')) {
      input.addEventListener('change', renderQrCode);
    }
    renderQrCode();

  </script>
</body>
</html>


================================================
FILE: demo/style.css
================================================
html {
  padding: .666rem;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: normal;
  font-size: 13px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  max-width: 720px;
  margin: 0 auto;
}

section {
  margin: 1.333rem 0;
}

#tools, #parameters {
  margin-top: 4rem;
  width: 50%;
  float: left;
}

#tools {
}

label {
  display: block;
  margin: .666rem 0;
}

input:not([type=checkbox]), select {
  display: block
}


================================================
FILE: package.json
================================================
{
  "name": "qr-creator",
  "version": "1.0.0",
  "description": "Lightweight QR code generator for stylish QR codes",
  "keywords": ["qr", "qr code", "qr creator", "qr encoder", "stylish qr", "beautiful qr", "lightweight", "small"],
  "repository": "git@github.com:nimiq/qr-creator.git",
  "author": "Nimiq (www.nimiq.com)",
  "license": "MIT",

  "main": "dist/qr-creator.min.js",
  "module": "dist/qr-creator.es6.min.js",
  "types": "types/qr-creator.d.ts",
  "files": ["src/qr-creator.js", "dist/qr-creator.es6.min.js", "dist/qr-creator.min.js", "dist/qr-creator.min.js.map", "types/qr-creator.d.ts"],

  "scripts": {
    "build": "google-closure-compiler --js=src/qr-creator.js --js_output_file=dist/qr-creator.min.js --language_in=ECMASCRIPT6 --language_out=ECMASCRIPT6 --rewrite_polyfills=false --compilation_level=ADVANCED --create_source_map=dist/qr-creator.min.js.map && cp dist/qr-creator.min.js dist/qr-creator.es6.min.js && echo -e '//# sourceMappingURL=qr-creator.min.js.map' >> dist/qr-creator.min.js && echo -e 'export default QrCreator;\n//# sourceMappingURL=qr-creator.min.js.map' >> dist/qr-creator.es6.min.js"
  },

  "devDependencies": {
    "google-closure-compiler": "^20190121.0.0"
  }
}


================================================
FILE: src/qr-creator.js
================================================
'use strict';
let qrCodeGenerator = null;

// Library interface
export default class QrCreator {
    static render(config, $element) {
        qrCodeGenerator(config, $element);
    }
}
// avoid that closure compiler strips these away
QrCreator['render'] = QrCreator.render;
self['QrCreator'] = QrCreator;


/*! jquery-qrcode v0.14.0 - https://larsjung.de/jquery-qrcode/ */
(function(vendor_qrcode) {

    // Wrapper for the original QR code generator.
    function createQRCode(text, level, version, quiet) {
        var qr = {};

        var vqr = vendor_qrcode(version, level);
        vqr.addData(text);
        vqr.make();

        quiet = quiet || 0;

        var qrModuleCount = vqr.getModuleCount(),
            quietModuleCount = vqr.getModuleCount() + 2 * quiet;

        function isDark(row, col) {
            row -= quiet;
            col -= quiet;

            if (row < 0 || row >= qrModuleCount || col < 0 || col >= qrModuleCount) {
                return false;
            }
            return vqr.isDark(row, col);
        }

        qr.text = text;
        qr.level = level;
        qr.version = version;
        qr.moduleCount = quietModuleCount;
        qr.isDark = isDark;
//        qr.addBlank = addBlank;

        return qr;
    }

    // Returns a minimal QR code for the given text starting with version `minVersion`.
    // Returns `undefined` if `text` is too long to be encoded in `maxVersion`.
    function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
        minVersion = Math.max(1, minVersion || 1);
        maxVersion = Math.min(40, maxVersion || 40);
        for (var version = minVersion; version <= maxVersion; version += 1) {
            try {
                return createQRCode(text, level, version, quiet);
            } catch (err) { }
        }
        return undefined;
    }

    function drawBackground(qr, context, settings) {
        if (settings.background) {
            context.fillStyle = settings.background;
            context.fillRect(settings.left, settings.top, settings.size, settings.size);
        }
    }

    // used when center is filled
    function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        //let moveTo = (x, y) => ctx.moveTo(Math.floor(x), Math.floor(y));
        if (nw) {
            ctx.moveTo(l + rad, t);
        } else {
            ctx.moveTo(l, t);
        }

        function lal(b, x0, y0, x1, y1, r0, r1) {
            if (b) {
                ctx.lineTo(x0 + r0, y0 + r1);
                ctx.arcTo(x0, y0, x1, y1, rad);
            } else {
                ctx.lineTo(x0, y0);
            }
        }

        lal(ne, r, t, r, b, -rad, 0);
        lal(se, r, b, l, b, 0, -rad);
        lal(sw, l, b, l, t, rad, 0);
        lal(nw, l, t, r, t, 0, rad);
    }

    // used when center is empty
    function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        function mlla(x, y, r0, r1) {
            ctx.moveTo(x+r0, y);
            ctx.lineTo(x, y);
            ctx.lineTo(x, y+r1);
            ctx.arcTo(x, y, x+r0, y, rad);
        }

        if (nw) mlla(l, t, rad, rad);
        if (ne) mlla(r, t, -rad, rad);
        if (se) mlla(r, b, -rad, -rad);
        if (sw) mlla(l, b, rad, -rad);
    }

    function drawModuleRounded(qr, context, settings, left, top, width, row, col) {
        var isDark = qr.isDark,
            right = left + width,
            bottom = top + width,
            rowT = row - 1,
            rowB = row + 1,
            colL = col - 1,
            colR = col + 1,
            radius = Math.floor(Math.min(0.5, Math.max(0, settings.radius)) * width),
            center = isDark(row, col),
            northwest = isDark(rowT, colL),
            north = isDark(rowT, col),
            northeast = isDark(rowT, colR),
            east = isDark(row, colR),
            southeast = isDark(rowB, colR),
            south = isDark(rowB, col),
            southwest = isDark(rowB, colL),
            west = isDark(row, colL);

        left = Math.round(left);
        top = Math.round(top);
        right = Math.round(right);
        bottom = Math.round(bottom);

        if (center) {
            drawModuleRoundedDark(context, left, top, right, bottom, radius, !north && !west, !north && !east, !south && !east, !south && !west);
        } else {
            drawModuleRoundendLight(context, left, top, right, bottom, radius, north && west && northwest, north && east && northeast, south && east && southeast, south && west && southwest);
        }
    }

    function drawModules(qr, context, settings) {
        var moduleCount = qr.moduleCount,
            moduleSize = settings.size / moduleCount,
            row,
            col;

        context.beginPath();
        for (row = 0; row < moduleCount; row += 1) {
            for (col = 0; col < moduleCount; col += 1) {
                var l = settings.left + col * moduleSize,
                    t = settings.top + row * moduleSize,
                    w = moduleSize;

                drawModuleRounded(qr, context, settings, l, t, w, row, col);
            }
        }

        setFill(context, settings);
        context.fill();
    }

    function setFill(context, settings) {
        const fill = settings.fill;
        if (typeof fill === 'string') {
            // solid color
            context.fillStyle = fill;
            return;
        }
        const type = fill['type'],
            position = fill['position'],
            colorStops = fill['colorStops'];
        let gradient;
        const absolutePosition = position.map(coordinate => Math.round(coordinate * settings.size));
        if (type === 'linear-gradient') {
            gradient = context.createLinearGradient.apply(context, absolutePosition);
        } else if (type === 'radial-gradient') {
            gradient = context.createRadialGradient.apply(context, absolutePosition);
        } else {
            throw new Error('Unsupported fill');
        }
        colorStops.forEach(([offset, color]) => {
            gradient.addColorStop(offset, color);
        });
        context.fillStyle = gradient;
    }

    // Draws QR code to the given `canvas` and returns it.
    function drawOnCanvas(canvas, settings) {
        var qr = createMinQRCode(settings.text, settings.ecLevel, settings.minVersion, settings.maxVersion, settings.quiet);
        if (!qr) {
            return null;
        }

        var context = canvas.getContext('2d');

        drawBackground(qr, context, settings);
        drawModules(qr, context, settings);

        return canvas;
    }

    // Returns a `canvas` element representing the QR code for the given settings.
    function createCanvas(settings) {
        var $canvas = document.createElement('canvas');
        $canvas.width = settings.size;
        $canvas.height = settings.size;
        return drawOnCanvas($canvas, settings);
    }

    // Plugin
    // ======

    // Default settings
    // ----------------
    var defaults = {
        // version range somewhere in 1 .. 40
        'minVersion': 1,
        'maxVersion': 40,

        // error correction level: `'L'`, `'M'`, `'Q'` or `'H'`
        'ecLevel': 'L',

        // offset in pixel if drawn onto existing canvas
        'left': 0,
        'top': 0,

        // size in pixel
        'size': 200,

        // code color or image element
        'fill': '#000',

        // background color, `null` for transparent background
        'background': null,

        // content
        'text': 'no text',

        // corner radius relative to module width: 0.0 .. 0.5
        'radius': 0.5,

        // quiet zone in modules
        'quiet': 0,

    };

    // // Register the plugin
    // // -------------------
    qrCodeGenerator = function(options, $element) {
        var settings = {};
        Object.assign(settings, defaults, options);
        // map real names to minifyable properties used by closure compiler
        settings.minVersion = settings['minVersion'];
        settings.maxVersion = settings['maxVersion'];
        settings.ecLevel = settings['ecLevel'];
        settings.left = settings['left'];
        settings.top = settings['top'];
        settings.size = settings['size'];
        settings.fill = settings['fill'];
        settings.background = settings['background'];
        settings.text = settings['text'];
        settings.radius = settings['radius'];
        settings.quiet = settings['quiet'];

        if ($element instanceof HTMLCanvasElement) {
            if ($element.width !== settings.size || $element.height !== settings.size) {
                $element.width = settings.size;
                $element.height = settings.size;
            }
            $element.getContext('2d').clearRect(0, 0, $element.width, $element.height);
            drawOnCanvas($element, settings);
        } else {
            const $canvas = createCanvas(settings);
            $element.appendChild($canvas);
        }
    };
}(function() {
    // `qrcode` is the single public function defined by the `QR Code Generator`
    //---------------------------------------------------------------------
    //
    // QR Code Generator 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
    //
    //---------------------------------------------------------------------

    var qrcode = function() {

        //---------------------------------------------------------------------
        // qrcode
        //---------------------------------------------------------------------

        /**
         * qrcode
         * @param typeNumber 1 to 40
         * @param errorCorrectLevel 'L','M','Q','H'
         */
        var qrcode = function(typeNumber, errorCorrectLevel) {

            var PAD0 = 0xEC,
                PAD1 = 0x11,
                _typeNumber = typeNumber,
                _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel],
                _modules = null,
                _moduleCount = 0,
                _dataCache = null,
                _dataList = new Array(),
                _this = {},
                makeImpl = function(test, maskPattern) {

                _moduleCount = _typeNumber * 4 + 17;
                _modules = function(moduleCount) {
                    var modules = new Array(moduleCount);
                    for (var row = 0; row < moduleCount; row += 1) {
                        modules[row] = new Array(moduleCount);
                        for (var col = 0; col < moduleCount; col += 1) {
                            modules[row][col] = null;
                        }
                    }
                    return modules;
                }(_moduleCount);

                setupPositionProbePattern(0, 0);
                setupPositionProbePattern(_moduleCount - 7, 0);
                setupPositionProbePattern(0, _moduleCount - 7);
                setupPositionAdjustPattern();
                setupTimingPattern();
                setupTypeInfo(test, maskPattern);

                if (_typeNumber >= 7) {
                    setupTypeNumber(test);
                }

                if (_dataCache == null) {
                    _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
                }

                mapData(_dataCache, maskPattern);
            },

                setupPositionProbePattern = function(row, col) {

                for (var r = -1; r <= 7; r += 1) {

                    if (row + r <= -1 || _moduleCount <= row + r) continue;

                    for (var c = -1; c <= 7; c += 1) {

                        if (col + c <= -1 || _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)) {
                            _modules[row + r][col + c] = true;
                        } else {
                            _modules[row + r][col + c] = false;
                        }
                    }
                }
            },

                getBestMaskPattern = function() {

                var minLostPoint = 0,
                    pattern = 0;

                for (var i = 0; i < 8; i += 1) {

                    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 < _moduleCount - 8; r += 1) {
                    if (_modules[r][6] != null) {
                        continue;
                    }
                    _modules[r][6] = (r % 2 == 0);
                }

                for (var c = 8; c < _moduleCount - 8; c += 1) {
                    if (_modules[6][c] != null) {
                        continue;
                    }
                    _modules[6][c] = (c % 2 == 0);
                }
            },

                setupPositionAdjustPattern = function() {

                var pos = QRUtil.getPatternPosition(_typeNumber);

                for (var i = 0; i < pos.length; i += 1) {

                    for (var j = 0; j < pos.length; j += 1) {

                        var row = pos[i];
                        var col = pos[j];

                        if (_modules[row][col] != null) {
                            continue;
                        }

                        for (var r = -2; r <= 2; r += 1) {

                            for (var c = -2; c <= 2; c += 1) {

                                _modules[row + r][col + c] = r == -2 || r == 2 || c == -2 || c == 2 || (r == 0 && c == 0);
                            }
                        }
                    }
                }
            },

            // TODO rm5 can be removed if we fix type to 5 (this method is called at 7 only)
                setupTypeNumber = function(test) {

                var bits = QRUtil.getBCHTypeNumber(_typeNumber);

                for (var i = 0; i < 18; i += 1) {
                    var mod = (!test && ((bits >> i) & 1) == 1);
                    _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
                }

                for (var i = 0; i < 18; i += 1) {
                    var mod = (!test && ((bits >> i) & 1) == 1);
                    _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
                }
            },

                setupTypeInfo = function(test, maskPattern) {

                var data = (_errorCorrectLevel << 3) | maskPattern;
                var bits = QRUtil.getBCHTypeInfo(data);

                for (var i = 0; i < 15; i += 1) {
                    let mod = (!test && ((bits >> i) & 1) == 1);

                    // vertical then horizontal
                    _modules[i < 6 ? i : (i < 8 ? i + 1 : _moduleCount - 15 + i)][8] = mod;
                    _modules[8][i < 8 ? _moduleCount - i - 1 : (i < 9 ? 15 - i : 14 - i)] = mod;
                }

                // fixed module
                _modules[_moduleCount - 8][8] = (!test);
            },

                mapData = function(data, maskPattern) {

                var inc = -1,
                    row = _moduleCount - 1,
                    bitIndex = 7,
                    byteIndex = 0,
                    maskFunc = QRUtil.getMaskFunction(maskPattern);

                for (var col = _moduleCount - 1; col > 0; col -= 2) {

                    if (col == 6) col -= 1;

                    while (true) {

                        for (var c = 0; c < 2; c += 1) {

                            if (_modules[row][col - c] == null) {

                                var dark = false;

                                if (byteIndex < data.length) {
                                    dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
                                }

                                var mask = maskFunc(row, col - c);

                                if (mask) {
                                    dark = !dark;
                                }

                                _modules[row][col - c] = dark;
                                bitIndex -= 1;

                                if (bitIndex == -1) {
                                    byteIndex += 1;
                                    bitIndex = 7;
                                }
                            }
                        }

                        row += inc;

                        if (row < 0 || _moduleCount <= row) {
                            row -= inc;
                            inc = -inc;
                            break;
                        }
                    }
                }
            },

                createBytes = function(buffer, rsBlocks) {

                var offset = 0,
                    maxDcCount = 0,
                    maxEcCount = 0,
                    dcdata = new Array(rsBlocks.length),
                    ecdata = new Array(rsBlocks.length);

                for (var r = 0; r < rsBlocks.length; r += 1) {

                    var dcCount = rsBlocks[r].dataCount,
                        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 += 1) {
                        dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
                    }
                    offset += dcCount;

                    var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount),
                        rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1),
                        modPoly = rawPoly.mod(rsPoly);

                    ecdata[r] = new Array(rsPoly.getLength() - 1);
                    for (var i = 0; i < ecdata[r].length; i += 1) {
                        var modIndex = i + modPoly.getLength() - ecdata[r].length;
                        ecdata[r][i] = (modIndex >= 0) ? modPoly.getAt(modIndex) : 0;
                    }
                }

                var totalCodeCount = 0;
                for (var i = 0; i < rsBlocks.length; i += 1) {
                    totalCodeCount += rsBlocks[i].totalCount;
                }

                var data = new Array(totalCodeCount);
                var index = 0;

                for (var i = 0; i < maxDcCount; i += 1) {
                    for (var r = 0; r < rsBlocks.length; r += 1) {
                        if (i < dcdata[r].length) {
                            data[index] = dcdata[r][i];
                            index += 1;
                        }
                    }
                }

                for (var i = 0; i < maxEcCount; i += 1) {
                    for (var r = 0; r < rsBlocks.length; r += 1) {
                        if (i < ecdata[r].length) {
                            data[index] = ecdata[r][i];
                            index += 1;
                        }
                    }
                }

                return data;
            },

                createData = function(typeNumber, errorCorrectLevel, dataList) {

                var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel),
                    buffer = qrBitBuffer();

                for (var i = 0; i < dataList.length; i += 1) {
                    var data = dataList[i];
                    buffer.put(data.getMode(), 4);
                    buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber));
                    data.write(buffer);
                }

                // calc num max data.
                var totalDataCount = 0;
                for (var i = 0; i < rsBlocks.length; i += 1) {
                    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(PAD0, 8);

                    if (buffer.getLengthInBits() >= totalDataCount * 8) {
                        break;
                    }
                    buffer.put(PAD1, 8);
                }

                return createBytes(buffer, rsBlocks);
            };

            _this.addData = function(data) {
                var newData = qr8BitByte(data);
                _dataList.push(newData);
                _dataCache = null;
            };

            _this.isDark = function(row, col) {
                if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
                    throw new Error(row + ',' + col);
                }
                return _modules[row][col];
            };

            _this.getModuleCount = function() {
                return _moduleCount;
            };

            _this.make = function() {
                makeImpl(false, getBestMaskPattern());
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // qrcode.stringToBytes
        //---------------------------------------------------------------------

        // UTF-8 version
        qrcode.stringToBytes = function(s) {
            // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
            function toUTF8Array(str) {
                var utf8 = [];
                for (var i = 0; i < str.length; i++) {
                    var charcode = str.charCodeAt(i);
                    if (charcode < 0x80) utf8.push(charcode);
                    else if (charcode < 0x800) {
                        utf8.push(0xc0 | (charcode >> 6),
                            0x80 | (charcode & 0x3f));
                    } else if (charcode < 0xd800 || charcode >= 0xe000) {
                        utf8.push(0xe0 | (charcode >> 12),
                            0x80 | ((charcode >> 6) & 0x3f),
                            0x80 | (charcode & 0x3f));
                    }
                    // surrogate pair
                    else {
                        i++;
                        // UTF-16 encodes 0x10000-0x10FFFF by
                        // subtracting 0x10000 and splitting the
                        // 20 bits of 0x0-0xFFFFF into two halves
                        charcode = 0x10000 + (((charcode & 0x3ff) << 10) |
                            (str.charCodeAt(i) & 0x3ff));
                        utf8.push(0xf0 | (charcode >> 18),
                            0x80 | ((charcode >> 12) & 0x3f),
                            0x80 | ((charcode >> 6) & 0x3f),
                            0x80 | (charcode & 0x3f));
                    }
                }
                return utf8;
            }
            return toUTF8Array(s);
        };

        //---------------------------------------------------------------------
        // QRMode
        //---------------------------------------------------------------------

        var QRMode = {
            MODE_8BIT_BYTE: 1 << 2,
        };

        //---------------------------------------------------------------------
        // QRErrorCorrectLevel
        //---------------------------------------------------------------------

        var 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 = function() {

            var 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),

                _this = {},

                getBCHDigit = function(data) {
                var digit = 0;
                while (data != 0) {
                    digit += 1;
                    data >>>= 1;
                }
                return digit;
            };

            _this.getBCHTypeInfo = function(data) {
                var d = data << 10;
                while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
                    d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15)));
                }
                return ((data << 10) | d) ^ G15_MASK;
            };

            // TODO rm5 (see rm5 above)
            _this.getBCHTypeNumber = function(data) {
                var d = data << 12;
                while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
                    d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18)));
                }
                return (data << 12) | d;
            };

            _this.getPatternPosition = function(typeNumber) {
                return PATTERN_POSITION_TABLE[typeNumber - 1];
            };

            _this.getMaskFunction = function(maskPattern) {

                switch (maskPattern) {

                    case QRMaskPattern.PATTERN000:
                        return function(i, j) { return (i + j) % 2 == 0; };
                    case QRMaskPattern.PATTERN001:
                        return function(i, j) { return i % 2 == 0; };
                    case QRMaskPattern.PATTERN010:
                        return function(i, j) { return j % 3 == 0; };
                    case QRMaskPattern.PATTERN011:
                        return function(i, j) { return (i + j) % 3 == 0; };
                    case QRMaskPattern.PATTERN100:
                        return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; };
                    case QRMaskPattern.PATTERN101:
                        return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
                    case QRMaskPattern.PATTERN110:
                        return function(i, j) { return ((i * j) % 2 + (i * j) % 3) % 2 == 0; };
                    case QRMaskPattern.PATTERN111:
                        return function(i, j) { return ((i * j) % 3 + (i + j) % 2) % 2 == 0; };

                    default:
                        throw new Error('bad maskPattern:' + maskPattern);
                }
            };

            _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
                var a = qrPolynomial([1], 0);
                for (var i = 0; i < errorCorrectLength; i += 1) {
                    a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0));
                }
                return a;
            };

            _this.getLengthInBits = function(mode, type) {
                if (mode != QRMode.MODE_8BIT_BYTE || type < 1 || type > 40)
                    throw new Error('mode: ' + mode + '; type: ' + type);

                return type < 10 ? 8 : 16;
            };

            _this.getLostPoint = function(qrcode) {

                var moduleCount = qrcode.getModuleCount(),
                    lostPoint = 0;

                // LEVEL1

                for (var row = 0; row < moduleCount; row += 1) {
                    for (var col = 0; col < moduleCount; col += 1) {

                        var sameCount = 0,
                            dark = qrcode.isDark(row, col);

                        for (var r = -1; r <= 1; r += 1) {

                            if (row + r < 0 || moduleCount <= row + r) {
                                continue;
                            }

                            for (var c = -1; c <= 1; c += 1) {

                                if (col + c < 0 || moduleCount <= col + c) {
                                    continue;
                                }

                                if (r == 0 && c == 0) {
                                    continue;
                                }

                                if (dark == qrcode.isDark(row + r, col + c)) {
                                    sameCount += 1;
                                }
                            }
                        }

                        if (sameCount > 5) {
                            lostPoint += (3 + sameCount - 5);
                        }
                    }
                };

                // LEVEL2

                for (var row = 0; row < moduleCount - 1; row += 1) {
                    for (var col = 0; col < moduleCount - 1; col += 1) {
                        var count = 0;
                        if (qrcode.isDark(row, col)) count += 1;
                        if (qrcode.isDark(row + 1, col)) count += 1;
                        if (qrcode.isDark(row, col + 1)) count += 1;
                        if (qrcode.isDark(row + 1, col + 1)) count += 1;
                        if (count == 0 || count == 4) {
                            lostPoint += 3;
                        }
                    }
                }

                // LEVEL3

                for (var row = 0; row < moduleCount; row += 1) {
                    for (var col = 0; col < moduleCount - 6; col += 1) {
                        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 += 1) {
                    for (var row = 0; row < moduleCount - 6; row += 1) {
                        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 += 1) {
                    for (var row = 0; row < moduleCount; row += 1) {
                        if (qrcode.isDark(row, col)) {
                            darkCount += 1;
                        }
                    }
                }

                var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
                lostPoint += ratio * 10;

                return lostPoint;
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // QRMath
        //---------------------------------------------------------------------

        var QRMath = function() {

            var EXP_TABLE = new Array(256),
                LOG_TABLE = new Array(256);

            // initialize tables
            for (var i = 0; i < 8; i += 1) {
                EXP_TABLE[i] = 1 << i;
            }
            for (var i = 8; i < 256; i += 1) {
                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 += 1) {
                LOG_TABLE[EXP_TABLE[i]] = i;
            }

            var _this = {};

            _this.glog = function(n) {

                if (n < 1) {
                    throw new Error('glog(' + n + ')');
                }

                return LOG_TABLE[n];
            };

            _this.gexp = function(n) {

                while (n < 0) {
                    n += 255;
                }

                while (n >= 256) {
                    n -= 255;
                }

                return EXP_TABLE[n];
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // qrPolynomial
        //---------------------------------------------------------------------

        function qrPolynomial(num, shift) {

            if (typeof num.length == 'undefined') {
                throw new Error(num.length + '/' + shift);
            }

            var _num = function() {
                var offset = 0;
                while (offset < num.length && num[offset] == 0) {
                    offset += 1;
                }
                var _num = new Array(num.length - offset + shift);
                for (var i = 0; i < num.length - offset; i += 1) {
                    _num[i] = num[i + offset];
                }
                return _num;
            }();

            var _this = {};

            _this.getAt = function(index) {
                return _num[index];
            };

            _this.getLength = function() {
                return _num.length;
            };

            _this.multiply = function(e) {

                var num = new Array(_this.getLength() + e.getLength() - 1);

                for (var i = 0; i < _this.getLength(); i += 1) {
                    for (var j = 0; j < e.getLength(); j += 1) {
                        num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i)) + QRMath.glog(e.getAt(j)));
                    }
                }

                return qrPolynomial(num, 0);
            };

            _this.mod = function(e) {

                if (_this.getLength() - e.getLength() < 0) {
                    return _this;
                }

                var ratio = QRMath.glog(_this.getAt(0)) - QRMath.glog(e.getAt(0));

                var num = new Array(_this.getLength());
                for (var i = 0; i < _this.getLength(); i += 1) {
                    num[i] = _this.getAt(i);
                }

                for (var i = 0; i < e.getLength(); i += 1) {
                    num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i)) + ratio);
                }

                // recursive call
                return qrPolynomial(num, 0).mod(e);
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // QRRSBlock
        //---------------------------------------------------------------------

        var QRRSBlock = function() {

            // TODO is it possible to generate this block with JS in let kB?
            var 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],

                // 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]
            ];

            var qrRSBlock = function(totalCount, dataCount) {
                var _this = {};
                _this.totalCount = totalCount;
                _this.dataCount = dataCount;
                return _this;
            };

            var _this = {};

            var getRsBlockTable = function(typeNumber, errorCorrectLevel) {
                switch (errorCorrectLevel) {
                    case QRErrorCorrectLevel['L']:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
                    case QRErrorCorrectLevel['M']:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
                    case QRErrorCorrectLevel['Q']:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
                    case QRErrorCorrectLevel['H']:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
                    default:
                        return undefined;
                }
            };

            _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {

                var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);

                if (typeof rsBlock == 'undefined') {
                    throw new Error('bad rs block @ typeNumber:' + typeNumber +
                        '/errorCorrectLevel:' + errorCorrectLevel);
                }

                var length = rsBlock.length / 3,
                    list = new Array();

                for (var i = 0; i < length; i += 1) {

                    var count = rsBlock[i * 3 + 0],
                        totalCount = rsBlock[i * 3 + 1],
                        dataCount = rsBlock[i * 3 + 2];

                    for (var j = 0; j < count; j += 1) {
                        list.push(qrRSBlock(totalCount, dataCount));
                    }
                }

                return list;
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // qrBitBuffer
        //---------------------------------------------------------------------

        var qrBitBuffer = function() {

            var _buffer = new Array(),
                _length = 0,
                _this = {};

            _this.getBuffer = function() {
                return _buffer;
            };

            _this.getAt = function(index) {
                var bufIndex = Math.floor(index / 8);
                return ((_buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
            };

            _this.put = function(num, length) {
                for (var i = 0; i < length; i += 1) {
                    _this.putBit(((num >>> (length - i - 1)) & 1) == 1);
                }
            };

            _this.getLengthInBits = function() {
                return _length;
            };

            _this.putBit = function(bit) {

                var bufIndex = Math.floor(_length / 8);
                if (_buffer.length <= bufIndex) {
                    _buffer.push(0);
                }

                if (bit) {
                    _buffer[bufIndex] |= (0x80 >>> (_length % 8));
                }

                _length += 1;
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // qr8BitByte
        //---------------------------------------------------------------------

        var qr8BitByte = function(data) {

            var _mode = QRMode.MODE_8BIT_BYTE,
                _data = data,
                _bytes = qrcode.stringToBytes(data),
                _this = {};

            _this.getMode = function() {
                return _mode;
            };

            _this.getLength = function(buffer) {
                return _bytes.length;
            };

            _this.write = function(buffer) {
                for (var i = 0; i < _bytes.length; i += 1) {
                    buffer.put(_bytes[i], 8);
                }
            };

            return _this;
        };

        // returns qrcode function.
        return qrcode;
    }();

    return qrcode; // eslint-disable-line no-undef
}()));


================================================
FILE: test/index.html
================================================
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>QR-Code generator test</title>

    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">

</head>

<body class="state-loading">
  <header>
    <h1>QR-Code generator test</h1>
  </header>
  <main>
    <section>
      Both QR Codes must be the same. So, if it looks like the QR Code has a shadow it's good!
    </section>
    <section id="qr-code">
    </section>
  </main>
  <link rel="apple-touch-icon" href="pwa/icons/apple-touch-icon.png">
  <link rel="stylesheet" href="style.css">
  <script src="https://cdn.jsdelivr.net/npm/qr-creator/dist/qr-creator.min.js"></script>
  <script src="qr-code.org.js"></script>
  <script>
    'use strict';
    let address = 'NQ95 I32O SA47 1KHL R1FV MP0O SVNI 73BS IJQ5',
        time    = new Date(),
        stats   = document.querySelector('#stats');

    test({
      text: address,
      radius: 0.5,
      ecLevel: 'H',
      fill: '#536DFE',
      background: null,
      size: Math.min(240, (window.innerWidth - 64) )
    }, '#qr-code');

    function test(config, selector) {
      let testReference = Object.assign({}, config, { fill: '#996633' })
      QrCodeOrg.render(testReference, document.querySelector(selector));
      QrCreator.render(config, document.querySelector(selector));
    }
  </script>
</body>
</html>


================================================
FILE: test/qr-code.larsjung.js
================================================
/*! jquery-qrcode v0.14.0 - https://larsjung.de/jquery-qrcode/ */
(function (vendor_qrcode) {
    'use strict';

    var jq = window.jQuery;

    // Check if canvas is available in the browser (as Modernizr does)
    var hasCanvas = (function () {
        var elem = document.createElement('canvas');
        return !!(elem.getContext && elem.getContext('2d'));
    }());

    // Wrapper for the original QR code generator.
    function createQRCode(text, level, version, quiet) {
        var qr = {};

        var vqr = vendor_qrcode(version, level);
        vqr.addData(text);
        vqr.make();

        quiet = quiet || 0;

        var qrModuleCount = vqr.getModuleCount();
        var quietModuleCount = vqr.getModuleCount() + 2 * quiet;

        function isDark(row, col) {
            row -= quiet;
            col -= quiet;

            if (row < 0 || row >= qrModuleCount || col < 0 || col >= qrModuleCount) {
                return false;
            }
            return vqr.isDark(row, col);
        }

        function addBlank(l, t, r, b) {
            var prevIsDark = qr.isDark;
            var moduleSize = 1 / quietModuleCount;

            qr.isDark = function (row, col) {
                var ml = col * moduleSize;
                var mt = row * moduleSize;
                var mr = ml + moduleSize;
                var mb = mt + moduleSize;

                return prevIsDark(row, col) && (l > mr || ml > r || t > mb || mt > b);
            };
        }

        qr.text = text;
        qr.level = level;
        qr.version = version;
        qr.moduleCount = quietModuleCount;
        qr.isDark = isDark;
        qr.addBlank = addBlank;

        return qr;
    }

    // Returns a minimal QR code for the given text starting with version `minVersion`.
    // Returns `undefined` if `text` is too long to be encoded in `maxVersion`.
    function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
        minVersion = Math.max(1, minVersion || 1);
        maxVersion = Math.min(40, maxVersion || 40);
        for (var version = minVersion; version <= maxVersion; version += 1) {
            try {
                return createQRCode(text, level, version, quiet);
            } catch (err) {/* empty */}
        }
        return undefined;
    }

    function drawBackgroundLabel(qr, context, settings) {
        var size = settings.size;
        var font = 'bold ' + settings.mSize * size + 'px ' + settings.fontname;
        var ctx = jq('<canvas/>')[0].getContext('2d');

        ctx.font = font;

        var w = ctx.measureText(settings.label).width;
        var sh = settings.mSize;
        var sw = w / size;
        var sl = (1 - sw) * settings.mPosX;
        var st = (1 - sh) * settings.mPosY;
        var sr = sl + sw;
        var sb = st + sh;
        var pad = 0.01;

        if (settings.mode === 1) {
            // Strip
            qr.addBlank(0, st - pad, size, sb + pad);
        } else {
            // Box
            qr.addBlank(sl - pad, st - pad, sr + pad, sb + pad);
        }

        context.fillStyle = settings.fontcolor;
        context.font = font;
        context.fillText(settings.label, sl * size, st * size + 0.75 * settings.mSize * size);
    }

    function drawBackgroundImage(qr, context, settings) {
        var size = settings.size;
        var w = settings.image.naturalWidth || 1;
        var h = settings.image.naturalHeight || 1;
        var sh = settings.mSize;
        var sw = sh * w / h;
        var sl = (1 - sw) * settings.mPosX;
        var st = (1 - sh) * settings.mPosY;
        var sr = sl + sw;
        var sb = st + sh;
        var pad = 0.01;

        if (settings.mode === 3) {
            // Strip
            qr.addBlank(0, st - pad, size, sb + pad);
        } else {
            // Box
            qr.addBlank(sl - pad, st - pad, sr + pad, sb + pad);
        }

        context.drawImage(settings.image, sl * size, st * size, sw * size, sh * size);
    }

    function drawBackground(qr, context, settings) {
        if (jq(settings.background).is('img')) {
            context.drawImage(settings.background, 0, 0, settings.size, settings.size);
        } else if (settings.background) {
            context.fillStyle = settings.background;
            context.fillRect(settings.left, settings.top, settings.size, settings.size);
        }

        var mode = settings.mode;
        if (mode === 1 || mode === 2) {
            drawBackgroundLabel(qr, context, settings);
        } else if (mode === 3 || mode === 4) {
            drawBackgroundImage(qr, context, settings);
        }
    }

    function drawModuleDefault(qr, context, settings, left, top, width, row, col) {
        if (qr.isDark(row, col)) {
            context.rect(left, top, width, width);
        }
    }

    function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        if (nw) {
            ctx.moveTo(l + rad, t);
        } else {
            ctx.moveTo(l, t);
        }

        if (ne) {
            ctx.lineTo(r - rad, t);
            ctx.arcTo(r, t, r, b, rad);
        } else {
            ctx.lineTo(r, t);
        }

        if (se) {
            ctx.lineTo(r, b - rad);
            ctx.arcTo(r, b, l, b, rad);
        } else {
            ctx.lineTo(r, b);
        }

        if (sw) {
            ctx.lineTo(l + rad, b);
            ctx.arcTo(l, b, l, t, rad);
        } else {
            ctx.lineTo(l, b);
        }

        if (nw) {
            ctx.lineTo(l, t + rad);
            ctx.arcTo(l, t, r, t, rad);
        } else {
            ctx.lineTo(l, t);
        }
    }

    function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        if (nw) {
            ctx.moveTo(l + rad, t);
            ctx.lineTo(l, t);
            ctx.lineTo(l, t + rad);
            ctx.arcTo(l, t, l + rad, t, rad);
        }

        if (ne) {
            ctx.moveTo(r - rad, t);
            ctx.lineTo(r, t);
            ctx.lineTo(r, t + rad);
            ctx.arcTo(r, t, r - rad, t, rad);
        }

        if (se) {
            ctx.moveTo(r - rad, b);
            ctx.lineTo(r, b);
            ctx.lineTo(r, b - rad);
            ctx.arcTo(r, b, r - rad, b, rad);
        }

        if (sw) {
            ctx.moveTo(l + rad, b);
            ctx.lineTo(l, b);
            ctx.lineTo(l, b - rad);
            ctx.arcTo(l, b, l + rad, b, rad);
        }
    }

    function drawModuleRounded(qr, context, settings, left, top, width, row, col) {
        var isDark = qr.isDark;
        var right = left + width;
        var bottom = top + width;
        var radius = settings.radius * width;
        var rowT = row - 1;
        var rowB = row + 1;
        var colL = col - 1;
        var colR = col + 1;
        var center = isDark(row, col);
        var northwest = isDark(rowT, colL);
        var north = isDark(rowT, col);
        var northeast = isDark(rowT, colR);
        var east = isDark(row, colR);
        var southeast = isDark(rowB, colR);
        var south = isDark(rowB, col);
        var southwest = isDark(rowB, colL);
        var west = isDark(row, colL);

        if (center) {
            drawModuleRoundedDark(context, left, top, right, bottom, radius, !north && !west, !north && !east, !south && !east, !south && !west);
        } else {
            drawModuleRoundendLight(context, left, top, right, bottom, radius, north && west && northwest, north && east && northeast, south && east && southeast, south && west && southwest);
        }
    }

    function drawModules(qr, context, settings) {
        var moduleCount = qr.moduleCount;
        var moduleSize = settings.size / moduleCount;
        var fn = drawModuleDefault;
        var row;
        var col;

        if (settings.radius > 0 && settings.radius <= 0.5) {
            fn = drawModuleRounded;
        }

        context.beginPath();
        for (row = 0; row < moduleCount; row += 1) {
            for (col = 0; col < moduleCount; col += 1) {
                var l = settings.left + col * moduleSize;
                var t = settings.top + row * moduleSize;
                var w = moduleSize;

                fn(qr, context, settings, l, t, w, row, col);
            }
        }
        if (jq(settings.fill).is('img')) {
            context.strokeStyle = 'rgba(0,0,0,0.5)';
            context.lineWidth = 2;
            context.stroke();
            var prev = context.globalCompositeOperation;
            context.globalCompositeOperation = 'destination-out';
            context.fill();
            context.globalCompositeOperation = prev;

            context.clip();
            context.drawImage(settings.fill, 0, 0, settings.size, settings.size);
            context.restore();
        } else {
            context.fillStyle = settings.fill;
            context.fill();
        }
    }

    // Draws QR code to the given `canvas` and returns it.
    function drawOnCanvas(canvas, settings) {
        var qr = createMinQRCode(settings.text, settings.ecLevel, settings.minVersion, settings.maxVersion, settings.quiet);
        if (!qr) {
            return null;
        }

        var $canvas = jq(canvas).data('qrcode', qr);
        var context = $canvas[0].getContext('2d');

        drawBackground(qr, context, settings);
        drawModules(qr, context, settings);

        return $canvas;
    }

    // Returns a `canvas` element representing the QR code for the given settings.
    function createCanvas(settings) {
        var $canvas = jq('<canvas/>').attr('width', settings.size).attr('height', settings.size);
        return drawOnCanvas($canvas, settings);
    }

    // Returns an `image` element representing the QR code for the given settings.
    function createImage(settings) {
        return jq('<img/>').attr('src', createCanvas(settings)[0].toDataURL('image/png'));
    }

    // Returns a `div` element representing the QR code for the given settings.
    function createDiv(settings) {
        var qr = createMinQRCode(settings.text, settings.ecLevel, settings.minVersion, settings.maxVersion, settings.quiet);
        if (!qr) {
            return null;
        }

        // some shortcuts to improve compression
        var settings_size = settings.size;
        var settings_bgColor = settings.background;
        var math_floor = Math.floor;

        var moduleCount = qr.moduleCount;
        var moduleSize = math_floor(settings_size / moduleCount);
        var offset = math_floor(0.5 * (settings_size - moduleSize * moduleCount));

        var row;
        var col;

        var containerCSS = {
            position: 'relative',
            left: 0,
            top: 0,
            padding: 0,
            margin: 0,
            width: settings_size,
            height: settings_size
        };
        var darkCSS = {
            position: 'absolute',
            padding: 0,
            margin: 0,
            width: moduleSize,
            height: moduleSize,
            'background-color': settings.fill
        };

        var $div = jq('<div/>').data('qrcode', qr).css(containerCSS);

        if (settings_bgColor) {
            $div.css('background-color', settings_bgColor);
        }

        for (row = 0; row < moduleCount; row += 1) {
            for (col = 0; col < moduleCount; col += 1) {
                if (qr.isDark(row, col)) {
                    jq('<div/>')
                        .css(darkCSS)
                        .css({
                            left: offset + col * moduleSize,
                            top: offset + row * moduleSize
                        })
                        .appendTo($div);
                }
            }
        }

        return $div;
    }

    function createHTML(settings) {
        if (hasCanvas && settings.render === 'canvas') {
            return createCanvas(settings);
        } else if (hasCanvas && settings.render === 'image') {
            return createImage(settings);
        }

        return createDiv(settings);
    }

    // Plugin
    // ======

    // Default settings
    // ----------------
    var defaults = {
        // render method: `'canvas'`, `'image'` or `'div'`
        render: 'canvas',

        // version range somewhere in 1 .. 40
        minVersion: 1,
        maxVersion: 40,

        // error correction level: `'L'`, `'M'`, `'Q'` or `'H'`
        ecLevel: 'L',

        // offset in pixel if drawn onto existing canvas
        left: 0,
        top: 0,

        // size in pixel
        size: 200,

        // code color or image element
        fill: '#000',

        // background color or image element, `null` for transparent background
        background: null,

        // content
        text: 'no text',

        // corner radius relative to module width: 0.0 .. 0.5
        radius: 0,

        // quiet zone in modules
        quiet: 0,

        // modes
        // 0: normal
        // 1: label strip
        // 2: label box
        // 3: image strip
        // 4: image box
        mode: 0,

        mSize: 0.1,
        mPosX: 0.5,
        mPosY: 0.5,

        label: 'no label',
        fontname: 'sans',
        fontcolor: '#000',

        image: null
    };

    // Register the plugin
    // -------------------
    jq.fn.qrcode = function (options) {
        var settings = jq.extend({}, defaults, options);

        return this.each(function (idx, el) {
            if (el.nodeName.toLowerCase() === 'canvas') {
                drawOnCanvas(el, settings);
            } else {
                jq(el).append(createHTML(settings));
            }
        });
    };
}(function () {
    // `qrcode` is the single public function defined by the `QR Code Generator`
    //---------------------------------------------------------------------
    //
    // QR Code Generator 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
    //
    //---------------------------------------------------------------------

    var qrcode = function() {

      //---------------------------------------------------------------------
      // qrcode
      //---------------------------------------------------------------------

      /**
       * qrcode
       * @param typeNumber 1 to 40
       * @param errorCorrectLevel 'L','M','Q','H'
       */
      var qrcode = function(typeNumber, errorCorrectLevel) {

        var PAD0 = 0xEC;
        var PAD1 = 0x11;

        var _typeNumber = typeNumber;
        var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
        var _modules = null;
        var _moduleCount = 0;
        var _dataCache = null;
        var _dataList = new Array();

        var _this = {};

        var makeImpl = function(test, maskPattern) {

          _moduleCount = _typeNumber * 4 + 17;
          _modules = function(moduleCount) {
            var modules = new Array(moduleCount);
            for (var row = 0; row < moduleCount; row += 1) {
              modules[row] = new Array(moduleCount);
              for (var col = 0; col < moduleCount; col += 1) {
                modules[row][col] = null;
              }
            }
            return modules;
          }(_moduleCount);

          setupPositionProbePattern(0, 0);
          setupPositionProbePattern(_moduleCount - 7, 0);
          setupPositionProbePattern(0, _moduleCount - 7);
          setupPositionAdjustPattern();
          setupTimingPattern();
          setupTypeInfo(test, maskPattern);

          if (_typeNumber >= 7) {
            setupTypeNumber(test);
          }

          if (_dataCache == null) {
            _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
          }

          mapData(_dataCache, maskPattern);
        };

        var setupPositionProbePattern = function(row, col) {

          for (var r = -1; r <= 7; r += 1) {

            if (row + r <= -1 || _moduleCount <= row + r) continue;

            for (var c = -1; c <= 7; c += 1) {

              if (col + c <= -1 || _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) ) {
                _modules[row + r][col + c] = true;
              } else {
                _modules[row + r][col + c] = false;
              }
            }
          }
        };

        var getBestMaskPattern = function() {

          var minLostPoint = 0;
          var pattern = 0;

          for (var i = 0; i < 8; i += 1) {

            makeImpl(true, i);

            var lostPoint = QRUtil.getLostPoint(_this);

            if (i == 0 || minLostPoint > lostPoint) {
              minLostPoint = lostPoint;
              pattern = i;
            }
          }

          return pattern;
        };

        var setupTimingPattern = function() {

          for (var r = 8; r < _moduleCount - 8; r += 1) {
            if (_modules[r][6] != null) {
              continue;
            }
            _modules[r][6] = (r % 2 == 0);
          }

          for (var c = 8; c < _moduleCount - 8; c += 1) {
            if (_modules[6][c] != null) {
              continue;
            }
            _modules[6][c] = (c % 2 == 0);
          }
        };

        var setupPositionAdjustPattern = function() {

          var pos = QRUtil.getPatternPosition(_typeNumber);

          for (var i = 0; i < pos.length; i += 1) {

            for (var j = 0; j < pos.length; j += 1) {

              var row = pos[i];
              var col = pos[j];

              if (_modules[row][col] != null) {
                continue;
              }

              for (var r = -2; r <= 2; r += 1) {

                for (var c = -2; c <= 2; c += 1) {

                  if (r == -2 || r == 2 || c == -2 || c == 2
                      || (r == 0 && c == 0) ) {
                    _modules[row + r][col + c] = true;
                  } else {
                    _modules[row + r][col + c] = false;
                  }
                }
              }
            }
          }
        };

        var setupTypeNumber = function(test) {

          var bits = QRUtil.getBCHTypeNumber(_typeNumber);

          for (var i = 0; i < 18; i += 1) {
            var mod = (!test && ( (bits >> i) & 1) == 1);
            _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
          }

          for (var i = 0; i < 18; i += 1) {
            var mod = (!test && ( (bits >> i) & 1) == 1);
            _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
          }
        };

        var setupTypeInfo = function(test, maskPattern) {

          var data = (_errorCorrectLevel << 3) | maskPattern;
          var bits = QRUtil.getBCHTypeInfo(data);

          // vertical
          for (var i = 0; i < 15; i += 1) {

            var mod = (!test && ( (bits >> i) & 1) == 1);

            if (i < 6) {
              _modules[i][8] = mod;
            } else if (i < 8) {
              _modules[i + 1][8] = mod;
            } else {
              _modules[_moduleCount - 15 + i][8] = mod;
            }
          }

          // horizontal
          for (var i = 0; i < 15; i += 1) {

            var mod = (!test && ( (bits >> i) & 1) == 1);

            if (i < 8) {
              _modules[8][_moduleCount - i - 1] = mod;
            } else if (i < 9) {
              _modules[8][15 - i - 1 + 1] = mod;
            } else {
              _modules[8][15 - i - 1] = mod;
            }
          }

          // fixed module
          _modules[_moduleCount - 8][8] = (!test);
        };

        var mapData = function(data, maskPattern) {

          var inc = -1;
          var row = _moduleCount - 1;
          var bitIndex = 7;
          var byteIndex = 0;
          var maskFunc = QRUtil.getMaskFunction(maskPattern);

          for (var col = _moduleCount - 1; col > 0; col -= 2) {

            if (col == 6) col -= 1;

            while (true) {

              for (var c = 0; c < 2; c += 1) {

                if (_modules[row][col - c] == null) {

                  var dark = false;

                  if (byteIndex < data.length) {
                    dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
                  }

                  var mask = maskFunc(row, col - c);

                  if (mask) {
                    dark = !dark;
                  }

                  _modules[row][col - c] = dark;
                  bitIndex -= 1;

                  if (bitIndex == -1) {
                    byteIndex += 1;
                    bitIndex = 7;
                  }
                }
              }

              row += inc;

              if (row < 0 || _moduleCount <= row) {
                row -= inc;
                inc = -inc;
                break;
              }
            }
          }
        };

        var 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 += 1) {

            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 += 1) {
              dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
            }
            offset += dcCount;

            var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
            var rawPoly = 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 += 1) {
              var modIndex = i + modPoly.getLength() - ecdata[r].length;
              ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
            }
          }

          var totalCodeCount = 0;
          for (var i = 0; i < rsBlocks.length; i += 1) {
            totalCodeCount += rsBlocks[i].totalCount;
          }

          var data = new Array(totalCodeCount);
          var index = 0;

          for (var i = 0; i < maxDcCount; i += 1) {
            for (var r = 0; r < rsBlocks.length; r += 1) {
              if (i < dcdata[r].length) {
                data[index] = dcdata[r][i];
                index += 1;
              }
            }
          }

          for (var i = 0; i < maxEcCount; i += 1) {
            for (var r = 0; r < rsBlocks.length; r += 1) {
              if (i < ecdata[r].length) {
                data[index] = ecdata[r][i];
                index += 1;
              }
            }
          }

          return data;
        };

        var createData = function(typeNumber, errorCorrectLevel, dataList) {

          var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);

          var buffer = qrBitBuffer();

          for (var i = 0; i < dataList.length; i += 1) {
            var data = dataList[i];
            buffer.put(data.getMode(), 4);
            buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
            data.write(buffer);
          }

          // calc num max data.
          var totalDataCount = 0;
          for (var i = 0; i < rsBlocks.length; i += 1) {
            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(PAD0, 8);

            if (buffer.getLengthInBits() >= totalDataCount * 8) {
              break;
            }
            buffer.put(PAD1, 8);
          }

          return createBytes(buffer, rsBlocks);
        };

        _this.addData = function(data) {
          var newData = qr8BitByte(data);
          _dataList.push(newData);
          _dataCache = null;
        };

        _this.isDark = function(row, col) {
          if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
            throw new Error(row + ',' + col);
          }
          return _modules[row][col];
        };

        _this.getModuleCount = function() {
          return _moduleCount;
        };

        _this.make = function() {
          makeImpl(false, getBestMaskPattern() );
        };

        _this.createTableTag = function(cellSize, margin) {

          cellSize = cellSize || 2;
          margin = (typeof margin == 'undefined')? cellSize * 4 : margin;

          var qrHtml = '';

          qrHtml += '<table style="';
          qrHtml += ' border-width: 0px; border-style: none;';
          qrHtml += ' border-collapse: collapse;';
          qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
          qrHtml += '">';
          qrHtml += '<tbody>';

          for (var r = 0; r < _this.getModuleCount(); r += 1) {

            qrHtml += '<tr>';

            for (var c = 0; c < _this.getModuleCount(); c += 1) {
              qrHtml += '<td style="';
              qrHtml += ' border-width: 0px; border-style: none;';
              qrHtml += ' border-collapse: collapse;';
              qrHtml += ' padding: 0px; margin: 0px;';
              qrHtml += ' width: ' + cellSize + 'px;';
              qrHtml += ' height: ' + cellSize + 'px;';
              qrHtml += ' background-color: ';
              qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
              qrHtml += ';';
              qrHtml += '"/>';
            }

            qrHtml += '</tr>';
          }

          qrHtml += '</tbody>';
          qrHtml += '</table>';

          return qrHtml;
        };

        _this.createImgTag = function(cellSize, margin) {

          cellSize = cellSize || 2;
          margin = (typeof margin == 'undefined')? cellSize * 4 : margin;

          var size = _this.getModuleCount() * cellSize + margin * 2;
          var min = margin;
          var max = size - margin;

          return createImgTag(size, size, function(x, y) {
            if (min <= x && x < max && min <= y && y < max) {
              var c = Math.floor( (x - min) / cellSize);
              var r = Math.floor( (y - min) / cellSize);
              return _this.isDark(r, c)? 0 : 1;
            } else {
              return 1;
            }
          } );
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // qrcode.stringToBytes
      //---------------------------------------------------------------------

      qrcode.stringToBytes = function(s) {
        var bytes = new Array();
        for (var i = 0; i < s.length; i += 1) {
          var c = s.charCodeAt(i);
          bytes.push(c & 0xff);
        }
        return bytes;
      };

      //---------------------------------------------------------------------
      // qrcode.createStringToBytes
      //---------------------------------------------------------------------

      /**
       * @param unicodeData base64 string of byte array.
       * [16bit Unicode],[16bit Bytes], ...
       * @param numChars
       */
      qrcode.createStringToBytes = function(unicodeData, numChars) {

        // create conversion map.

        var unicodeMap = function() {

          var bin = base64DecodeInputStream(unicodeData);
          var read = function() {
            var b = bin.read();
            if (b == -1) throw new Error();
            return b;
          };

          var count = 0;
          var unicodeMap = {};
          while (true) {
            var b0 = bin.read();
            if (b0 == -1) break;
            var b1 = read();
            var b2 = read();
            var b3 = read();
            var k = String.fromCharCode( (b0 << 8) | b1);
            var v = (b2 << 8) | b3;
            unicodeMap[k] = v;
            count += 1;
          }
          if (count != numChars) {
            throw new Error(count + ' != ' + numChars);
          }

          return unicodeMap;
        }();

        var unknownChar = '?'.charCodeAt(0);

        return function(s) {
          var bytes = new Array();
          for (var i = 0; i < s.length; i += 1) {
            var c = s.charCodeAt(i);
            if (c < 128) {
              bytes.push(c);
            } else {
              var b = unicodeMap[s.charAt(i)];
              if (typeof b == 'number') {
                if ( (b & 0xff) == b) {
                  // 1byte
                  bytes.push(b);
                } else {
                  // 2bytes
                  bytes.push(b >>> 8);
                  bytes.push(b & 0xff);
                }
              } else {
                bytes.push(unknownChar);
              }
            }
          }
          return bytes;
        };
      };

      //---------------------------------------------------------------------
      // QRMode
      //---------------------------------------------------------------------

      var QRMode = {
        MODE_NUMBER :    1 << 0,
        MODE_ALPHA_NUM : 1 << 1,
        MODE_8BIT_BYTE : 1 << 2,
        MODE_KANJI :     1 << 3
      };

      //---------------------------------------------------------------------
      // QRErrorCorrectLevel
      //---------------------------------------------------------------------

      var 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 = function() {

        var 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]
        ];
        var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
        var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
        var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);

        var _this = {};

        var getBCHDigit = function(data) {
          var digit = 0;
          while (data != 0) {
            digit += 1;
            data >>>= 1;
          }
          return digit;
        };

        _this.getBCHTypeInfo = function(data) {
          var d = data << 10;
          while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
            d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
          }
          return ( (data << 10) | d) ^ G15_MASK;
        };

        _this.getBCHTypeNumber = function(data) {
          var d = data << 12;
          while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
            d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
          }
          return (data << 12) | d;
        };

        _this.getPatternPosition = function(typeNumber) {
          return PATTERN_POSITION_TABLE[typeNumber - 1];
        };

        _this.getMaskFunction = function(maskPattern) {

          switch (maskPattern) {

          case QRMaskPattern.PATTERN000 :
            return function(i, j) { return (i + j) % 2 == 0; };
          case QRMaskPattern.PATTERN001 :
            return function(i, j) { return i % 2 == 0; };
          case QRMaskPattern.PATTERN010 :
            return function(i, j) { return j % 3 == 0; };
          case QRMaskPattern.PATTERN011 :
            return function(i, j) { return (i + j) % 3 == 0; };
          case QRMaskPattern.PATTERN100 :
            return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
          case QRMaskPattern.PATTERN101 :
            return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
          case QRMaskPattern.PATTERN110 :
            return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
          case QRMaskPattern.PATTERN111 :
            return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };

          default :
            throw new Error('bad maskPattern:' + maskPattern);
          }
        };

        _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
          var a = qrPolynomial([1], 0);
          for (var i = 0; i < errorCorrectLength; i += 1) {
            a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
          }
          return a;
        };

        _this.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);
          }
        };

        _this.getLostPoint = function(qrcode) {

          var moduleCount = qrcode.getModuleCount();

          var lostPoint = 0;

          // LEVEL1

          for (var row = 0; row < moduleCount; row += 1) {
            for (var col = 0; col < moduleCount; col += 1) {

              var sameCount = 0;
              var dark = qrcode.isDark(row, col);

              for (var r = -1; r <= 1; r += 1) {

                if (row + r < 0 || moduleCount <= row + r) {
                  continue;
                }

                for (var c = -1; c <= 1; c += 1) {

                  if (col + c < 0 || moduleCount <= col + c) {
                    continue;
                  }

                  if (r == 0 && c == 0) {
                    continue;
                  }

                  if (dark == qrcode.isDark(row + r, col + c) ) {
                    sameCount += 1;
                  }
                }
              }

              if (sameCount > 5) {
                lostPoint += (3 + sameCount - 5);
              }
            }
          };

          // LEVEL2

          for (var row = 0; row < moduleCount - 1; row += 1) {
            for (var col = 0; col < moduleCount - 1; col += 1) {
              var count = 0;
              if (qrcode.isDark(row, col) ) count += 1;
              if (qrcode.isDark(row + 1, col) ) count += 1;
              if (qrcode.isDark(row, col + 1) ) count += 1;
              if (qrcode.isDark(row + 1, col + 1) ) count += 1;
              if (count == 0 || count == 4) {
                lostPoint += 3;
              }
            }
          }

          // LEVEL3

          for (var row = 0; row < moduleCount; row += 1) {
            for (var col = 0; col < moduleCount - 6; col += 1) {
              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 += 1) {
            for (var row = 0; row < moduleCount - 6; row += 1) {
              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 += 1) {
            for (var row = 0; row < moduleCount; row += 1) {
              if (qrcode.isDark(row, col) ) {
                darkCount += 1;
              }
            }
          }

          var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
          lostPoint += ratio * 10;

          return lostPoint;
        };

        return _this;
      }();

      //---------------------------------------------------------------------
      // QRMath
      //---------------------------------------------------------------------

      var QRMath = function() {

        var EXP_TABLE = new Array(256);
        var LOG_TABLE = new Array(256);

        // initialize tables
        for (var i = 0; i < 8; i += 1) {
          EXP_TABLE[i] = 1 << i;
        }
        for (var i = 8; i < 256; i += 1) {
          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 += 1) {
          LOG_TABLE[EXP_TABLE[i] ] = i;
        }

        var _this = {};

        _this.glog = function(n) {

          if (n < 1) {
            throw new Error('glog(' + n + ')');
          }

          return LOG_TABLE[n];
        };

        _this.gexp = function(n) {

          while (n < 0) {
            n += 255;
          }

          while (n >= 256) {
            n -= 255;
          }

          return EXP_TABLE[n];
        };

        return _this;
      }();

      //---------------------------------------------------------------------
      // qrPolynomial
      //---------------------------------------------------------------------

      function qrPolynomial(num, shift) {

        if (typeof num.length == 'undefined') {
          throw new Error(num.length + '/' + shift);
        }

        var _num = function() {
          var offset = 0;
          while (offset < num.length && num[offset] == 0) {
            offset += 1;
          }
          var _num = new Array(num.length - offset + shift);
          for (var i = 0; i < num.length - offset; i += 1) {
            _num[i] = num[i + offset];
          }
          return _num;
        }();

        var _this = {};

        _this.getAt = function(index) {
          return _num[index];
        };

        _this.getLength = function() {
          return _num.length;
        };

        _this.multiply = function(e) {

          var num = new Array(_this.getLength() + e.getLength() - 1);

          for (var i = 0; i < _this.getLength(); i += 1) {
            for (var j = 0; j < e.getLength(); j += 1) {
              num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
            }
          }

          return qrPolynomial(num, 0);
        };

        _this.mod = function(e) {

          if (_this.getLength() - e.getLength() < 0) {
            return _this;
          }

          var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );

          var num = new Array(_this.getLength() );
          for (var i = 0; i < _this.getLength(); i += 1) {
            num[i] = _this.getAt(i);
          }

          for (var i = 0; i < e.getLength(); i += 1) {
            num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
          }

          // recursive call
          return qrPolynomial(num, 0).mod(e);
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // QRRSBlock
      //---------------------------------------------------------------------

      var QRRSBlock = function() {

        var 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],

          // 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]
        ];

        var qrRSBlock = function(totalCount, dataCount) {
          var _this = {};
          _this.totalCount = totalCount;
          _this.dataCount = dataCount;
          return _this;
        };

        var _this = {};

        var getRsBlockTable = function(typeNumber, errorCorrectLevel) {

          switch(errorCorrectLevel) {
          case QRErrorCorrectLevel.L :
            return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
          case QRErrorCorrectLevel.M :
            return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
          case QRErrorCorrectLevel.Q :
            return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
          case QRErrorCorrectLevel.H :
            return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
          default :
            return undefined;
          }
        };

        _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {

          var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);

          if (typeof 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 += 1) {

            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 += 1) {
              list.push(qrRSBlock(totalCount, dataCount) );
            }
          }

          return list;
        };

        return _this;
      }();

      //---------------------------------------------------------------------
      // qrBitBuffer
      //---------------------------------------------------------------------

      var qrBitBuffer = function() {

        var _buffer = new Array();
        var _length = 0;

        var _this = {};

        _this.getBuffer = function() {
          return _buffer;
        };

        _this.getAt = function(index) {
          var bufIndex = Math.floor(index / 8);
          return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
        };

        _this.put = function(num, length) {
          for (var i = 0; i < length; i += 1) {
            _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
          }
        };

        _this.getLengthInBits = function() {
          return _length;
        };

        _this.putBit = function(bit) {

          var bufIndex = Math.floor(_length / 8);
          if (_buffer.length <= bufIndex) {
            _buffer.push(0);
          }

          if (bit) {
            _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
          }

          _length += 1;
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // qr8BitByte
      //---------------------------------------------------------------------

      var qr8BitByte = function(data) {

        var _mode = QRMode.MODE_8BIT_BYTE;
        var _data = data;
        var _bytes = qrcode.stringToBytes(data);

        var _this = {};

        _this.getMode = function() {
          return _mode;
        };

        _this.getLength = function(buffer) {
          return _bytes.length;
        };

        _this.write = function(buffer) {
          for (var i = 0; i < _bytes.length; i += 1) {
            buffer.put(_bytes[i], 8);
          }
        };

        return _this;
      };

      //=====================================================================
      // GIF Support etc.
      //

      //---------------------------------------------------------------------
      // byteArrayOutputStream
      //---------------------------------------------------------------------

      var byteArrayOutputStream = function() {

        var _bytes = new Array();

        var _this = {};

        _this.writeByte = function(b) {
          _bytes.push(b & 0xff);
        };

        _this.writeShort = function(i) {
          _this.writeByte(i);
          _this.writeByte(i >>> 8);
        };

        _this.writeBytes = function(b, off, len) {
          off = off || 0;
          len = len || b.length;
          for (var i = 0; i < len; i += 1) {
            _this.writeByte(b[i + off]);
          }
        };

        _this.writeString = function(s) {
          for (var i = 0; i < s.length; i += 1) {
            _this.writeByte(s.charCodeAt(i) );
          }
        };

        _this.toByteArray = function() {
          return _bytes;
        };

        _this.toString = function() {
          var s = '';
          s += '[';
          for (var i = 0; i < _bytes.length; i += 1) {
            if (i > 0) {
              s += ',';
            }
            s += _bytes[i];
          }
          s += ']';
          return s;
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // base64EncodeOutputStream
      //---------------------------------------------------------------------

      var base64EncodeOutputStream = function() {

        var _buffer = 0;
        var _buflen = 0;
        var _length = 0;
        var _base64 = '';

        var _this = {};

        var writeEncoded = function(b) {
          _base64 += String.fromCharCode(encode(b & 0x3f) );
        };

        var encode = function(n) {
          if (n < 0) {
            // error.
          } else if (n < 26) {
            return 0x41 + n;
          } else if (n < 52) {
            return 0x61 + (n - 26);
          } else if (n < 62) {
            return 0x30 + (n - 52);
          } else if (n == 62) {
            return 0x2b;
          } else if (n == 63) {
            return 0x2f;
          }
          throw new Error('n:' + n);
        };

        _this.writeByte = function(n) {

          _buffer = (_buffer << 8) | (n & 0xff);
          _buflen += 8;
          _length += 1;

          while (_buflen >= 6) {
            writeEncoded(_buffer >>> (_buflen - 6) );
            _buflen -= 6;
          }
        };

        _this.flush = function() {

          if (_buflen > 0) {
            writeEncoded(_buffer << (6 - _buflen) );
            _buffer = 0;
            _buflen = 0;
          }

          if (_length % 3 != 0) {
            // padding
            var padlen = 3 - _length % 3;
            for (var i = 0; i < padlen; i += 1) {
              _base64 += '=';
            }
          }
        };

        _this.toString = function() {
          return _base64;
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // base64DecodeInputStream
      //---------------------------------------------------------------------

      var base64DecodeInputStream = function(str) {

        var _str = str;
        var _pos = 0;
        var _buffer = 0;
        var _buflen = 0;

        var _this = {};

        _this.read = function() {

          while (_buflen < 8) {

            if (_pos >= _str.length) {
              if (_buflen == 0) {
                return -1;
              }
              throw new Error('unexpected end of file./' + _buflen);
            }

            var c = _str.charAt(_pos);
            _pos += 1;

            if (c == '=') {
              _buflen = 0;
              return -1;
            } else if (c.match(/^\s$/) ) {
              // ignore if whitespace.
              continue;
            }

            _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
            _buflen += 6;
          }

          var n = (_buffer >>> (_buflen - 8) ) & 0xff;
          _buflen -= 8;
          return n;
        };

        var decode = function(c) {
          if (0x41 <= c && c <= 0x5a) {
            return c - 0x41;
          } else if (0x61 <= c && c <= 0x7a) {
            return c - 0x61 + 26;
          } else if (0x30 <= c && c <= 0x39) {
            return c - 0x30 + 52;
          } else if (c == 0x2b) {
            return 62;
          } else if (c == 0x2f) {
            return 63;
          } else {
            throw new Error('c:' + c);
          }
        };

        return _this;
      };

      //---------------------------------------------------------------------
      // gifImage (B/W)
      //---------------------------------------------------------------------

      var gifImage = function(width, height) {

        var _width = width;
        var _height = height;
        var _data = new Array(width * height);

        var _this = {};

        _this.setPixel = function(x, y, pixel) {
          _data[y * _width + x] = pixel;
        };

        _this.write = function(out) {

          //---------------------------------
          // GIF Signature

          out.writeString('GIF87a');

          //---------------------------------
          // Screen Descriptor

          out.writeShort(_width);
          out.writeShort(_height);

          out.writeByte(0x80); // 2bit
          out.writeByte(0);
          out.writeByte(0);

          //---------------------------------
          // Global Color Map

          // black
          out.writeByte(0x00);
          out.writeByte(0x00);
          out.writeByte(0x00);

          // white
          out.writeByte(0xff);
          out.writeByte(0xff);
          out.writeByte(0xff);

          //---------------------------------
          // Image Descriptor

          out.writeString(',');
          out.writeShort(0);
          out.writeShort(0);
          out.writeShort(_width);
          out.writeShort(_height);
          out.writeByte(0);

          //---------------------------------
          // Local Color Map

          //---------------------------------
          // Raster Data

          var lzwMinCodeSize = 2;
          var raster = getLZWRaster(lzwMinCodeSize);

          out.writeByte(lzwMinCodeSize);

          var offset = 0;

          while (raster.length - offset > 255) {
            out.writeByte(255);
            out.writeBytes(raster, offset, 255);
            offset += 255;
          }

          out.writeByte(raster.length - offset);
          out.writeBytes(raster, offset, raster.length - offset);
          out.writeByte(0x00);

          //---------------------------------
          // GIF Terminator
          out.writeString(';');
        };

        var bitOutputStream = function(out) {

          var _out = out;
          var _bitLength = 0;
          var _bitBuffer = 0;

          var _this = {};

          _this.write = function(data, length) {

            if ( (data >>> length) != 0) {
              throw new Error('length over');
            }

            while (_bitLength + length >= 8) {
              _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
              length -= (8 - _bitLength);
              data >>>= (8 - _bitLength);
              _bitBuffer = 0;
              _bitLength = 0;
            }

            _bitBuffer = (data << _bitLength) | _bitBuffer;
            _bitLength = _bitLength + length;
          };

          _this.flush = function() {
            if (_bitLength > 0) {
              _out.writeByte(_bitBuffer);
            }
          };

          return _this;
        };

        var getLZWRaster = function(lzwMinCodeSize) {

          var clearCode = 1 << lzwMinCodeSize;
          var endCode = (1 << lzwMinCodeSize) + 1;
          var bitLength = lzwMinCodeSize + 1;

          // Setup LZWTable
          var table = lzwTable();

          for (var i = 0; i < clearCode; i += 1) {
            table.add(String.fromCharCode(i) );
          }
          table.add(String.fromCharCode(clearCode) );
          table.add(String.fromCharCode(endCode) );

          var byteOut = byteArrayOutputStream();
          var bitOut = bitOutputStream(byteOut);

          // clear code
          bitOut.write(clearCode, bitLength);

          var dataIndex = 0;

          var s = String.fromCharCode(_data[dataIndex]);
          dataIndex += 1;

          while (dataIndex < _data.length) {

            var c = String.fromCharCode(_data[dataIndex]);
            dataIndex += 1;

            if (table.contains(s + c) ) {

              s = s + c;

            } else {

              bitOut.write(table.indexOf(s), bitLength);

              if (table.size() < 0xfff) {

                if (table.size() == (1 << bitLength) ) {
                  bitLength += 1;
                }

                table.add(s + c);
              }

              s = c;
            }
          }

          bitOut.write(table.indexOf(s), bitLength);

          // end code
          bitOut.write(endCode, bitLength);

          bitOut.flush();

          return byteOut.toByteArray();
        };

        var lzwTable = function() {

          var _map = {};
          var _size = 0;

          var _this = {};

          _this.add = function(key) {
            if (_this.contains(key) ) {
              throw new Error('dup key:' + key);
            }
            _map[key] = _size;
            _size += 1;
          };

          _this.size = function() {
            return _size;
          };

          _this.indexOf = function(key) {
            return _map[key];
          };

          _this.contains = function(key) {
            return typeof _map[key] != 'undefined';
          };

          return _this;
        };

        return _this;
      };

      var createImgTag = function(width, height, getPixel, alt) {

        var gif = gifImage(width, height);
        for (var y = 0; y < height; y += 1) {
          for (var x = 0; x < width; x += 1) {
            gif.setPixel(x, y, getPixel(x, y) );
          }
        }

        var b = byteArrayOutputStream();
        gif.write(b);

        var base64 = base64EncodeOutputStream();
        var bytes = b.toByteArray();
        for (var i = 0; i < bytes.length; i += 1) {
          base64.writeByte(bytes[i]);
        }
        base64.flush();

        var img = '';
        img += '<img';
        img += '\u0020src="';
        img += 'data:image/gif;base64,';
        img += base64;
        img += '"';
        img += '\u0020width="';
        img += width;
        img += '"';
        img += '\u0020height="';
        img += height;
        img += '"';
        if (alt) {
          img += '\u0020alt="';
          img += alt;
          img += '"';
        }
        img += '/>';

        return img;
      };

      //---------------------------------------------------------------------
      // returns qrcode function.

      return qrcode;
    }();

    (function (factory) {
      if (typeof define === 'function' && define.amd) {
          define([], factory);
      } else if (typeof exports === 'object') {
          module.exports = factory();
      }
    }(function () {
        return qrcode;
    }));
    //---------------------------------------------------------------------
    //
    // QR Code Generator for JavaScript UTF8 Support (optional)
    //
    // Copyright (c) 2011 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(qrcode) {

      //---------------------------------------------------------------------
      // overwrite qrcode.stringToBytes
      //---------------------------------------------------------------------

      qrcode.stringToBytes = function(s) {
        // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
        function toUTF8Array(str) {
          var utf8 = [];
          for (var i=0; i < str.length; i++) {
            var charcode = str.charCodeAt(i);
            if (charcode < 0x80) utf8.push(charcode);
            else if (charcode < 0x800) {
              utf8.push(0xc0 | (charcode >> 6),
                  0x80 | (charcode & 0x3f));
            }
            else if (charcode < 0xd800 || charcode >= 0xe000) {
              utf8.push(0xe0 | (charcode >> 12),
                  0x80 | ((charcode>>6) & 0x3f),
                  0x80 | (charcode & 0x3f));
            }
            // surrogate pair
            else {
              i++;
              // UTF-16 encodes 0x10000-0x10FFFF by
              // subtracting 0x10000 and splitting the
              // 20 bits of 0x0-0xFFFFF into two halves
              charcode = 0x10000 + (((charcode & 0x3ff)<<10)
                | (str.charCodeAt(i) & 0x3ff));
              utf8.push(0xf0 | (charcode >>18),
                  0x80 | ((charcode>>12) & 0x3f),
                  0x80 | ((charcode>>6) & 0x3f),
                  0x80 | (charcode & 0x3f));
            }
          }
          return utf8;
        }
        return toUTF8Array(s);
      };

    }(qrcode);

    return qrcode; // eslint-disable-line no-undef
}()));


================================================
FILE: test/qr-code.org.js
================================================
// 2346 lines (1867 sloc)  73.4 KB
class QrCodeOrg {
    static render(config, $element) {
        $element.appendChild(window.qrcode(config));
    }
}

/*! jquery-qrcode v0.14.0 - https://larsjung.de/jquery-qrcode/ */
(function(vendor_qrcode) {
    'use strict';

    var jq = window.jQuery;

    // Check if canvas is available in the browser (as Modernizr does)
    var hasCanvas = (function() {
        var elem = document.createElement('canvas');
        return !!(elem.getContext && elem.getContext('2d'));
    }());

    // Wrapper for the original QR code generator.
    function createQRCode(text, level, version, quiet) {
        var qr = {};

        var vqr = vendor_qrcode(version, level);
        vqr.addData(text);
        vqr.make();

        quiet = quiet || 0;

        var qrModuleCount = vqr.getModuleCount();
        var quietModuleCount = vqr.getModuleCount() + 2 * quiet;

        function isDark(row, col) {
            row -= quiet;
            col -= quiet;

            if (row < 0 || row >= qrModuleCount || col < 0 || col >= qrModuleCount) {
                return false;
            }
            return vqr.isDark(row, col);
        }

        function addBlank(l, t, r, b) {
            var prevIsDark = qr.isDark;
            var moduleSize = 1 / quietModuleCount;

            qr.isDark = function(row, col) {
                var ml = col * moduleSize;
                var mt = row * moduleSize;
                var mr = ml + moduleSize;
                var mb = mt + moduleSize;

                return prevIsDark(row, col) && (l > mr || ml > r || t > mb || mt > b);
            };
        }

        qr.text = text;
        qr.level = level;
        qr.version = version;
        qr.moduleCount = quietModuleCount;
        qr.isDark = isDark;
        qr.addBlank = addBlank;

        return qr;
    }

    // Returns a minimal QR code for the given text starting with version `minVersion`.
    // Returns `undefined` if `text` is too long to be encoded in `maxVersion`.
    function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
        minVersion = Math.max(1, minVersion || 1);
        maxVersion = Math.min(40, maxVersion || 40);
        for (var version = minVersion; version <= maxVersion; version += 1) {
            try {
                return createQRCode(text, level, version, quiet);
            } catch (err) { /* empty */ }
        }
        return undefined;
    }

    function drawBackgroundLabel(qr, context, settings) {
        var size = settings.size;
        var font = 'bold ' + settings.mSize * size + 'px ' + settings.fontname;
        var ctx = jq('<canvas/>')[0].getContext('2d');

        ctx.font = font;

        var w = ctx.measureText(settings.label).width;
        var sh = settings.mSize;
        var sw = w / size;
        var sl = (1 - sw) * settings.mPosX;
        var st = (1 - sh) * settings.mPosY;
        var sr = sl + sw;
        var sb = st + sh;
        var pad = 0.01;

        if (settings.mode === 1) {
            // Strip
            qr.addBlank(0, st - pad, size, sb + pad);
        } else {
            // Box
            qr.addBlank(sl - pad, st - pad, sr + pad, sb + pad);
        }

        context.fillStyle = settings.fontcolor;
        context.font = font;
        context.fillText(settings.label, sl * size, st * size + 0.75 * settings.mSize * size);
    }

    function drawBackgroundImage(qr, context, settings) {
        var size = settings.size;
        var w = settings.image.naturalWidth || 1;
        var h = settings.image.naturalHeight || 1;
        var sh = settings.mSize;
        var sw = sh * w / h;
        var sl = (1 - sw) * settings.mPosX;
        var st = (1 - sh) * settings.mPosY;
        var sr = sl + sw;
        var sb = st + sh;
        var pad = 0.01;

        if (settings.mode === 3) {
            // Strip
            qr.addBlank(0, st - pad, size, sb + pad);
        } else {
            // Box
            qr.addBlank(sl - pad, st - pad, sr + pad, sb + pad);
        }

        context.drawImage(settings.image, sl * size, st * size, sw * size, sh * size);
    }

    function drawBackground(qr, context, settings) {
        if (settings.background == 'img') {
            context.drawImage(settings.background, 0, 0, settings.size, settings.size);
        } else if (settings.background) {
            context.fillStyle = settings.background;
            context.fillRect(settings.left, settings.top, settings.size, settings.size);
        }

        var mode = settings.mode;
        if (mode === 1 || mode === 2) {
            drawBackgroundLabel(qr, context, settings);
        } else if (mode === 3 || mode === 4) {
            drawBackgroundImage(qr, context, settings);
        }
    }

    function drawModuleDefault(qr, context, settings, left, top, width, row, col) {
        if (qr.isDark(row, col)) {
            context.rect(left, top, width, width);
        }
    }

    function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        if (nw) {
            ctx.moveTo(l + rad, t);
        } else {
            ctx.moveTo(l, t);
        }

        if (ne) {
            ctx.lineTo(r - rad, t);
            ctx.arcTo(r, t, r, b, rad);
        } else {
            ctx.lineTo(r, t);
        }

        if (se) {
            ctx.lineTo(r, b - rad);
            ctx.arcTo(r, b, l, b, rad);
        } else {
            ctx.lineTo(r, b);
        }

        if (sw) {
            ctx.lineTo(l + rad, b);
            ctx.arcTo(l, b, l, t, rad);
        } else {
            ctx.lineTo(l, b);
        }

        if (nw) {
            ctx.lineTo(l, t + rad);
            ctx.arcTo(l, t, r, t, rad);
        } else {
            ctx.lineTo(l, t);
        }
    }

    function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
        if (nw) {
            ctx.moveTo(l + rad, t);
            ctx.lineTo(l, t);
            ctx.lineTo(l, t + rad);
            ctx.arcTo(l, t, l + rad, t, rad);
        }

        if (ne) {
            ctx.moveTo(r - rad, t);
            ctx.lineTo(r, t);
            ctx.lineTo(r, t + rad);
            ctx.arcTo(r, t, r - rad, t, rad);
        }

        if (se) {
            ctx.moveTo(r - rad, b);
            ctx.lineTo(r, b);
            ctx.lineTo(r, b - rad);
            ctx.arcTo(r, b, r - rad, b, rad);
        }

        if (sw) {
            ctx.moveTo(l + rad, b);
            ctx.lineTo(l, b);
            ctx.lineTo(l, b - rad);
            ctx.arcTo(l, b, l + rad, b, rad);
        }
    }

    function drawModuleRounded(qr, context, settings, left, top, width, row, col) {
        var isDark = qr.isDark;
        var right = left + width;
        var bottom = top + width;
        var radius = settings.radius * width;
        var rowT = row - 1;
        var rowB = row + 1;
        var colL = col - 1;
        var colR = col + 1;
        var center = isDark(row, col);
        var northwest = isDark(rowT, colL);
        var north = isDark(rowT, col);
        var northeast = isDark(rowT, colR);
        var east = isDark(row, colR);
        var southeast = isDark(rowB, colR);
        var south = isDark(rowB, col);
        var southwest = isDark(rowB, colL);
        var west = isDark(row, colL);

        if (center) {
            drawModuleRoundedDark(context, left, top, right, bottom, radius, !north && !west, !north && !east, !south && !east, !south && !west);
        } else {
            drawModuleRoundendLight(context, left, top, right, bottom, radius, north && west && northwest, north && east && northeast, south && east && southeast, south && west && southwest);
        }
    }

    function drawModules(qr, context, settings) {
        var moduleCount = qr.moduleCount;
        var moduleSize = settings.size / moduleCount;
        var fn = drawModuleDefault;
        var row;
        var col;

        if (settings.radius > 0 && settings.radius <= 0.5) {
            fn = drawModuleRounded;
        }

        context.beginPath();
        for (row = 0; row < moduleCount; row += 1) {
            for (col = 0; col < moduleCount; col += 1) {
                var l = settings.left + col * moduleSize;
                var t = settings.top + row * moduleSize;
                var w = moduleSize;

                fn(qr, context, settings, l, t, w, row, col);
            }
        }
        if (settings.fill == 'img') {
            context.strokeStyle = 'rgba(0,0,0,0.5)';
            context.lineWidth = 2;
            context.stroke();
            var prev = context.globalCompositeOperation;
            context.globalCompositeOperation = 'destination-out';
            context.fill();
            context.globalCompositeOperation = prev;

            context.clip();
            context.drawImage(settings.fill, 0, 0, settings.size, settings.size);
            context.restore();
        } else {
            context.fillStyle = settings.fill;
            context.fill();
        }
    }

    // Draws QR code to the given `canvas` and returns it.
    function drawOnCanvas(canvas, settings) {
        var qr = createMinQRCode(settings.text, settings.ecLevel, settings.minVersion, settings.maxVersion, settings.quiet);
        if (!qr) {
            return null;
        }

        //         var $canvas = jq(canvas).data('qrcode', qr);
        // var $canvas = canvas;
        var context = canvas.getContext('2d');

        drawBackground(qr, context, settings);
        drawModules(qr, context, settings);

        return canvas;
    }

    // Returns a `canvas` element representing the QR code for the given settings.
    function createCanvas(settings) {
        var $canvas = document.createElement('canvas');
        $canvas.width = settings.size;
        $canvas.height = settings.size;
        return drawOnCanvas($canvas, settings);
    }

    // Returns an `image` element representing the QR code for the given settings.
    function createImage(settings) {
        return jq('<img/>').attr('src', createCanvas(settings)[0].toDataURL('image/png'));
    }

    // Returns a `div` element representing the QR code for the given settings.
    function createDiv(settings) {
        var qr = createMinQRCode(settings.text, settings.ecLevel, settings.minVersion, settings.maxVersion, settings.quiet);
        if (!qr) {
            return null;
        }

        // some shortcuts to improve compression
        var settings_size = settings.size;
        var settings_bgColor = settings.background;
        var math_floor = Math.floor;

        var moduleCount = qr.moduleCount;
        var moduleSize = math_floor(settings_size / moduleCount);
        var offset = math_floor(0.5 * (settings_size - moduleSize * moduleCount));

        var row;
        var col;

        var containerCSS = {
            position: 'relative',
            left: 0,
            top: 0,
            padding: 0,
            margin: 0,
            width: settings_size,
            height: settings_size
        };
        var darkCSS = {
            position: 'absolute',
            padding: 0,
            margin: 0,
            width: moduleSize,
            height: moduleSize,
            'background-color': settings.fill
        };

        var $div = jq('<div/>').data('qrcode', qr).css(containerCSS);

        if (settings_bgColor) {
            $div.css('background-color', settings_bgColor);
        }

        for (row = 0; row < moduleCount; row += 1) {
            for (col = 0; col < moduleCount; col += 1) {
                if (qr.isDark(row, col)) {
                    jq('<div/>')
                        .css(darkCSS)
                        .css({
                            left: offset + col * moduleSize,
                            top: offset + row * moduleSize
                        })
                        .appendTo($div);
                }
            }
        }

        return $div;
    }

    function createHTML(settings) {
        if (hasCanvas && settings.render === 'canvas') {
            return createCanvas(settings);
        } else if (hasCanvas && settings.render === 'image') {
            return createImage(settings);
        }

        return createDiv(settings);
    }

    // Plugin
    // ======

    // Default settings
    // ----------------
    var defaults = {
        // render method: `'canvas'`, `'image'` or `'div'`
        render: 'canvas',

        // version range somewhere in 1 .. 40
        minVersion: 1,
        maxVersion: 40,

        // error correction level: `'L'`, `'M'`, `'Q'` or `'H'`
        ecLevel: 'L',

        // offset in pixel if drawn onto existing canvas
        left: 0,
        top: 0,

        // size in pixel
        size: 200,

        // code color or image element
        fill: '#000',

        // background color or image element, `null` for transparent background
        background: null,

        // content
        text: 'no text',

        // corner radius relative to module width: 0.0 .. 0.5
        radius: 0,

        // quiet zone in modules
        quiet: 0,

        // modes
        // 0: normal
        // 1: label strip
        // 2: label box
        // 3: image strip
        // 4: image box
        mode: 0,

        mSize: 0.1,
        mPosX: 0.5,
        mPosY: 0.5,

        label: 'no label',
        fontname: 'sans',
        fontcolor: '#000',

        image: null
    };

    // // Register the plugin
    // // -------------------
    window.qrcode = function(options) {
        var settings = {};
        Object.assign(settings, defaults, options);
        return createHTML(settings)
    };
}(function() {
    // `qrcode` is the single public function defined by the `QR Code Generator`
    //---------------------------------------------------------------------
    //
    // QR Code Generator 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
    //
    //---------------------------------------------------------------------

    var qrcode = function() {

        //---------------------------------------------------------------------
        // qrcode
        //---------------------------------------------------------------------

        /**
         * qrcode
         * @param typeNumber 1 to 40
         * @param errorCorrectLevel 'L','M','Q','H'
         */
        var qrcode = function(typeNumber, errorCorrectLevel) {

            var PAD0 = 0xEC;
            var PAD1 = 0x11;

            var _typeNumber = typeNumber;
            var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];
            var _modules = null;
            var _moduleCount = 0;
            var _dataCache = null;
            var _dataList = new Array();

            var _this = {};

            var makeImpl = function(test, maskPattern) {

                _moduleCount = _typeNumber * 4 + 17;
                _modules = function(moduleCount) {
                    var modules = new Array(moduleCount);
                    for (var row = 0; row < moduleCount; row += 1) {
                        modules[row] = new Array(moduleCount);
                        for (var col = 0; col < moduleCount; col += 1) {
                            modules[row][col] = null;
                        }
                    }
                    return modules;
                }(_moduleCount);

                setupPositionProbePattern(0, 0);
                setupPositionProbePattern(_moduleCount - 7, 0);
                setupPositionProbePattern(0, _moduleCount - 7);
                setupPositionAdjustPattern();
                setupTimingPattern();
                setupTypeInfo(test, maskPattern);

                if (_typeNumber >= 7) {
                    setupTypeNumber(test);
                }

                if (_dataCache == null) {
                    _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);
                }

                mapData(_dataCache, maskPattern);
            };

            var setupPositionProbePattern = function(row, col) {

                for (var r = -1; r <= 7; r += 1) {

                    if (row + r <= -1 || _moduleCount <= row + r) continue;

                    for (var c = -1; c <= 7; c += 1) {

                        if (col + c <= -1 || _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)) {
                            _modules[row + r][col + c] = true;
                        } else {
                            _modules[row + r][col + c] = false;
                        }
                    }
                }
            };

            var getBestMaskPattern = function() {

                var minLostPoint = 0;
                var pattern = 0;

                for (var i = 0; i < 8; i += 1) {

                    makeImpl(true, i);

                    var lostPoint = QRUtil.getLostPoint(_this);

                    if (i == 0 || minLostPoint > lostPoint) {
                        minLostPoint = lostPoint;
                        pattern = i;
                    }
                }

                return pattern;
            };

            var setupTimingPattern = function() {

                for (var r = 8; r < _moduleCount - 8; r += 1) {
                    if (_modules[r][6] != null) {
                        continue;
                    }
                    _modules[r][6] = (r % 2 == 0);
                }

                for (var c = 8; c < _moduleCount - 8; c += 1) {
                    if (_modules[6][c] != null) {
                        continue;
                    }
                    _modules[6][c] = (c % 2 == 0);
                }
            };

            var setupPositionAdjustPattern = function() {

                var pos = QRUtil.getPatternPosition(_typeNumber);

                for (var i = 0; i < pos.length; i += 1) {

                    for (var j = 0; j < pos.length; j += 1) {

                        var row = pos[i];
                        var col = pos[j];

                        if (_modules[row][col] != null) {
                            continue;
                        }

                        for (var r = -2; r <= 2; r += 1) {

                            for (var c = -2; c <= 2; c += 1) {

                                if (r == -2 || r == 2 || c == -2 || c == 2 ||
                                    (r == 0 && c == 0)) {
                                    _modules[row + r][col + c] = true;
                                } else {
                                    _modules[row + r][col + c] = false;
                                }
                            }
                        }
                    }
                }
            };

            var setupTypeNumber = function(test) {

                var bits = QRUtil.getBCHTypeNumber(_typeNumber);

                for (var i = 0; i < 18; i += 1) {
                    var mod = (!test && ((bits >> i) & 1) == 1);
                    _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
                }

                for (var i = 0; i < 18; i += 1) {
                    var mod = (!test && ((bits >> i) & 1) == 1);
                    _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
                }
            };

            var setupTypeInfo = function(test, maskPattern) {

                var data = (_errorCorrectLevel << 3) | maskPattern;
                var bits = QRUtil.getBCHTypeInfo(data);

                // vertical
                for (var i = 0; i < 15; i += 1) {

                    var mod = (!test && ((bits >> i) & 1) == 1);

                    if (i < 6) {
                        _modules[i][8] = mod;
                    } else if (i < 8) {
                        _modules[i + 1][8] = mod;
                    } else {
                        _modules[_moduleCount - 15 + i][8] = mod;
                    }
                }

                // horizontal
                for (var i = 0; i < 15; i += 1) {

                    var mod = (!test && ((bits >> i) & 1) == 1);

                    if (i < 8) {
                        _modules[8][_moduleCount - i - 1] = mod;
                    } else if (i < 9) {
                        _modules[8][15 - i - 1 + 1] = mod;
                    } else {
                        _modules[8][15 - i - 1] = mod;
                    }
                }

                // fixed module
                _modules[_moduleCount - 8][8] = (!test);
            };

            var mapData = function(data, maskPattern) {

                var inc = -1;
                var row = _moduleCount - 1;
                var bitIndex = 7;
                var byteIndex = 0;
                var maskFunc = QRUtil.getMaskFunction(maskPattern);

                for (var col = _moduleCount - 1; col > 0; col -= 2) {

                    if (col == 6) col -= 1;

                    while (true) {

                        for (var c = 0; c < 2; c += 1) {

                            if (_modules[row][col - c] == null) {

                                var dark = false;

                                if (byteIndex < data.length) {
                                    dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);
                                }

                                var mask = maskFunc(row, col - c);

                                if (mask) {
                                    dark = !dark;
                                }

                                _modules[row][col - c] = dark;
                                bitIndex -= 1;

                                if (bitIndex == -1) {
                                    byteIndex += 1;
                                    bitIndex = 7;
                                }
                            }
                        }

                        row += inc;

                        if (row < 0 || _moduleCount <= row) {
                            row -= inc;
                            inc = -inc;
                            break;
                        }
                    }
                }
            };

            var 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 += 1) {

                    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 += 1) {
                        dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
                    }
                    offset += dcCount;

                    var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
                    var rawPoly = 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 += 1) {
                        var modIndex = i + modPoly.getLength() - ecdata[r].length;
                        ecdata[r][i] = (modIndex >= 0) ? modPoly.getAt(modIndex) : 0;
                    }
                }

                var totalCodeCount = 0;
                for (var i = 0; i < rsBlocks.length; i += 1) {
                    totalCodeCount += rsBlocks[i].totalCount;
                }

                var data = new Array(totalCodeCount);
                var index = 0;

                for (var i = 0; i < maxDcCount; i += 1) {
                    for (var r = 0; r < rsBlocks.length; r += 1) {
                        if (i < dcdata[r].length) {
                            data[index] = dcdata[r][i];
                            index += 1;
                        }
                    }
                }

                for (var i = 0; i < maxEcCount; i += 1) {
                    for (var r = 0; r < rsBlocks.length; r += 1) {
                        if (i < ecdata[r].length) {
                            data[index] = ecdata[r][i];
                            index += 1;
                        }
                    }
                }

                return data;
            };

            var createData = function(typeNumber, errorCorrectLevel, dataList) {

                var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);

                var buffer = qrBitBuffer();

                for (var i = 0; i < dataList.length; i += 1) {
                    var data = dataList[i];
                    buffer.put(data.getMode(), 4);
                    buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber));
                    data.write(buffer);
                }

                // calc num max data.
                var totalDataCount = 0;
                for (var i = 0; i < rsBlocks.length; i += 1) {
                    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(PAD0, 8);

                    if (buffer.getLengthInBits() >= totalDataCount * 8) {
                        break;
                    }
                    buffer.put(PAD1, 8);
                }

                return createBytes(buffer, rsBlocks);
            };

            _this.addData = function(data) {
                var newData = qr8BitByte(data);
                _dataList.push(newData);
                _dataCache = null;
            };

            _this.isDark = function(row, col) {
                if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
                    throw new Error(row + ',' + col);
                }
                return _modules[row][col];
            };

            _this.getModuleCount = function() {
                return _moduleCount;
            };

            _this.make = function() {
                makeImpl(false, getBestMaskPattern());
            };

            _this.createTableTag = function(cellSize, margin) {

                cellSize = cellSize || 2;
                margin = (typeof margin == 'undefined') ? cellSize * 4 : margin;

                var qrHtml = '';

                qrHtml += '<table style="';
                qrHtml += ' border-width: 0px; border-style: none;';
                qrHtml += ' border-collapse: collapse;';
                qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
                qrHtml += '">';
                qrHtml += '<tbody>';

                for (var r = 0; r < _this.getModuleCount(); r += 1) {

                    qrHtml += '<tr>';

                    for (var c = 0; c < _this.getModuleCount(); c += 1) {
                        qrHtml += '<td style="';
                        qrHtml += ' border-width: 0px; border-style: none;';
                        qrHtml += ' border-collapse: collapse;';
                        qrHtml += ' padding: 0px; margin: 0px;';
                        qrHtml += ' width: ' + cellSize + 'px;';
                        qrHtml += ' height: ' + cellSize + 'px;';
                        qrHtml += ' background-color: ';
                        qrHtml += _this.isDark(r, c) ? '#000000' : '#ffffff';
                        qrHtml += ';';
                        qrHtml += '"/>';
                    }

                    qrHtml += '</tr>';
                }

                qrHtml += '</tbody>';
                qrHtml += '</table>';

                return qrHtml;
            };

            _this.createImgTag = function(cellSize, margin) {

                cellSize = cellSize || 2;
                margin = (typeof margin == 'undefined') ? cellSize * 4 : margin;

                var size = _this.getModuleCount() * cellSize + margin * 2;
                var min = margin;
                var max = size - margin;

                return createImgTag(size, size, function(x, y) {
                    if (min <= x && x < max && min <= y && y < max) {
                        var c = Math.floor((x - min) / cellSize);
                        var r = Math.floor((y - min) / cellSize);
                        return _this.isDark(r, c) ? 0 : 1;
                    } else {
                        return 1;
                    }
                });
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // qrcode.stringToBytes
        //---------------------------------------------------------------------

        qrcode.stringToBytes = function(s) {
            var bytes = new Array();
            for (var i = 0; i < s.length; i += 1) {
                var c = s.charCodeAt(i);
                bytes.push(c & 0xff);
            }
            return bytes;
        };

        //---------------------------------------------------------------------
        // qrcode.createStringToBytes
        //---------------------------------------------------------------------

        /**
         * @param unicodeData base64 string of byte array.
         * [16bit Unicode],[16bit Bytes], ...
         * @param numChars
         */
        qrcode.createStringToBytes = function(unicodeData, numChars) {

            // create conversion map.

            var unicodeMap = function() {

                var bin = base64DecodeInputStream(unicodeData);
                var read = function() {
                    var b = bin.read();
                    if (b == -1) throw new Error();
                    return b;
                };

                var count = 0;
                var unicodeMap = {};
                while (true) {
                    var b0 = bin.read();
                    if (b0 == -1) break;
                    var b1 = read();
                    var b2 = read();
                    var b3 = read();
                    var k = String.fromCharCode((b0 << 8) | b1);
                    var v = (b2 << 8) | b3;
                    unicodeMap[k] = v;
                    count += 1;
                }
                if (count != numChars) {
                    throw new Error(count + ' != ' + numChars);
                }

                return unicodeMap;
            }();

            var unknownChar = '?'.charCodeAt(0);

            return function(s) {
                var bytes = new Array();
                for (var i = 0; i < s.length; i += 1) {
                    var c = s.charCodeAt(i);
                    if (c < 128) {
                        bytes.push(c);
                    } else {
                        var b = unicodeMap[s.charAt(i)];
                        if (typeof b == 'number') {
                            if ((b & 0xff) == b) {
                                // 1byte
                                bytes.push(b);
                            } else {
                                // 2bytes
                                bytes.push(b >>> 8);
                                bytes.push(b & 0xff);
                            }
                        } else {
                            bytes.push(unknownChar);
                        }
                    }
                }
                return bytes;
            };
        };

        //---------------------------------------------------------------------
        // QRMode
        //---------------------------------------------------------------------

        var QRMode = {
            MODE_NUMBER: 1 << 0,
            MODE_ALPHA_NUM: 1 << 1,
            MODE_8BIT_BYTE: 1 << 2,
            MODE_KANJI: 1 << 3
        };

        //---------------------------------------------------------------------
        // QRErrorCorrectLevel
        //---------------------------------------------------------------------

        var 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 = function() {

            var 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]
            ];
            var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
            var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
            var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);

            var _this = {};

            var getBCHDigit = function(data) {
                var digit = 0;
                while (data != 0) {
                    digit += 1;
                    data >>>= 1;
                }
                return digit;
            };

            _this.getBCHTypeInfo = function(data) {
                var d = data << 10;
                while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
                    d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15)));
                }
                return ((data << 10) | d) ^ G15_MASK;
            };

            _this.getBCHTypeNumber = function(data) {
                var d = data << 12;
                while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
                    d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18)));
                }
                return (data << 12) | d;
            };

            _this.getPatternPosition = function(typeNumber) {
                return PATTERN_POSITION_TABLE[typeNumber - 1];
            };

            _this.getMaskFunction = function(maskPattern) {

                switch (maskPattern) {

                    case QRMaskPattern.PATTERN000:
                        return function(i, j) { return (i + j) % 2 == 0; };
                    case QRMaskPattern.PATTERN001:
                        return function(i, j) { return i % 2 == 0; };
                    case QRMaskPattern.PATTERN010:
                        return function(i, j) { return j % 3 == 0; };
                    case QRMaskPattern.PATTERN011:
                        return function(i, j) { return (i + j) % 3 == 0; };
                    case QRMaskPattern.PATTERN100:
                        return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; };
                    case QRMaskPattern.PATTERN101:
                        return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
                    case QRMaskPattern.PATTERN110:
                        return function(i, j) { return ((i * j) % 2 + (i * j) % 3) % 2 == 0; };
                    case QRMaskPattern.PATTERN111:
                        return function(i, j) { return ((i * j) % 3 + (i + j) % 2) % 2 == 0; };

                    default:
                        throw new Error('bad maskPattern:' + maskPattern);
                }
            };

            _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
                var a = qrPolynomial([1], 0);
                for (var i = 0; i < errorCorrectLength; i += 1) {
                    a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0));
                }
                return a;
            };

            _this.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);
                }
            };

            _this.getLostPoint = function(qrcode) {

                var moduleCount = qrcode.getModuleCount();

                var lostPoint = 0;

                // LEVEL1

                for (var row = 0; row < moduleCount; row += 1) {
                    for (var col = 0; col < moduleCount; col += 1) {

                        var sameCount = 0;
                        var dark = qrcode.isDark(row, col);

                        for (var r = -1; r <= 1; r += 1) {

                            if (row + r < 0 || moduleCount <= row + r) {
                                continue;
                            }

                            for (var c = -1; c <= 1; c += 1) {

                                if (col + c < 0 || moduleCount <= col + c) {
                                    continue;
                                }

                                if (r == 0 && c == 0) {
                                    continue;
                                }

                                if (dark == qrcode.isDark(row + r, col + c)) {
                                    sameCount += 1;
                                }
                            }
                        }

                        if (sameCount > 5) {
                            lostPoint += (3 + sameCount - 5);
                        }
                    }
                };

                // LEVEL2

                for (var row = 0; row < moduleCount - 1; row += 1) {
                    for (var col = 0; col < moduleCount - 1; col += 1) {
                        var count = 0;
                        if (qrcode.isDark(row, col)) count += 1;
                        if (qrcode.isDark(row + 1, col)) count += 1;
                        if (qrcode.isDark(row, col + 1)) count += 1;
                        if (qrcode.isDark(row + 1, col + 1)) count += 1;
                        if (count == 0 || count == 4) {
                            lostPoint += 3;
                        }
                    }
                }

                // LEVEL3

                for (var row = 0; row < moduleCount; row += 1) {
                    for (var col = 0; col < moduleCount - 6; col += 1) {
                        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 += 1) {
                    for (var row = 0; row < moduleCount - 6; row += 1) {
                        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 += 1) {
                    for (var row = 0; row < moduleCount; row += 1) {
                        if (qrcode.isDark(row, col)) {
                            darkCount += 1;
                        }
                    }
                }

                var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
                lostPoint += ratio * 10;

                return lostPoint;
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // QRMath
        //---------------------------------------------------------------------

        var QRMath = function() {

            var EXP_TABLE = new Array(256);
            var LOG_TABLE = new Array(256);

            // initialize tables
            for (var i = 0; i < 8; i += 1) {
                EXP_TABLE[i] = 1 << i;
            }
            for (var i = 8; i < 256; i += 1) {
                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 += 1) {
                LOG_TABLE[EXP_TABLE[i]] = i;
            }

            var _this = {};

            _this.glog = function(n) {

                if (n < 1) {
                    throw new Error('glog(' + n + ')');
                }

                return LOG_TABLE[n];
            };

            _this.gexp = function(n) {

                while (n < 0) {
                    n += 255;
                }

                while (n >= 256) {
                    n -= 255;
                }

                return EXP_TABLE[n];
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // qrPolynomial
        //---------------------------------------------------------------------

        function qrPolynomial(num, shift) {

            if (typeof num.length == 'undefined') {
                throw new Error(num.length + '/' + shift);
            }

            var _num = function() {
                var offset = 0;
                while (offset < num.length && num[offset] == 0) {
                    offset += 1;
                }
                var _num = new Array(num.length - offset + shift);
                for (var i = 0; i < num.length - offset; i += 1) {
                    _num[i] = num[i + offset];
                }
                return _num;
            }();

            var _this = {};

            _this.getAt = function(index) {
                return _num[index];
            };

            _this.getLength = function() {
                return _num.length;
            };

            _this.multiply = function(e) {

                var num = new Array(_this.getLength() + e.getLength() - 1);

                for (var i = 0; i < _this.getLength(); i += 1) {
                    for (var j = 0; j < e.getLength(); j += 1) {
                        num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i)) + QRMath.glog(e.getAt(j)));
                    }
                }

                return qrPolynomial(num, 0);
            };

            _this.mod = function(e) {

                if (_this.getLength() - e.getLength() < 0) {
                    return _this;
                }

                var ratio = QRMath.glog(_this.getAt(0)) - QRMath.glog(e.getAt(0));

                var num = new Array(_this.getLength());
                for (var i = 0; i < _this.getLength(); i += 1) {
                    num[i] = _this.getAt(i);
                }

                for (var i = 0; i < e.getLength(); i += 1) {
                    num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i)) + ratio);
                }

                // recursive call
                return qrPolynomial(num, 0).mod(e);
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // QRRSBlock
        //---------------------------------------------------------------------

        var QRRSBlock = function() {

            var 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],

                // 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]
            ];

            var qrRSBlock = function(totalCount, dataCount) {
                var _this = {};
                _this.totalCount = totalCount;
                _this.dataCount = dataCount;
                return _this;
            };

            var _this = {};

            var getRsBlockTable = function(typeNumber, errorCorrectLevel) {

                switch (errorCorrectLevel) {
                    case QRErrorCorrectLevel.L:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
                    case QRErrorCorrectLevel.M:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
                    case QRErrorCorrectLevel.Q:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
                    case QRErrorCorrectLevel.H:
                        return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
                    default:
                        return undefined;
                }
            };

            _this.getRSBlocks = function(typeNumber, errorCorrectLevel) {

                var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);

                if (typeof 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 += 1) {

                    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 += 1) {
                        list.push(qrRSBlock(totalCount, dataCount));
                    }
                }

                return list;
            };

            return _this;
        }();

        //---------------------------------------------------------------------
        // qrBitBuffer
        //---------------------------------------------------------------------

        var qrBitBuffer = function() {

            var _buffer = new Array();
            var _length = 0;

            var _this = {};

            _this.getBuffer = function() {
                return _buffer;
            };

            _this.getAt = function(index) {
                var bufIndex = Math.floor(index / 8);
                return ((_buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;
            };

            _this.put = function(num, length) {
                for (var i = 0; i < length; i += 1) {
                    _this.putBit(((num >>> (length - i - 1)) & 1) == 1);
                }
            };

            _this.getLengthInBits = function() {
                return _length;
            };

            _this.putBit = function(bit) {

                var bufIndex = Math.floor(_length / 8);
                if (_buffer.length <= bufIndex) {
                    _buffer.push(0);
                }

                if (bit) {
                    _buffer[bufIndex] |= (0x80 >>> (_length % 8));
                }

                _length += 1;
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // qr8BitByte
        //---------------------------------------------------------------------

        var qr8BitByte = function(data) {

            var _mode = QRMode.MODE_8BIT_BYTE;
            var _data = data;
            var _bytes = qrcode.stringToBytes(data);

            var _this = {};

            _this.getMode = function() {
                return _mode;
            };

            _this.getLength = function(buffer) {
                return _bytes.length;
            };

            _this.write = function(buffer) {
                for (var i = 0; i < _bytes.length; i += 1) {
                    buffer.put(_bytes[i], 8);
                }
            };

            return _this;
        };

        //=====================================================================
        // GIF Support etc.
        //

        //---------------------------------------------------------------------
        // byteArrayOutputStream
        //---------------------------------------------------------------------

        var byteArrayOutputStream = function() {

            var _bytes = new Array();

            var _this = {};

            _this.writeByte = function(b) {
                _bytes.push(b & 0xff);
            };

            _this.writeShort = function(i) {
                _this.writeByte(i);
                _this.writeByte(i >>> 8);
            };

            _this.writeBytes = function(b, off, len) {
                off = off || 0;
                len = len || b.length;
                for (var i = 0; i < len; i += 1) {
                    _this.writeByte(b[i + off]);
                }
            };

            _this.writeString = function(s) {
                for (var i = 0; i < s.length; i += 1) {
                    _this.writeByte(s.charCodeAt(i));
                }
            };

            _this.toByteArray = function() {
                return _bytes;
            };

            _this.toString = function() {
                var s = '';
                s += '[';
                for (var i = 0; i < _bytes.length; i += 1) {
                    if (i > 0) {
                        s += ',';
                    }
                    s += _bytes[i];
                }
                s += ']';
                return s;
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // base64EncodeOutputStream
        //---------------------------------------------------------------------

        var base64EncodeOutputStream = function() {

            var _buffer = 0;
            var _buflen = 0;
            var _length = 0;
            var _base64 = '';

            var _this = {};

            var writeEncoded = function(b) {
                _base64 += String.fromCharCode(encode(b & 0x3f));
            };

            var encode = function(n) {
                if (n < 0) {
                    // error.
                } else if (n < 26) {
                    return 0x41 + n;
                } else if (n < 52) {
                    return 0x61 + (n - 26);
                } else if (n < 62) {
                    return 0x30 + (n - 52);
                } else if (n == 62) {
                    return 0x2b;
                } else if (n == 63) {
                    return 0x2f;
                }
                throw new Error('n:' + n);
            };

            _this.writeByte = function(n) {

                _buffer = (_buffer << 8) | (n & 0xff);
                _buflen += 8;
                _length += 1;

                while (_buflen >= 6) {
                    writeEncoded(_buffer >>> (_buflen - 6));
                    _buflen -= 6;
                }
            };

            _this.flush = function() {

                if (_buflen > 0) {
                    writeEncoded(_buffer << (6 - _buflen));
                    _buffer = 0;
                    _buflen = 0;
                }

                if (_length % 3 != 0) {
                    // padding
                    var padlen = 3 - _length % 3;
                    for (var i = 0; i < padlen; i += 1) {
                        _base64 += '=';
                    }
                }
            };

            _this.toString = function() {
                return _base64;
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // base64DecodeInputStream
        //---------------------------------------------------------------------

        var base64DecodeInputStream = function(str) {

            var _str = str;
            var _pos = 0;
            var _buffer = 0;
            var _buflen = 0;

            var _this = {};

            _this.read = function() {

                while (_buflen < 8) {

                    if (_pos >= _str.length) {
                        if (_buflen == 0) {
                            return -1;
                        }
                        throw new Error('unexpected end of file./' + _buflen);
                    }

                    var c = _str.charAt(_pos);
                    _pos += 1;

                    if (c == '=') {
                        _buflen = 0;
                        return -1;
                    } else if (c.match(/^\s$/)) {
                        // ignore if whitespace.
                        continue;
                    }

                    _buffer = (_buffer << 6) | decode(c.charCodeAt(0));
                    _buflen += 6;
                }

                var n = (_buffer >>> (_buflen - 8)) & 0xff;
                _buflen -= 8;
                return n;
            };

            var decode = function(c) {
                if (0x41 <= c && c <= 0x5a) {
                    return c - 0x41;
                } else if (0x61 <= c && c <= 0x7a) {
                    return c - 0x61 + 26;
                } else if (0x30 <= c && c <= 0x39) {
                    return c - 0x30 + 52;
                } else if (c == 0x2b) {
                    return 62;
                } else if (c == 0x2f) {
                    return 63;
                } else {
                    throw new Error('c:' + c);
                }
            };

            return _this;
        };

        //---------------------------------------------------------------------
        // gifImage (B/W)
        //---------------------------------------------------------------------

        var gifImage = function(width, height) {

            var _width = width;
            var _height = height;
            var _data = new Array(width * height);

            var _this = {};

            _this.setPixel = function(x, y, pixel) {
                _data[y * _width + x] = pixel;
            };

            _this.write = function(out) {

                //---------------------------------
                // GIF Signature

                out.writeString('GIF87a');

                //---------------------------------
                // Screen Descriptor

                out.writeShort(_width);
                out.writeShort(_height);

                out.writeByte(0x80); // 2bit
                out.writeByte(0);
                out.writeByte(0);

                //---------------------------------
                // Global Color Map

                // black
                out.writeByte(0x00);
                out.writeByte(0x00);
                out.writeByte(0x00);

                // white
                out.writeByte(0xff);
                out.writeByte(0xff);
                out.writeByte(0xff);

                //---------------------------------
                // Image Descriptor

                out.writeString(',');
                out.writeShort(0);
                out.writeShort(0);
                out.writeShort(_width);
                out.writeShort(_height);
                out.writeByte(0);

                //---------------------------------
                // Local Color Map

                //---------------------------------
                // Raster Data

                var lzwMinCodeSize = 2;
                var raster = getLZWRaster(lzwMinCodeSize);

                out.writeByte(lzwMinCodeSize);

                var offset = 0;

                while (raster.length - offset > 255) {
                    out.writeByte(255);
                    out.writeBytes(raster, offset, 255);
                    offset += 255;
                }

                out.writeByte(raster.length - offset);
                out.writeBytes(raster, offset, raster.length - offset);
                out.writeByte(0x00);

                //---------------------------------
                // GIF Terminator
                out.writeString(';');
            };

            var bitOutputStream = function(out) {

                var _out = out;
                var _bitLength = 0;
                var _bitBuffer = 0;

                var _this = {};

                _this.write = function(data, length) {

                    if ((data >>> length) != 0) {
                        throw new Error('length over');
                    }

                    while (_bitLength + length >= 8) {
                        _out.writeByte(0xff & ((data << _bitLength) | _bitBuffer));
                        length -= (8 - _bitLength);
                        data >>>= (8 - _bitLength);
                        _bitBuffer = 0;
                        _bitLength = 0;
                    }

                    _bitBuffer = (data << _bitLength) | _bitBuffer;
                    _bitLength = _bitLength + length;
                };

                _this.flush = function() {
                    if (_bitLength > 0) {
                        _out.writeByte(_bitBuffer);
                    }
                };

                return _this;
            };

            var getLZWRaster = function(lzwMinCodeSize) {

                var clearCode = 1 << lzwMinCodeSize;
                var endCode = (1 << lzwMinCodeSize) + 1;
                var bitLength = lzwMinCodeSize + 1;

                // Setup LZWTable
                var table = lzwTable();

                for (var i = 0; i < clearCode; i += 1) {
                    table.add(String.fromCharCode(i));
                }
                table.add(String.fromCharCode(clearCode));
                table.add(String.fromCharCode(endCode));

                var byteOut = byteArrayOutputStream();
                var bitOut = bitOutputStream(byteOut);

                // clear code
                bitOut.write(clearCode, bitLength);

                var dataIndex = 0;

                var s = String.fromCharCode(_data[dataIndex]);
                dataIndex += 1;

                while (dataIndex < _data.length) {

                    var c = String.fromCharCode(_data[dataIndex]);
                    dataIndex += 1;

                    if (table.contains(s + c)) {

                        s = s + c;

                    } else {

                        bitOut.write(table.indexOf(s), bitLength);

                        if (table.size() < 0xfff) {

                            if (table.size() == (1 << bitLength)) {
                                bitLength += 1;
                            }

                            table.add(s + c);
                        }

                        s = c;
                    }
                }

                bitOut.write(table.indexOf(s), bitLength);

                // end code
                bitOut.write(endCode, bitLength);

                bitOut.flush();

                return byteOut.toByteArray();
            };

            var lzwTable = function() {

                var _map = {};
                var _size = 0;

                var _this = {};

                _this.add = function(key) {
                    if (_this.contains(key)) {
                        throw new Error('dup key:' + key);
                    }
                    _map[key] = _size;
                    _size += 1;
                };

                _this.size = function() {
                    return _size;
                };

                _this.indexOf = function(key) {
                    return _map[key];
                };

                _this.contains = function(key) {
                    return typeof _map[key] != 'undefined';
                };

                return _this;
            };

            return _this;
        };

        var createImgTag = function(width, height, getPixel, alt) {

            var gif = gifImage(width, height);
            for (var y = 0; y < height; y += 1) {
                for (var x = 0; x < width; x += 1) {
                    gif.setPixel(x, y, getPixel(x, y));
                }
            }

            var b = byteArrayOutputStream();
            gif.write(b);

            var base64 = base64EncodeOutputStream();
            var bytes = b.toByteArray();
            for (var i = 0; i < bytes.length; i += 1) {
                base64.writeByte(bytes[i]);
            }
            base64.flush();

            var img = '';
            img += '<img';
            img += '\u0020src="';
            img += 'data:image/gif;base64,';
            img += base64;
            img += '"';
            img += '\u0020width="';
            img += width;
            img += '"';
            img += '\u0020height="';
            img += height;
            img += '"';
            if (alt) {
                img += '\u0020alt="';
                img += alt;
                img += '"';
            }
            img += '/>';

            return img;
        };

        //---------------------------------------------------------------------
        // returns qrcode function.

        return qrcode;
    }();

    (function(factory) {
        if (typeof define === 'function' && define.amd) {
            define([], factory);
        } else if (typeof exports === 'object') {
            module.exports = factory();
        }
    }(function() {
        return qrcode;
    }));
    //---------------------------------------------------------------------
    //
    // QR Code Generator for JavaScript UTF8 Support (optional)
    //
    // Copyright (
Download .txt
gitextract_rfzm3utl/

├── .gitignore
├── LICENSE
├── README.md
├── demo/
│   ├── index.html
│   └── style.css
├── package.json
├── src/
│   └── qr-creator.js
├── test/
│   ├── index.html
│   ├── qr-code.larsjung.js
│   ├── qr-code.org.js
│   └── style.css
└── types/
    └── qr-creator.d.ts
Download .txt
SYMBOL INDEX (56 symbols across 4 files)

FILE: src/qr-creator.js
  class QrCreator (line 5) | class QrCreator {
    method render (line 6) | static render(config, $element) {
  function createQRCode (line 19) | function createQRCode(text, level, version, quiet) {
  function createMinQRCode (line 53) | function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
  function drawBackground (line 64) | function drawBackground(qr, context, settings) {
  function drawModuleRoundedDark (line 72) | function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRoundendLight (line 96) | function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRounded (line 110) | function drawModuleRounded(qr, context, settings, left, top, width, row,...
  function drawModules (line 141) | function drawModules(qr, context, settings) {
  function setFill (line 162) | function setFill(context, settings) {
  function drawOnCanvas (line 188) | function drawOnCanvas(canvas, settings) {
  function createCanvas (line 203) | function createCanvas(settings) {
  function toUTF8Array (line 665) | function toUTF8Array(str) {
  function qrPolynomial (line 1017) | function qrPolynomial(num, shift) {

FILE: test/qr-code.larsjung.js
  function createQRCode (line 14) | function createQRCode(text, level, version, quiet) {
  function createMinQRCode (line 62) | function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
  function drawBackgroundLabel (line 73) | function drawBackgroundLabel(qr, context, settings) {
  function drawBackgroundImage (line 102) | function drawBackgroundImage(qr, context, settings) {
  function drawBackground (line 125) | function drawBackground(qr, context, settings) {
  function drawModuleDefault (line 141) | function drawModuleDefault(qr, context, settings, left, top, width, row,...
  function drawModuleRoundedDark (line 147) | function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRoundendLight (line 183) | function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRounded (line 213) | function drawModuleRounded(qr, context, settings, left, top, width, row,...
  function drawModules (line 239) | function drawModules(qr, context, settings) {
  function drawOnCanvas (line 279) | function drawOnCanvas(canvas, settings) {
  function createCanvas (line 295) | function createCanvas(settings) {
  function createImage (line 301) | function createImage(settings) {
  function createDiv (line 306) | function createDiv(settings) {
  function createHTML (line 365) | function createHTML(settings) {
  function qrPolynomial (line 1361) | function qrPolynomial(num, shift) {
  function toUTF8Array (line 2296) | function toUTF8Array(str) {

FILE: test/qr-code.org.js
  class QrCodeOrg (line 2) | class QrCodeOrg {
    method render (line 3) | static render(config, $element) {
  function createQRCode (line 21) | function createQRCode(text, level, version, quiet) {
  function createMinQRCode (line 69) | function createMinQRCode(text, level, minVersion, maxVersion, quiet) {
  function drawBackgroundLabel (line 80) | function drawBackgroundLabel(qr, context, settings) {
  function drawBackgroundImage (line 109) | function drawBackgroundImage(qr, context, settings) {
  function drawBackground (line 132) | function drawBackground(qr, context, settings) {
  function drawModuleDefault (line 148) | function drawModuleDefault(qr, context, settings, left, top, width, row,...
  function drawModuleRoundedDark (line 154) | function drawModuleRoundedDark(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRoundendLight (line 190) | function drawModuleRoundendLight(ctx, l, t, r, b, rad, nw, ne, se, sw) {
  function drawModuleRounded (line 220) | function drawModuleRounded(qr, context, settings, left, top, width, row,...
  function drawModules (line 246) | function drawModules(qr, context, settings) {
  function drawOnCanvas (line 286) | function drawOnCanvas(canvas, settings) {
  function createCanvas (line 303) | function createCanvas(settings) {
  function createImage (line 311) | function createImage(settings) {
  function createDiv (line 316) | function createDiv(settings) {
  function createHTML (line 375) | function createHTML(settings) {
  function qrPolynomial (line 1377) | function qrPolynomial(num, shift) {
  function toUTF8Array (line 2312) | function toUTF8Array(str) {

FILE: types/qr-creator.d.ts
  class QrCreator (line 5) | class QrCreator {
  type Config (line 11) | interface Config {
  type ErrorCorrectionLevel (line 25) | type ErrorCorrectionLevel = 'L' | 'M' | 'H' | 'Q';
  type LinearGradient (line 27) | interface LinearGradient {
  type RadialGradient (line 33) | interface RadialGradient {
  type ColorStop (line 39) | type ColorStop = [ number, string ];
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (210K chars).
[
  {
    "path": ".gitignore",
    "chars": 38,
    "preview": "node_modules\ndist\n.idea\n.DS_Store\ntmp\n"
  },
  {
    "path": "LICENSE",
    "chars": 1078,
    "preview": "MIT License\n\nCopyright (c) 2017 The Nimiq Foundation.\n\nPermission is hereby granted, free of charge, to any person obtai"
  },
  {
    "path": "README.md",
    "chars": 4273,
    "preview": "# QR Code Encoder\n\n<img src=\"https://nimiq.github.io/qr-creator/demo/qr-code-example.png\"/>\n\nA lightweight library gener"
  },
  {
    "path": "demo/index.html",
    "chars": 2504,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>QR code creator demo</title>\n    <meta name=\"viewpo"
  },
  {
    "path": "demo/style.css",
    "chars": 642,
    "preview": "html {\n  padding: .666rem;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\", \"Ubuntu\", \""
  },
  {
    "path": "package.json",
    "chars": 1212,
    "preview": "{\n  \"name\": \"qr-creator\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Lightweight QR code generator for stylish QR codes\",\n "
  },
  {
    "path": "src/qr-creator.js",
    "chars": 49228,
    "preview": "'use strict';\nlet qrCodeGenerator = null;\n\n// Library interface\nexport default class QrCreator {\n    static render(confi"
  },
  {
    "path": "test/index.html",
    "chars": 1374,
    "preview": "<!DOCTYPE html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>QR-Code generator test</title>\n\n    <meta name=\"vie"
  },
  {
    "path": "test/qr-code.larsjung.js",
    "chars": 65551,
    "preview": "/*! jquery-qrcode v0.14.0 - https://larsjung.de/jquery-qrcode/ */\n(function (vendor_qrcode) {\n    'use strict';\n\n    var"
  },
  {
    "path": "test/qr-code.org.js",
    "chars": 75206,
    "preview": "// 2346 lines (1867 sloc)  73.4 KB\nclass QrCodeOrg {\n    static render(config, $element) {\n        $element.appendChild("
  },
  {
    "path": "test/style.css",
    "chars": 155,
    "preview": "section {\n  position: relative;\n}\nsection canvas {\n  position: absolute;\n}\n\nsection canvas:nth-child(1) {\n  position: ab"
  },
  {
    "path": "types/qr-creator.d.ts",
    "chars": 1167,
    "preview": "// Type definitions for qr-creator\n// Project: qr-creator\n// Definitions by: Nimiq <www.nimiq.com>\n\ndeclare class QrCrea"
  }
]

About this extraction

This page contains the full source code of the nimiq/qr-creator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (197.7 KB), approximately 52.2k tokens, and a symbol index with 56 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!