[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/media/vendor/qrcode/js/ -> qrcode.js (source)

   1  //---------------------------------------------------------------------
   2  //
   3  // QR Code Generator for JavaScript
   4  //
   5  // Copyright (c) 2009 Kazuhiko Arase
   6  //
   7  // URL: http://www.d-project.com/
   8  //
   9  // Licensed under the MIT license:
  10  //  http://www.opensource.org/licenses/mit-license.php
  11  //
  12  // The word 'QR Code' is registered trademark of
  13  // DENSO WAVE INCORPORATED
  14  //  http://www.denso-wave.com/qrcode/faqpatent-e.html
  15  //
  16  //---------------------------------------------------------------------
  17  
  18  var qrcode = function() {
  19  
  20    //---------------------------------------------------------------------
  21    // qrcode
  22    //---------------------------------------------------------------------
  23  
  24    /**
  25     * qrcode
  26     * @param typeNumber 1 to 40
  27     * @param errorCorrectionLevel 'L','M','Q','H'
  28     */
  29    var qrcode = function(typeNumber, errorCorrectionLevel) {
  30  
  31      var PAD0 = 0xEC;
  32      var PAD1 = 0x11;
  33  
  34      var _typeNumber = typeNumber;
  35      var _errorCorrectionLevel = QRErrorCorrectionLevel[errorCorrectionLevel];
  36      var _modules = null;
  37      var _moduleCount = 0;
  38      var _dataCache = null;
  39      var _dataList = [];
  40  
  41      var _this = {};
  42  
  43      var makeImpl = function(test, maskPattern) {
  44  
  45        _moduleCount = _typeNumber * 4 + 17;
  46        _modules = function(moduleCount) {
  47          var modules = new Array(moduleCount);
  48          for (var row = 0; row < moduleCount; row += 1) {
  49            modules[row] = new Array(moduleCount);
  50            for (var col = 0; col < moduleCount; col += 1) {
  51              modules[row][col] = null;
  52            }
  53          }
  54          return modules;
  55        }(_moduleCount);
  56  
  57        setupPositionProbePattern(0, 0);
  58        setupPositionProbePattern(_moduleCount - 7, 0);
  59        setupPositionProbePattern(0, _moduleCount - 7);
  60        setupPositionAdjustPattern();
  61        setupTimingPattern();
  62        setupTypeInfo(test, maskPattern);
  63  
  64        if (_typeNumber >= 7) {
  65          setupTypeNumber(test);
  66        }
  67  
  68        if (_dataCache == null) {
  69          _dataCache = createData(_typeNumber, _errorCorrectionLevel, _dataList);
  70        }
  71  
  72        mapData(_dataCache, maskPattern);
  73      };
  74  
  75      var setupPositionProbePattern = function(row, col) {
  76  
  77        for (var r = -1; r <= 7; r += 1) {
  78  
  79          if (row + r <= -1 || _moduleCount <= row + r) continue;
  80  
  81          for (var c = -1; c <= 7; c += 1) {
  82  
  83            if (col + c <= -1 || _moduleCount <= col + c) continue;
  84  
  85            if ( (0 <= r && r <= 6 && (c == 0 || c == 6) )
  86                || (0 <= c && c <= 6 && (r == 0 || r == 6) )
  87                || (2 <= r && r <= 4 && 2 <= c && c <= 4) ) {
  88              _modules[row + r][col + c] = true;
  89            } else {
  90              _modules[row + r][col + c] = false;
  91            }
  92          }
  93        }
  94      };
  95  
  96      var getBestMaskPattern = function() {
  97  
  98        var minLostPoint = 0;
  99        var pattern = 0;
 100  
 101        for (var i = 0; i < 8; i += 1) {
 102  
 103          makeImpl(true, i);
 104  
 105          var lostPoint = QRUtil.getLostPoint(_this);
 106  
 107          if (i == 0 || minLostPoint > lostPoint) {
 108            minLostPoint = lostPoint;
 109            pattern = i;
 110          }
 111        }
 112  
 113        return pattern;
 114      };
 115  
 116      var setupTimingPattern = function() {
 117  
 118        for (var r = 8; r < _moduleCount - 8; r += 1) {
 119          if (_modules[r][6] != null) {
 120            continue;
 121          }
 122          _modules[r][6] = (r % 2 == 0);
 123        }
 124  
 125        for (var c = 8; c < _moduleCount - 8; c += 1) {
 126          if (_modules[6][c] != null) {
 127            continue;
 128          }
 129          _modules[6][c] = (c % 2 == 0);
 130        }
 131      };
 132  
 133      var setupPositionAdjustPattern = function() {
 134  
 135        var pos = QRUtil.getPatternPosition(_typeNumber);
 136  
 137        for (var i = 0; i < pos.length; i += 1) {
 138  
 139          for (var j = 0; j < pos.length; j += 1) {
 140  
 141            var row = pos[i];
 142            var col = pos[j];
 143  
 144            if (_modules[row][col] != null) {
 145              continue;
 146            }
 147  
 148            for (var r = -2; r <= 2; r += 1) {
 149  
 150              for (var c = -2; c <= 2; c += 1) {
 151  
 152                if (r == -2 || r == 2 || c == -2 || c == 2
 153                    || (r == 0 && c == 0) ) {
 154                  _modules[row + r][col + c] = true;
 155                } else {
 156                  _modules[row + r][col + c] = false;
 157                }
 158              }
 159            }
 160          }
 161        }
 162      };
 163  
 164      var setupTypeNumber = function(test) {
 165  
 166        var bits = QRUtil.getBCHTypeNumber(_typeNumber);
 167  
 168        for (var i = 0; i < 18; i += 1) {
 169          var mod = (!test && ( (bits >> i) & 1) == 1);
 170          _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;
 171        }
 172  
 173        for (var i = 0; i < 18; i += 1) {
 174          var mod = (!test && ( (bits >> i) & 1) == 1);
 175          _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;
 176        }
 177      };
 178  
 179      var setupTypeInfo = function(test, maskPattern) {
 180  
 181        var data = (_errorCorrectionLevel << 3) | maskPattern;
 182        var bits = QRUtil.getBCHTypeInfo(data);
 183  
 184        // vertical
 185        for (var i = 0; i < 15; i += 1) {
 186  
 187          var mod = (!test && ( (bits >> i) & 1) == 1);
 188  
 189          if (i < 6) {
 190            _modules[i][8] = mod;
 191          } else if (i < 8) {
 192            _modules[i + 1][8] = mod;
 193          } else {
 194            _modules[_moduleCount - 15 + i][8] = mod;
 195          }
 196        }
 197  
 198        // horizontal
 199        for (var i = 0; i < 15; i += 1) {
 200  
 201          var mod = (!test && ( (bits >> i) & 1) == 1);
 202  
 203          if (i < 8) {
 204            _modules[8][_moduleCount - i - 1] = mod;
 205          } else if (i < 9) {
 206            _modules[8][15 - i - 1 + 1] = mod;
 207          } else {
 208            _modules[8][15 - i - 1] = mod;
 209          }
 210        }
 211  
 212        // fixed module
 213        _modules[_moduleCount - 8][8] = (!test);
 214      };
 215  
 216      var mapData = function(data, maskPattern) {
 217  
 218        var inc = -1;
 219        var row = _moduleCount - 1;
 220        var bitIndex = 7;
 221        var byteIndex = 0;
 222        var maskFunc = QRUtil.getMaskFunction(maskPattern);
 223  
 224        for (var col = _moduleCount - 1; col > 0; col -= 2) {
 225  
 226          if (col == 6) col -= 1;
 227  
 228          while (true) {
 229  
 230            for (var c = 0; c < 2; c += 1) {
 231  
 232              if (_modules[row][col - c] == null) {
 233  
 234                var dark = false;
 235  
 236                if (byteIndex < data.length) {
 237                  dark = ( ( (data[byteIndex] >>> bitIndex) & 1) == 1);
 238                }
 239  
 240                var mask = maskFunc(row, col - c);
 241  
 242                if (mask) {
 243                  dark = !dark;
 244                }
 245  
 246                _modules[row][col - c] = dark;
 247                bitIndex -= 1;
 248  
 249                if (bitIndex == -1) {
 250                  byteIndex += 1;
 251                  bitIndex = 7;
 252                }
 253              }
 254            }
 255  
 256            row += inc;
 257  
 258            if (row < 0 || _moduleCount <= row) {
 259              row -= inc;
 260              inc = -inc;
 261              break;
 262            }
 263          }
 264        }
 265      };
 266  
 267      var createBytes = function(buffer, rsBlocks) {
 268  
 269        var offset = 0;
 270  
 271        var maxDcCount = 0;
 272        var maxEcCount = 0;
 273  
 274        var dcdata = new Array(rsBlocks.length);
 275        var ecdata = new Array(rsBlocks.length);
 276  
 277        for (var r = 0; r < rsBlocks.length; r += 1) {
 278  
 279          var dcCount = rsBlocks[r].dataCount;
 280          var ecCount = rsBlocks[r].totalCount - dcCount;
 281  
 282          maxDcCount = Math.max(maxDcCount, dcCount);
 283          maxEcCount = Math.max(maxEcCount, ecCount);
 284  
 285          dcdata[r] = new Array(dcCount);
 286  
 287          for (var i = 0; i < dcdata[r].length; i += 1) {
 288            dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];
 289          }
 290          offset += dcCount;
 291  
 292          var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
 293          var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);
 294  
 295          var modPoly = rawPoly.mod(rsPoly);
 296          ecdata[r] = new Array(rsPoly.getLength() - 1);
 297          for (var i = 0; i < ecdata[r].length; i += 1) {
 298            var modIndex = i + modPoly.getLength() - ecdata[r].length;
 299            ecdata[r][i] = (modIndex >= 0)? modPoly.getAt(modIndex) : 0;
 300          }
 301        }
 302  
 303        var totalCodeCount = 0;
 304        for (var i = 0; i < rsBlocks.length; i += 1) {
 305          totalCodeCount += rsBlocks[i].totalCount;
 306        }
 307  
 308        var data = new Array(totalCodeCount);
 309        var index = 0;
 310  
 311        for (var i = 0; i < maxDcCount; i += 1) {
 312          for (var r = 0; r < rsBlocks.length; r += 1) {
 313            if (i < dcdata[r].length) {
 314              data[index] = dcdata[r][i];
 315              index += 1;
 316            }
 317          }
 318        }
 319  
 320        for (var i = 0; i < maxEcCount; i += 1) {
 321          for (var r = 0; r < rsBlocks.length; r += 1) {
 322            if (i < ecdata[r].length) {
 323              data[index] = ecdata[r][i];
 324              index += 1;
 325            }
 326          }
 327        }
 328  
 329        return data;
 330      };
 331  
 332      var createData = function(typeNumber, errorCorrectionLevel, dataList) {
 333  
 334        var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectionLevel);
 335  
 336        var buffer = qrBitBuffer();
 337  
 338        for (var i = 0; i < dataList.length; i += 1) {
 339          var data = dataList[i];
 340          buffer.put(data.getMode(), 4);
 341          buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
 342          data.write(buffer);
 343        }
 344  
 345        // calc num max data.
 346        var totalDataCount = 0;
 347        for (var i = 0; i < rsBlocks.length; i += 1) {
 348          totalDataCount += rsBlocks[i].dataCount;
 349        }
 350  
 351        if (buffer.getLengthInBits() > totalDataCount * 8) {
 352          throw 'code length overflow. ('
 353            + buffer.getLengthInBits()
 354            + '>'
 355            + totalDataCount * 8
 356            + ')';
 357        }
 358  
 359        // end code
 360        if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
 361          buffer.put(0, 4);
 362        }
 363  
 364        // padding
 365        while (buffer.getLengthInBits() % 8 != 0) {
 366          buffer.putBit(false);
 367        }
 368  
 369        // padding
 370        while (true) {
 371  
 372          if (buffer.getLengthInBits() >= totalDataCount * 8) {
 373            break;
 374          }
 375          buffer.put(PAD0, 8);
 376  
 377          if (buffer.getLengthInBits() >= totalDataCount * 8) {
 378            break;
 379          }
 380          buffer.put(PAD1, 8);
 381        }
 382  
 383        return createBytes(buffer, rsBlocks);
 384      };
 385  
 386      _this.addData = function(data, mode) {
 387  
 388        mode = mode || 'Byte';
 389  
 390        var newData = null;
 391  
 392        switch(mode) {
 393        case 'Numeric' :
 394          newData = qrNumber(data);
 395          break;
 396        case 'Alphanumeric' :
 397          newData = qrAlphaNum(data);
 398          break;
 399        case 'Byte' :
 400          newData = qr8BitByte(data);
 401          break;
 402        case 'Kanji' :
 403          newData = qrKanji(data);
 404          break;
 405        default :
 406          throw 'mode:' + mode;
 407        }
 408  
 409        _dataList.push(newData);
 410        _dataCache = null;
 411      };
 412  
 413      _this.isDark = function(row, col) {
 414        if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {
 415          throw row + ',' + col;
 416        }
 417        return _modules[row][col];
 418      };
 419  
 420      _this.getModuleCount = function() {
 421        return _moduleCount;
 422      };
 423  
 424      _this.make = function() {
 425        if (_typeNumber < 1) {
 426          var typeNumber = 1;
 427  
 428          for (; typeNumber < 40; typeNumber++) {
 429            var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, _errorCorrectionLevel);
 430            var buffer = qrBitBuffer();
 431  
 432            for (var i = 0; i < _dataList.length; i++) {
 433              var data = _dataList[i];
 434              buffer.put(data.getMode(), 4);
 435              buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber) );
 436              data.write(buffer);
 437            }
 438  
 439            var totalDataCount = 0;
 440            for (var i = 0; i < rsBlocks.length; i++) {
 441              totalDataCount += rsBlocks[i].dataCount;
 442            }
 443  
 444            if (buffer.getLengthInBits() <= totalDataCount * 8) {
 445              break;
 446            }
 447          }
 448  
 449          _typeNumber = typeNumber;
 450        }
 451  
 452        makeImpl(false, getBestMaskPattern() );
 453      };
 454  
 455      _this.createTableTag = function(cellSize, margin) {
 456  
 457        cellSize = cellSize || 2;
 458        margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
 459  
 460        var qrHtml = '';
 461  
 462        qrHtml += '<table style="';
 463        qrHtml += ' border-width: 0px; border-style: none;';
 464        qrHtml += ' border-collapse: collapse;';
 465        qrHtml += ' padding: 0px; margin: ' + margin + 'px;';
 466        qrHtml += '">';
 467        qrHtml += '<tbody>';
 468  
 469        for (var r = 0; r < _this.getModuleCount(); r += 1) {
 470  
 471          qrHtml += '<tr>';
 472  
 473          for (var c = 0; c < _this.getModuleCount(); c += 1) {
 474            qrHtml += '<td style="';
 475            qrHtml += ' border-width: 0px; border-style: none;';
 476            qrHtml += ' border-collapse: collapse;';
 477            qrHtml += ' padding: 0px; margin: 0px;';
 478            qrHtml += ' width: ' + cellSize + 'px;';
 479            qrHtml += ' height: ' + cellSize + 'px;';
 480            qrHtml += ' background-color: ';
 481            qrHtml += _this.isDark(r, c)? '#000000' : '#ffffff';
 482            qrHtml += ';';
 483            qrHtml += '"/>';
 484          }
 485  
 486          qrHtml += '</tr>';
 487        }
 488  
 489        qrHtml += '</tbody>';
 490        qrHtml += '</table>';
 491  
 492        return qrHtml;
 493      };
 494  
 495      _this.createSvgTag = function(cellSize, margin, alt, title) {
 496  
 497        var opts = {};
 498        if (typeof arguments[0] == 'object') {
 499          // Called by options.
 500          opts = arguments[0];
 501          // overwrite cellSize and margin.
 502          cellSize = opts.cellSize;
 503          margin = opts.margin;
 504          alt = opts.alt;
 505          title = opts.title;
 506        }
 507  
 508        cellSize = cellSize || 2;
 509        margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
 510  
 511        // Compose alt property surrogate
 512        alt = (typeof alt === 'string') ? {text: alt} : alt || {};
 513        alt.text = alt.text || null;
 514        alt.id = (alt.text) ? alt.id || 'qrcode-description' : null;
 515  
 516        // Compose title property surrogate
 517        title = (typeof title === 'string') ? {text: title} : title || {};
 518        title.text = title.text || null;
 519        title.id = (title.text) ? title.id || 'qrcode-title' : null;
 520  
 521        var size = _this.getModuleCount() * cellSize + margin * 2;
 522        var c, mc, r, mr, qrSvg='', rect;
 523  
 524        rect = 'l' + cellSize + ',0 0,' + cellSize +
 525          ' -' + cellSize + ',0 0,-' + cellSize + 'z ';
 526  
 527        qrSvg += '<svg version="1.1" xmlns="http://www.w3.org/2000/svg"';
 528        qrSvg += !opts.scalable ? ' width="' + size + 'px" height="' + size + 'px"' : '';
 529        qrSvg += ' viewBox="0 0 ' + size + ' ' + size + '" ';
 530        qrSvg += ' preserveAspectRatio="xMinYMin meet"';
 531        qrSvg += (title.text || alt.text) ? ' role="img" aria-labelledby="' +
 532            escapeXml([title.id, alt.id].join(' ').trim() ) + '"' : '';
 533        qrSvg += '>';
 534        qrSvg += (title.text) ? '<title id="' + escapeXml(title.id) + '">' +
 535            escapeXml(title.text) + '</title>' : '';
 536        qrSvg += (alt.text) ? '<description id="' + escapeXml(alt.id) + '">' +
 537            escapeXml(alt.text) + '</description>' : '';
 538        qrSvg += '<rect width="100%" height="100%" fill="white" cx="0" cy="0"/>';
 539        qrSvg += '<path d="';
 540  
 541        for (r = 0; r < _this.getModuleCount(); r += 1) {
 542          mr = r * cellSize + margin;
 543          for (c = 0; c < _this.getModuleCount(); c += 1) {
 544            if (_this.isDark(r, c) ) {
 545              mc = c*cellSize+margin;
 546              qrSvg += 'M' + mc + ',' + mr + rect;
 547            }
 548          }
 549        }
 550  
 551        qrSvg += '" stroke="transparent" fill="black"/>';
 552        qrSvg += '</svg>';
 553  
 554        return qrSvg;
 555      };
 556  
 557      _this.createDataURL = function(cellSize, margin) {
 558  
 559        cellSize = cellSize || 2;
 560        margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
 561  
 562        var size = _this.getModuleCount() * cellSize + margin * 2;
 563        var min = margin;
 564        var max = size - margin;
 565  
 566        return createDataURL(size, size, function(x, y) {
 567          if (min <= x && x < max && min <= y && y < max) {
 568            var c = Math.floor( (x - min) / cellSize);
 569            var r = Math.floor( (y - min) / cellSize);
 570            return _this.isDark(r, c)? 0 : 1;
 571          } else {
 572            return 1;
 573          }
 574        } );
 575      };
 576  
 577      _this.createImgTag = function(cellSize, margin, alt) {
 578  
 579        cellSize = cellSize || 2;
 580        margin = (typeof margin == 'undefined')? cellSize * 4 : margin;
 581  
 582        var size = _this.getModuleCount() * cellSize + margin * 2;
 583  
 584        var img = '';
 585        img += '<img';
 586        img += '\u0020src="';
 587        img += _this.createDataURL(cellSize, margin);
 588        img += '"';
 589        img += '\u0020width="';
 590        img += size;
 591        img += '"';
 592        img += '\u0020height="';
 593        img += size;
 594        img += '"';
 595        if (alt) {
 596          img += '\u0020alt="';
 597          img += escapeXml(alt);
 598          img += '"';
 599        }
 600        img += '/>';
 601  
 602        return img;
 603      };
 604  
 605      var escapeXml = function(s) {
 606        var escaped = '';
 607        for (var i = 0; i < s.length; i += 1) {
 608          var c = s.charAt(i);
 609          switch(c) {
 610          case '<': escaped += '&lt;'; break;
 611          case '>': escaped += '&gt;'; break;
 612          case '&': escaped += '&amp;'; break;
 613          case '"': escaped += '&quot;'; break;
 614          default : escaped += c; break;
 615          }
 616        }
 617        return escaped;
 618      };
 619  
 620      var _createHalfASCII = function(margin) {
 621        var cellSize = 1;
 622        margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
 623  
 624        var size = _this.getModuleCount() * cellSize + margin * 2;
 625        var min = margin;
 626        var max = size - margin;
 627  
 628        var y, x, r1, r2, p;
 629  
 630        var blocks = {
 631          '██': '█',
 632          '█ ': '▀',
 633          ' █': '▄',
 634          '  ': ' '
 635        };
 636  
 637        var blocksLastLineNoMargin = {
 638          '██': '▀',
 639          '█ ': '▀',
 640          ' █': ' ',
 641          '  ': ' '
 642        };
 643  
 644        var ascii = '';
 645        for (y = 0; y < size; y += 2) {
 646          r1 = Math.floor((y - min) / cellSize);
 647          r2 = Math.floor((y + 1 - min) / cellSize);
 648          for (x = 0; x < size; x += 1) {
 649            p = '█';
 650  
 651            if (min <= x && x < max && min <= y && y < max && _this.isDark(r1, Math.floor((x - min) / cellSize))) {
 652              p = ' ';
 653            }
 654  
 655            if (min <= x && x < max && min <= y+1 && y+1 < max && _this.isDark(r2, Math.floor((x - min) / cellSize))) {
 656              p += ' ';
 657            }
 658            else {
 659              p += '█';
 660            }
 661  
 662            // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
 663            ascii += (margin < 1 && y+1 >= max) ? blocksLastLineNoMargin[p] : blocks[p];
 664          }
 665  
 666          ascii += '\n';
 667        }
 668  
 669        if (size % 2 && margin > 0) {
 670          return ascii.substring(0, ascii.length - size - 1) + Array(size+1).join('▀');
 671        }
 672  
 673        return ascii.substring(0, ascii.length-1);
 674      };
 675  
 676      _this.createASCII = function(cellSize, margin) {
 677        cellSize = cellSize || 1;
 678  
 679        if (cellSize < 2) {
 680          return _createHalfASCII(margin);
 681        }
 682  
 683        cellSize -= 1;
 684        margin = (typeof margin == 'undefined')? cellSize * 2 : margin;
 685  
 686        var size = _this.getModuleCount() * cellSize + margin * 2;
 687        var min = margin;
 688        var max = size - margin;
 689  
 690        var y, x, r, p;
 691  
 692        var white = Array(cellSize+1).join('██');
 693        var black = Array(cellSize+1).join('  ');
 694  
 695        var ascii = '';
 696        var line = '';
 697        for (y = 0; y < size; y += 1) {
 698          r = Math.floor( (y - min) / cellSize);
 699          line = '';
 700          for (x = 0; x < size; x += 1) {
 701            p = 1;
 702  
 703            if (min <= x && x < max && min <= y && y < max && _this.isDark(r, Math.floor((x - min) / cellSize))) {
 704              p = 0;
 705            }
 706  
 707            // Output 2 characters per pixel, to create full square. 1 character per pixels gives only half width of square.
 708            line += p ? white : black;
 709          }
 710  
 711          for (r = 0; r < cellSize; r += 1) {
 712            ascii += line + '\n';
 713          }
 714        }
 715  
 716        return ascii.substring(0, ascii.length-1);
 717      };
 718  
 719      _this.renderTo2dContext = function(context, cellSize) {
 720        cellSize = cellSize || 2;
 721        var length = _this.getModuleCount();
 722        for (var row = 0; row < length; row++) {
 723          for (var col = 0; col < length; col++) {
 724            context.fillStyle = _this.isDark(row, col) ? 'black' : 'white';
 725            context.fillRect(row * cellSize, col * cellSize, cellSize, cellSize);
 726          }
 727        }
 728      }
 729  
 730      return _this;
 731    };
 732  
 733    //---------------------------------------------------------------------
 734    // qrcode.stringToBytes
 735    //---------------------------------------------------------------------
 736  
 737    qrcode.stringToBytesFuncs = {
 738      'default' : function(s) {
 739        var bytes = [];
 740        for (var i = 0; i < s.length; i += 1) {
 741          var c = s.charCodeAt(i);
 742          bytes.push(c & 0xff);
 743        }
 744        return bytes;
 745      }
 746    };
 747  
 748    qrcode.stringToBytes = qrcode.stringToBytesFuncs['default'];
 749  
 750    //---------------------------------------------------------------------
 751    // qrcode.createStringToBytes
 752    //---------------------------------------------------------------------
 753  
 754    /**
 755     * @param unicodeData base64 string of byte array.
 756     * [16bit Unicode],[16bit Bytes], ...
 757     * @param numChars
 758     */
 759    qrcode.createStringToBytes = function(unicodeData, numChars) {
 760  
 761      // create conversion map.
 762  
 763      var unicodeMap = function() {
 764  
 765        var bin = base64DecodeInputStream(unicodeData);
 766        var read = function() {
 767          var b = bin.read();
 768          if (b == -1) throw 'eof';
 769          return b;
 770        };
 771  
 772        var count = 0;
 773        var unicodeMap = {};
 774        while (true) {
 775          var b0 = bin.read();
 776          if (b0 == -1) break;
 777          var b1 = read();
 778          var b2 = read();
 779          var b3 = read();
 780          var k = String.fromCharCode( (b0 << 8) | b1);
 781          var v = (b2 << 8) | b3;
 782          unicodeMap[k] = v;
 783          count += 1;
 784        }
 785        if (count != numChars) {
 786          throw count + ' != ' + numChars;
 787        }
 788  
 789        return unicodeMap;
 790      }();
 791  
 792      var unknownChar = '?'.charCodeAt(0);
 793  
 794      return function(s) {
 795        var bytes = [];
 796        for (var i = 0; i < s.length; i += 1) {
 797          var c = s.charCodeAt(i);
 798          if (c < 128) {
 799            bytes.push(c);
 800          } else {
 801            var b = unicodeMap[s.charAt(i)];
 802            if (typeof b == 'number') {
 803              if ( (b & 0xff) == b) {
 804                // 1byte
 805                bytes.push(b);
 806              } else {
 807                // 2bytes
 808                bytes.push(b >>> 8);
 809                bytes.push(b & 0xff);
 810              }
 811            } else {
 812              bytes.push(unknownChar);
 813            }
 814          }
 815        }
 816        return bytes;
 817      };
 818    };
 819  
 820    //---------------------------------------------------------------------
 821    // QRMode
 822    //---------------------------------------------------------------------
 823  
 824    var QRMode = {
 825      MODE_NUMBER :    1 << 0,
 826      MODE_ALPHA_NUM : 1 << 1,
 827      MODE_8BIT_BYTE : 1 << 2,
 828      MODE_KANJI :     1 << 3
 829    };
 830  
 831    //---------------------------------------------------------------------
 832    // QRErrorCorrectionLevel
 833    //---------------------------------------------------------------------
 834  
 835    var QRErrorCorrectionLevel = {
 836      L : 1,
 837      M : 0,
 838      Q : 3,
 839      H : 2
 840    };
 841  
 842    //---------------------------------------------------------------------
 843    // QRMaskPattern
 844    //---------------------------------------------------------------------
 845  
 846    var QRMaskPattern = {
 847      PATTERN000 : 0,
 848      PATTERN001 : 1,
 849      PATTERN010 : 2,
 850      PATTERN011 : 3,
 851      PATTERN100 : 4,
 852      PATTERN101 : 5,
 853      PATTERN110 : 6,
 854      PATTERN111 : 7
 855    };
 856  
 857    //---------------------------------------------------------------------
 858    // QRUtil
 859    //---------------------------------------------------------------------
 860  
 861    var QRUtil = function() {
 862  
 863      var PATTERN_POSITION_TABLE = [
 864        [],
 865        [6, 18],
 866        [6, 22],
 867        [6, 26],
 868        [6, 30],
 869        [6, 34],
 870        [6, 22, 38],
 871        [6, 24, 42],
 872        [6, 26, 46],
 873        [6, 28, 50],
 874        [6, 30, 54],
 875        [6, 32, 58],
 876        [6, 34, 62],
 877        [6, 26, 46, 66],
 878        [6, 26, 48, 70],
 879        [6, 26, 50, 74],
 880        [6, 30, 54, 78],
 881        [6, 30, 56, 82],
 882        [6, 30, 58, 86],
 883        [6, 34, 62, 90],
 884        [6, 28, 50, 72, 94],
 885        [6, 26, 50, 74, 98],
 886        [6, 30, 54, 78, 102],
 887        [6, 28, 54, 80, 106],
 888        [6, 32, 58, 84, 110],
 889        [6, 30, 58, 86, 114],
 890        [6, 34, 62, 90, 118],
 891        [6, 26, 50, 74, 98, 122],
 892        [6, 30, 54, 78, 102, 126],
 893        [6, 26, 52, 78, 104, 130],
 894        [6, 30, 56, 82, 108, 134],
 895        [6, 34, 60, 86, 112, 138],
 896        [6, 30, 58, 86, 114, 142],
 897        [6, 34, 62, 90, 118, 146],
 898        [6, 30, 54, 78, 102, 126, 150],
 899        [6, 24, 50, 76, 102, 128, 154],
 900        [6, 28, 54, 80, 106, 132, 158],
 901        [6, 32, 58, 84, 110, 136, 162],
 902        [6, 26, 54, 82, 110, 138, 166],
 903        [6, 30, 58, 86, 114, 142, 170]
 904      ];
 905      var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);
 906      var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);
 907      var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);
 908  
 909      var _this = {};
 910  
 911      var getBCHDigit = function(data) {
 912        var digit = 0;
 913        while (data != 0) {
 914          digit += 1;
 915          data >>>= 1;
 916        }
 917        return digit;
 918      };
 919  
 920      _this.getBCHTypeInfo = function(data) {
 921        var d = data << 10;
 922        while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {
 923          d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15) ) );
 924        }
 925        return ( (data << 10) | d) ^ G15_MASK;
 926      };
 927  
 928      _this.getBCHTypeNumber = function(data) {
 929        var d = data << 12;
 930        while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {
 931          d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18) ) );
 932        }
 933        return (data << 12) | d;
 934      };
 935  
 936      _this.getPatternPosition = function(typeNumber) {
 937        return PATTERN_POSITION_TABLE[typeNumber - 1];
 938      };
 939  
 940      _this.getMaskFunction = function(maskPattern) {
 941  
 942        switch (maskPattern) {
 943  
 944        case QRMaskPattern.PATTERN000 :
 945          return function(i, j) { return (i + j) % 2 == 0; };
 946        case QRMaskPattern.PATTERN001 :
 947          return function(i, j) { return i % 2 == 0; };
 948        case QRMaskPattern.PATTERN010 :
 949          return function(i, j) { return j % 3 == 0; };
 950        case QRMaskPattern.PATTERN011 :
 951          return function(i, j) { return (i + j) % 3 == 0; };
 952        case QRMaskPattern.PATTERN100 :
 953          return function(i, j) { return (Math.floor(i / 2) + Math.floor(j / 3) ) % 2 == 0; };
 954        case QRMaskPattern.PATTERN101 :
 955          return function(i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };
 956        case QRMaskPattern.PATTERN110 :
 957          return function(i, j) { return ( (i * j) % 2 + (i * j) % 3) % 2 == 0; };
 958        case QRMaskPattern.PATTERN111 :
 959          return function(i, j) { return ( (i * j) % 3 + (i + j) % 2) % 2 == 0; };
 960  
 961        default :
 962          throw 'bad maskPattern:' + maskPattern;
 963        }
 964      };
 965  
 966      _this.getErrorCorrectPolynomial = function(errorCorrectLength) {
 967        var a = qrPolynomial([1], 0);
 968        for (var i = 0; i < errorCorrectLength; i += 1) {
 969          a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0) );
 970        }
 971        return a;
 972      };
 973  
 974      _this.getLengthInBits = function(mode, type) {
 975  
 976        if (1 <= type && type < 10) {
 977  
 978          // 1 - 9
 979  
 980          switch(mode) {
 981          case QRMode.MODE_NUMBER    : return 10;
 982          case QRMode.MODE_ALPHA_NUM : return 9;
 983          case QRMode.MODE_8BIT_BYTE : return 8;
 984          case QRMode.MODE_KANJI     : return 8;
 985          default :
 986            throw 'mode:' + mode;
 987          }
 988  
 989        } else if (type < 27) {
 990  
 991          // 10 - 26
 992  
 993          switch(mode) {
 994          case QRMode.MODE_NUMBER    : return 12;
 995          case QRMode.MODE_ALPHA_NUM : return 11;
 996          case QRMode.MODE_8BIT_BYTE : return 16;
 997          case QRMode.MODE_KANJI     : return 10;
 998          default :
 999            throw 'mode:' + mode;
1000          }
1001  
1002        } else if (type < 41) {
1003  
1004          // 27 - 40
1005  
1006          switch(mode) {
1007          case QRMode.MODE_NUMBER    : return 14;
1008          case QRMode.MODE_ALPHA_NUM : return 13;
1009          case QRMode.MODE_8BIT_BYTE : return 16;
1010          case QRMode.MODE_KANJI     : return 12;
1011          default :
1012            throw 'mode:' + mode;
1013          }
1014  
1015        } else {
1016          throw 'type:' + type;
1017        }
1018      };
1019  
1020      _this.getLostPoint = function(qrcode) {
1021  
1022        var moduleCount = qrcode.getModuleCount();
1023  
1024        var lostPoint = 0;
1025  
1026        // LEVEL1
1027  
1028        for (var row = 0; row < moduleCount; row += 1) {
1029          for (var col = 0; col < moduleCount; col += 1) {
1030  
1031            var sameCount = 0;
1032            var dark = qrcode.isDark(row, col);
1033  
1034            for (var r = -1; r <= 1; r += 1) {
1035  
1036              if (row + r < 0 || moduleCount <= row + r) {
1037                continue;
1038              }
1039  
1040              for (var c = -1; c <= 1; c += 1) {
1041  
1042                if (col + c < 0 || moduleCount <= col + c) {
1043                  continue;
1044                }
1045  
1046                if (r == 0 && c == 0) {
1047                  continue;
1048                }
1049  
1050                if (dark == qrcode.isDark(row + r, col + c) ) {
1051                  sameCount += 1;
1052                }
1053              }
1054            }
1055  
1056            if (sameCount > 5) {
1057              lostPoint += (3 + sameCount - 5);
1058            }
1059          }
1060        };
1061  
1062        // LEVEL2
1063  
1064        for (var row = 0; row < moduleCount - 1; row += 1) {
1065          for (var col = 0; col < moduleCount - 1; col += 1) {
1066            var count = 0;
1067            if (qrcode.isDark(row, col) ) count += 1;
1068            if (qrcode.isDark(row + 1, col) ) count += 1;
1069            if (qrcode.isDark(row, col + 1) ) count += 1;
1070            if (qrcode.isDark(row + 1, col + 1) ) count += 1;
1071            if (count == 0 || count == 4) {
1072              lostPoint += 3;
1073            }
1074          }
1075        }
1076  
1077        // LEVEL3
1078  
1079        for (var row = 0; row < moduleCount; row += 1) {
1080          for (var col = 0; col < moduleCount - 6; col += 1) {
1081            if (qrcode.isDark(row, col)
1082                && !qrcode.isDark(row, col + 1)
1083                &&  qrcode.isDark(row, col + 2)
1084                &&  qrcode.isDark(row, col + 3)
1085                &&  qrcode.isDark(row, col + 4)
1086                && !qrcode.isDark(row, col + 5)
1087                &&  qrcode.isDark(row, col + 6) ) {
1088              lostPoint += 40;
1089            }
1090          }
1091        }
1092  
1093        for (var col = 0; col < moduleCount; col += 1) {
1094          for (var row = 0; row < moduleCount - 6; row += 1) {
1095            if (qrcode.isDark(row, col)
1096                && !qrcode.isDark(row + 1, col)
1097                &&  qrcode.isDark(row + 2, col)
1098                &&  qrcode.isDark(row + 3, col)
1099                &&  qrcode.isDark(row + 4, col)
1100                && !qrcode.isDark(row + 5, col)
1101                &&  qrcode.isDark(row + 6, col) ) {
1102              lostPoint += 40;
1103            }
1104          }
1105        }
1106  
1107        // LEVEL4
1108  
1109        var darkCount = 0;
1110  
1111        for (var col = 0; col < moduleCount; col += 1) {
1112          for (var row = 0; row < moduleCount; row += 1) {
1113            if (qrcode.isDark(row, col) ) {
1114              darkCount += 1;
1115            }
1116          }
1117        }
1118  
1119        var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
1120        lostPoint += ratio * 10;
1121  
1122        return lostPoint;
1123      };
1124  
1125      return _this;
1126    }();
1127  
1128    //---------------------------------------------------------------------
1129    // QRMath
1130    //---------------------------------------------------------------------
1131  
1132    var QRMath = function() {
1133  
1134      var EXP_TABLE = new Array(256);
1135      var LOG_TABLE = new Array(256);
1136  
1137      // initialize tables
1138      for (var i = 0; i < 8; i += 1) {
1139        EXP_TABLE[i] = 1 << i;
1140      }
1141      for (var i = 8; i < 256; i += 1) {
1142        EXP_TABLE[i] = EXP_TABLE[i - 4]
1143          ^ EXP_TABLE[i - 5]
1144          ^ EXP_TABLE[i - 6]
1145          ^ EXP_TABLE[i - 8];
1146      }
1147      for (var i = 0; i < 255; i += 1) {
1148        LOG_TABLE[EXP_TABLE[i] ] = i;
1149      }
1150  
1151      var _this = {};
1152  
1153      _this.glog = function(n) {
1154  
1155        if (n < 1) {
1156          throw 'glog(' + n + ')';
1157        }
1158  
1159        return LOG_TABLE[n];
1160      };
1161  
1162      _this.gexp = function(n) {
1163  
1164        while (n < 0) {
1165          n += 255;
1166        }
1167  
1168        while (n >= 256) {
1169          n -= 255;
1170        }
1171  
1172        return EXP_TABLE[n];
1173      };
1174  
1175      return _this;
1176    }();
1177  
1178    //---------------------------------------------------------------------
1179    // qrPolynomial
1180    //---------------------------------------------------------------------
1181  
1182    function qrPolynomial(num, shift) {
1183  
1184      if (typeof num.length == 'undefined') {
1185        throw num.length + '/' + shift;
1186      }
1187  
1188      var _num = function() {
1189        var offset = 0;
1190        while (offset < num.length && num[offset] == 0) {
1191          offset += 1;
1192        }
1193        var _num = new Array(num.length - offset + shift);
1194        for (var i = 0; i < num.length - offset; i += 1) {
1195          _num[i] = num[i + offset];
1196        }
1197        return _num;
1198      }();
1199  
1200      var _this = {};
1201  
1202      _this.getAt = function(index) {
1203        return _num[index];
1204      };
1205  
1206      _this.getLength = function() {
1207        return _num.length;
1208      };
1209  
1210      _this.multiply = function(e) {
1211  
1212        var num = new Array(_this.getLength() + e.getLength() - 1);
1213  
1214        for (var i = 0; i < _this.getLength(); i += 1) {
1215          for (var j = 0; j < e.getLength(); j += 1) {
1216            num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i) ) + QRMath.glog(e.getAt(j) ) );
1217          }
1218        }
1219  
1220        return qrPolynomial(num, 0);
1221      };
1222  
1223      _this.mod = function(e) {
1224  
1225        if (_this.getLength() - e.getLength() < 0) {
1226          return _this;
1227        }
1228  
1229        var ratio = QRMath.glog(_this.getAt(0) ) - QRMath.glog(e.getAt(0) );
1230  
1231        var num = new Array(_this.getLength() );
1232        for (var i = 0; i < _this.getLength(); i += 1) {
1233          num[i] = _this.getAt(i);
1234        }
1235  
1236        for (var i = 0; i < e.getLength(); i += 1) {
1237          num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i) ) + ratio);
1238        }
1239  
1240        // recursive call
1241        return qrPolynomial(num, 0).mod(e);
1242      };
1243  
1244      return _this;
1245    };
1246  
1247    //---------------------------------------------------------------------
1248    // QRRSBlock
1249    //---------------------------------------------------------------------
1250  
1251    var QRRSBlock = function() {
1252  
1253      var RS_BLOCK_TABLE = [
1254  
1255        // L
1256        // M
1257        // Q
1258        // H
1259  
1260        // 1
1261        [1, 26, 19],
1262        [1, 26, 16],
1263        [1, 26, 13],
1264        [1, 26, 9],
1265  
1266        // 2
1267        [1, 44, 34],
1268        [1, 44, 28],
1269        [1, 44, 22],
1270        [1, 44, 16],
1271  
1272        // 3
1273        [1, 70, 55],
1274        [1, 70, 44],
1275        [2, 35, 17],
1276        [2, 35, 13],
1277  
1278        // 4
1279        [1, 100, 80],
1280        [2, 50, 32],
1281        [2, 50, 24],
1282        [4, 25, 9],
1283  
1284        // 5
1285        [1, 134, 108],
1286        [2, 67, 43],
1287        [2, 33, 15, 2, 34, 16],
1288        [2, 33, 11, 2, 34, 12],
1289  
1290        // 6
1291        [2, 86, 68],
1292        [4, 43, 27],
1293        [4, 43, 19],
1294        [4, 43, 15],
1295  
1296        // 7
1297        [2, 98, 78],
1298        [4, 49, 31],
1299        [2, 32, 14, 4, 33, 15],
1300        [4, 39, 13, 1, 40, 14],
1301  
1302        // 8
1303        [2, 121, 97],
1304        [2, 60, 38, 2, 61, 39],
1305        [4, 40, 18, 2, 41, 19],
1306        [4, 40, 14, 2, 41, 15],
1307  
1308        // 9
1309        [2, 146, 116],
1310        [3, 58, 36, 2, 59, 37],
1311        [4, 36, 16, 4, 37, 17],
1312        [4, 36, 12, 4, 37, 13],
1313  
1314        // 10
1315        [2, 86, 68, 2, 87, 69],
1316        [4, 69, 43, 1, 70, 44],
1317        [6, 43, 19, 2, 44, 20],
1318        [6, 43, 15, 2, 44, 16],
1319  
1320        // 11
1321        [4, 101, 81],
1322        [1, 80, 50, 4, 81, 51],
1323        [4, 50, 22, 4, 51, 23],
1324        [3, 36, 12, 8, 37, 13],
1325  
1326        // 12
1327        [2, 116, 92, 2, 117, 93],
1328        [6, 58, 36, 2, 59, 37],
1329        [4, 46, 20, 6, 47, 21],
1330        [7, 42, 14, 4, 43, 15],
1331  
1332        // 13
1333        [4, 133, 107],
1334        [8, 59, 37, 1, 60, 38],
1335        [8, 44, 20, 4, 45, 21],
1336        [12, 33, 11, 4, 34, 12],
1337  
1338        // 14
1339        [3, 145, 115, 1, 146, 116],
1340        [4, 64, 40, 5, 65, 41],
1341        [11, 36, 16, 5, 37, 17],
1342        [11, 36, 12, 5, 37, 13],
1343  
1344        // 15
1345        [5, 109, 87, 1, 110, 88],
1346        [5, 65, 41, 5, 66, 42],
1347        [5, 54, 24, 7, 55, 25],
1348        [11, 36, 12, 7, 37, 13],
1349  
1350        // 16
1351        [5, 122, 98, 1, 123, 99],
1352        [7, 73, 45, 3, 74, 46],
1353        [15, 43, 19, 2, 44, 20],
1354        [3, 45, 15, 13, 46, 16],
1355  
1356        // 17
1357        [1, 135, 107, 5, 136, 108],
1358        [10, 74, 46, 1, 75, 47],
1359        [1, 50, 22, 15, 51, 23],
1360        [2, 42, 14, 17, 43, 15],
1361  
1362        // 18
1363        [5, 150, 120, 1, 151, 121],
1364        [9, 69, 43, 4, 70, 44],
1365        [17, 50, 22, 1, 51, 23],
1366        [2, 42, 14, 19, 43, 15],
1367  
1368        // 19
1369        [3, 141, 113, 4, 142, 114],
1370        [3, 70, 44, 11, 71, 45],
1371        [17, 47, 21, 4, 48, 22],
1372        [9, 39, 13, 16, 40, 14],
1373  
1374        // 20
1375        [3, 135, 107, 5, 136, 108],
1376        [3, 67, 41, 13, 68, 42],
1377        [15, 54, 24, 5, 55, 25],
1378        [15, 43, 15, 10, 44, 16],
1379  
1380        // 21
1381        [4, 144, 116, 4, 145, 117],
1382        [17, 68, 42],
1383        [17, 50, 22, 6, 51, 23],
1384        [19, 46, 16, 6, 47, 17],
1385  
1386        // 22
1387        [2, 139, 111, 7, 140, 112],
1388        [17, 74, 46],
1389        [7, 54, 24, 16, 55, 25],
1390        [34, 37, 13],
1391  
1392        // 23
1393        [4, 151, 121, 5, 152, 122],
1394        [4, 75, 47, 14, 76, 48],
1395        [11, 54, 24, 14, 55, 25],
1396        [16, 45, 15, 14, 46, 16],
1397  
1398        // 24
1399        [6, 147, 117, 4, 148, 118],
1400        [6, 73, 45, 14, 74, 46],
1401        [11, 54, 24, 16, 55, 25],
1402        [30, 46, 16, 2, 47, 17],
1403  
1404        // 25
1405        [8, 132, 106, 4, 133, 107],
1406        [8, 75, 47, 13, 76, 48],
1407        [7, 54, 24, 22, 55, 25],
1408        [22, 45, 15, 13, 46, 16],
1409  
1410        // 26
1411        [10, 142, 114, 2, 143, 115],
1412        [19, 74, 46, 4, 75, 47],
1413        [28, 50, 22, 6, 51, 23],
1414        [33, 46, 16, 4, 47, 17],
1415  
1416        // 27
1417        [8, 152, 122, 4, 153, 123],
1418        [22, 73, 45, 3, 74, 46],
1419        [8, 53, 23, 26, 54, 24],
1420        [12, 45, 15, 28, 46, 16],
1421  
1422        // 28
1423        [3, 147, 117, 10, 148, 118],
1424        [3, 73, 45, 23, 74, 46],
1425        [4, 54, 24, 31, 55, 25],
1426        [11, 45, 15, 31, 46, 16],
1427  
1428        // 29
1429        [7, 146, 116, 7, 147, 117],
1430        [21, 73, 45, 7, 74, 46],
1431        [1, 53, 23, 37, 54, 24],
1432        [19, 45, 15, 26, 46, 16],
1433  
1434        // 30
1435        [5, 145, 115, 10, 146, 116],
1436        [19, 75, 47, 10, 76, 48],
1437        [15, 54, 24, 25, 55, 25],
1438        [23, 45, 15, 25, 46, 16],
1439  
1440        // 31
1441        [13, 145, 115, 3, 146, 116],
1442        [2, 74, 46, 29, 75, 47],
1443        [42, 54, 24, 1, 55, 25],
1444        [23, 45, 15, 28, 46, 16],
1445  
1446        // 32
1447        [17, 145, 115],
1448        [10, 74, 46, 23, 75, 47],
1449        [10, 54, 24, 35, 55, 25],
1450        [19, 45, 15, 35, 46, 16],
1451  
1452        // 33
1453        [17, 145, 115, 1, 146, 116],
1454        [14, 74, 46, 21, 75, 47],
1455        [29, 54, 24, 19, 55, 25],
1456        [11, 45, 15, 46, 46, 16],
1457  
1458        // 34
1459        [13, 145, 115, 6, 146, 116],
1460        [14, 74, 46, 23, 75, 47],
1461        [44, 54, 24, 7, 55, 25],
1462        [59, 46, 16, 1, 47, 17],
1463  
1464        // 35
1465        [12, 151, 121, 7, 152, 122],
1466        [12, 75, 47, 26, 76, 48],
1467        [39, 54, 24, 14, 55, 25],
1468        [22, 45, 15, 41, 46, 16],
1469  
1470        // 36
1471        [6, 151, 121, 14, 152, 122],
1472        [6, 75, 47, 34, 76, 48],
1473        [46, 54, 24, 10, 55, 25],
1474        [2, 45, 15, 64, 46, 16],
1475  
1476        // 37
1477        [17, 152, 122, 4, 153, 123],
1478        [29, 74, 46, 14, 75, 47],
1479        [49, 54, 24, 10, 55, 25],
1480        [24, 45, 15, 46, 46, 16],
1481  
1482        // 38
1483        [4, 152, 122, 18, 153, 123],
1484        [13, 74, 46, 32, 75, 47],
1485        [48, 54, 24, 14, 55, 25],
1486        [42, 45, 15, 32, 46, 16],
1487  
1488        // 39
1489        [20, 147, 117, 4, 148, 118],
1490        [40, 75, 47, 7, 76, 48],
1491        [43, 54, 24, 22, 55, 25],
1492        [10, 45, 15, 67, 46, 16],
1493  
1494        // 40
1495        [19, 148, 118, 6, 149, 119],
1496        [18, 75, 47, 31, 76, 48],
1497        [34, 54, 24, 34, 55, 25],
1498        [20, 45, 15, 61, 46, 16]
1499      ];
1500  
1501      var qrRSBlock = function(totalCount, dataCount) {
1502        var _this = {};
1503        _this.totalCount = totalCount;
1504        _this.dataCount = dataCount;
1505        return _this;
1506      };
1507  
1508      var _this = {};
1509  
1510      var getRsBlockTable = function(typeNumber, errorCorrectionLevel) {
1511  
1512        switch(errorCorrectionLevel) {
1513        case QRErrorCorrectionLevel.L :
1514          return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
1515        case QRErrorCorrectionLevel.M :
1516          return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
1517        case QRErrorCorrectionLevel.Q :
1518          return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
1519        case QRErrorCorrectionLevel.H :
1520          return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
1521        default :
1522          return undefined;
1523        }
1524      };
1525  
1526      _this.getRSBlocks = function(typeNumber, errorCorrectionLevel) {
1527  
1528        var rsBlock = getRsBlockTable(typeNumber, errorCorrectionLevel);
1529  
1530        if (typeof rsBlock == 'undefined') {
1531          throw 'bad rs block @ typeNumber:' + typeNumber +
1532              '/errorCorrectionLevel:' + errorCorrectionLevel;
1533        }
1534  
1535        var length = rsBlock.length / 3;
1536  
1537        var list = [];
1538  
1539        for (var i = 0; i < length; i += 1) {
1540  
1541          var count = rsBlock[i * 3 + 0];
1542          var totalCount = rsBlock[i * 3 + 1];
1543          var dataCount = rsBlock[i * 3 + 2];
1544  
1545          for (var j = 0; j < count; j += 1) {
1546            list.push(qrRSBlock(totalCount, dataCount) );
1547          }
1548        }
1549  
1550        return list;
1551      };
1552  
1553      return _this;
1554    }();
1555  
1556    //---------------------------------------------------------------------
1557    // qrBitBuffer
1558    //---------------------------------------------------------------------
1559  
1560    var qrBitBuffer = function() {
1561  
1562      var _buffer = [];
1563      var _length = 0;
1564  
1565      var _this = {};
1566  
1567      _this.getBuffer = function() {
1568        return _buffer;
1569      };
1570  
1571      _this.getAt = function(index) {
1572        var bufIndex = Math.floor(index / 8);
1573        return ( (_buffer[bufIndex] >>> (7 - index % 8) ) & 1) == 1;
1574      };
1575  
1576      _this.put = function(num, length) {
1577        for (var i = 0; i < length; i += 1) {
1578          _this.putBit( ( (num >>> (length - i - 1) ) & 1) == 1);
1579        }
1580      };
1581  
1582      _this.getLengthInBits = function() {
1583        return _length;
1584      };
1585  
1586      _this.putBit = function(bit) {
1587  
1588        var bufIndex = Math.floor(_length / 8);
1589        if (_buffer.length <= bufIndex) {
1590          _buffer.push(0);
1591        }
1592  
1593        if (bit) {
1594          _buffer[bufIndex] |= (0x80 >>> (_length % 8) );
1595        }
1596  
1597        _length += 1;
1598      };
1599  
1600      return _this;
1601    };
1602  
1603    //---------------------------------------------------------------------
1604    // qrNumber
1605    //---------------------------------------------------------------------
1606  
1607    var qrNumber = function(data) {
1608  
1609      var _mode = QRMode.MODE_NUMBER;
1610      var _data = data;
1611  
1612      var _this = {};
1613  
1614      _this.getMode = function() {
1615        return _mode;
1616      };
1617  
1618      _this.getLength = function(buffer) {
1619        return _data.length;
1620      };
1621  
1622      _this.write = function(buffer) {
1623  
1624        var data = _data;
1625  
1626        var i = 0;
1627  
1628        while (i + 2 < data.length) {
1629          buffer.put(strToNum(data.substring(i, i + 3) ), 10);
1630          i += 3;
1631        }
1632  
1633        if (i < data.length) {
1634          if (data.length - i == 1) {
1635            buffer.put(strToNum(data.substring(i, i + 1) ), 4);
1636          } else if (data.length - i == 2) {
1637            buffer.put(strToNum(data.substring(i, i + 2) ), 7);
1638          }
1639        }
1640      };
1641  
1642      var strToNum = function(s) {
1643        var num = 0;
1644        for (var i = 0; i < s.length; i += 1) {
1645          num = num * 10 + chatToNum(s.charAt(i) );
1646        }
1647        return num;
1648      };
1649  
1650      var chatToNum = function(c) {
1651        if ('0' <= c && c <= '9') {
1652          return c.charCodeAt(0) - '0'.charCodeAt(0);
1653        }
1654        throw 'illegal char :' + c;
1655      };
1656  
1657      return _this;
1658    };
1659  
1660    //---------------------------------------------------------------------
1661    // qrAlphaNum
1662    //---------------------------------------------------------------------
1663  
1664    var qrAlphaNum = function(data) {
1665  
1666      var _mode = QRMode.MODE_ALPHA_NUM;
1667      var _data = data;
1668  
1669      var _this = {};
1670  
1671      _this.getMode = function() {
1672        return _mode;
1673      };
1674  
1675      _this.getLength = function(buffer) {
1676        return _data.length;
1677      };
1678  
1679      _this.write = function(buffer) {
1680  
1681        var s = _data;
1682  
1683        var i = 0;
1684  
1685        while (i + 1 < s.length) {
1686          buffer.put(
1687            getCode(s.charAt(i) ) * 45 +
1688            getCode(s.charAt(i + 1) ), 11);
1689          i += 2;
1690        }
1691  
1692        if (i < s.length) {
1693          buffer.put(getCode(s.charAt(i) ), 6);
1694        }
1695      };
1696  
1697      var getCode = function(c) {
1698  
1699        if ('0' <= c && c <= '9') {
1700          return c.charCodeAt(0) - '0'.charCodeAt(0);
1701        } else if ('A' <= c && c <= 'Z') {
1702          return c.charCodeAt(0) - 'A'.charCodeAt(0) + 10;
1703        } else {
1704          switch (c) {
1705          case ' ' : return 36;
1706          case '$' : return 37;
1707          case '%' : return 38;
1708          case '*' : return 39;
1709          case '+' : return 40;
1710          case '-' : return 41;
1711          case '.' : return 42;
1712          case '/' : return 43;
1713          case ':' : return 44;
1714          default :
1715            throw 'illegal char :' + c;
1716          }
1717        }
1718      };
1719  
1720      return _this;
1721    };
1722  
1723    //---------------------------------------------------------------------
1724    // qr8BitByte
1725    //---------------------------------------------------------------------
1726  
1727    var qr8BitByte = function(data) {
1728  
1729      var _mode = QRMode.MODE_8BIT_BYTE;
1730      var _data = data;
1731      var _bytes = qrcode.stringToBytes(data);
1732  
1733      var _this = {};
1734  
1735      _this.getMode = function() {
1736        return _mode;
1737      };
1738  
1739      _this.getLength = function(buffer) {
1740        return _bytes.length;
1741      };
1742  
1743      _this.write = function(buffer) {
1744        for (var i = 0; i < _bytes.length; i += 1) {
1745          buffer.put(_bytes[i], 8);
1746        }
1747      };
1748  
1749      return _this;
1750    };
1751  
1752    //---------------------------------------------------------------------
1753    // qrKanji
1754    //---------------------------------------------------------------------
1755  
1756    var qrKanji = function(data) {
1757  
1758      var _mode = QRMode.MODE_KANJI;
1759      var _data = data;
1760  
1761      var stringToBytes = qrcode.stringToBytesFuncs['SJIS'];
1762      if (!stringToBytes) {
1763        throw 'sjis not supported.';
1764      }
1765      !function(c, code) {
1766        // self test for sjis support.
1767        var test = stringToBytes(c);
1768        if (test.length != 2 || ( (test[0] << 8) | test[1]) != code) {
1769          throw 'sjis not supported.';
1770        }
1771      }('\u53cb', 0x9746);
1772  
1773      var _bytes = stringToBytes(data);
1774  
1775      var _this = {};
1776  
1777      _this.getMode = function() {
1778        return _mode;
1779      };
1780  
1781      _this.getLength = function(buffer) {
1782        return ~~(_bytes.length / 2);
1783      };
1784  
1785      _this.write = function(buffer) {
1786  
1787        var data = _bytes;
1788  
1789        var i = 0;
1790  
1791        while (i + 1 < data.length) {
1792  
1793          var c = ( (0xff & data[i]) << 8) | (0xff & data[i + 1]);
1794  
1795          if (0x8140 <= c && c <= 0x9FFC) {
1796            c -= 0x8140;
1797          } else if (0xE040 <= c && c <= 0xEBBF) {
1798            c -= 0xC140;
1799          } else {
1800            throw 'illegal char at ' + (i + 1) + '/' + c;
1801          }
1802  
1803          c = ( (c >>> 8) & 0xff) * 0xC0 + (c & 0xff);
1804  
1805          buffer.put(c, 13);
1806  
1807          i += 2;
1808        }
1809  
1810        if (i < data.length) {
1811          throw 'illegal char at ' + (i + 1);
1812        }
1813      };
1814  
1815      return _this;
1816    };
1817  
1818    //=====================================================================
1819    // GIF Support etc.
1820    //
1821  
1822    //---------------------------------------------------------------------
1823    // byteArrayOutputStream
1824    //---------------------------------------------------------------------
1825  
1826    var byteArrayOutputStream = function() {
1827  
1828      var _bytes = [];
1829  
1830      var _this = {};
1831  
1832      _this.writeByte = function(b) {
1833        _bytes.push(b & 0xff);
1834      };
1835  
1836      _this.writeShort = function(i) {
1837        _this.writeByte(i);
1838        _this.writeByte(i >>> 8);
1839      };
1840  
1841      _this.writeBytes = function(b, off, len) {
1842        off = off || 0;
1843        len = len || b.length;
1844        for (var i = 0; i < len; i += 1) {
1845          _this.writeByte(b[i + off]);
1846        }
1847      };
1848  
1849      _this.writeString = function(s) {
1850        for (var i = 0; i < s.length; i += 1) {
1851          _this.writeByte(s.charCodeAt(i) );
1852        }
1853      };
1854  
1855      _this.toByteArray = function() {
1856        return _bytes;
1857      };
1858  
1859      _this.toString = function() {
1860        var s = '';
1861        s += '[';
1862        for (var i = 0; i < _bytes.length; i += 1) {
1863          if (i > 0) {
1864            s += ',';
1865          }
1866          s += _bytes[i];
1867        }
1868        s += ']';
1869        return s;
1870      };
1871  
1872      return _this;
1873    };
1874  
1875    //---------------------------------------------------------------------
1876    // base64EncodeOutputStream
1877    //---------------------------------------------------------------------
1878  
1879    var base64EncodeOutputStream = function() {
1880  
1881      var _buffer = 0;
1882      var _buflen = 0;
1883      var _length = 0;
1884      var _base64 = '';
1885  
1886      var _this = {};
1887  
1888      var writeEncoded = function(b) {
1889        _base64 += String.fromCharCode(encode(b & 0x3f) );
1890      };
1891  
1892      var encode = function(n) {
1893        if (n < 0) {
1894          // error.
1895        } else if (n < 26) {
1896          return 0x41 + n;
1897        } else if (n < 52) {
1898          return 0x61 + (n - 26);
1899        } else if (n < 62) {
1900          return 0x30 + (n - 52);
1901        } else if (n == 62) {
1902          return 0x2b;
1903        } else if (n == 63) {
1904          return 0x2f;
1905        }
1906        throw 'n:' + n;
1907      };
1908  
1909      _this.writeByte = function(n) {
1910  
1911        _buffer = (_buffer << 8) | (n & 0xff);
1912        _buflen += 8;
1913        _length += 1;
1914  
1915        while (_buflen >= 6) {
1916          writeEncoded(_buffer >>> (_buflen - 6) );
1917          _buflen -= 6;
1918        }
1919      };
1920  
1921      _this.flush = function() {
1922  
1923        if (_buflen > 0) {
1924          writeEncoded(_buffer << (6 - _buflen) );
1925          _buffer = 0;
1926          _buflen = 0;
1927        }
1928  
1929        if (_length % 3 != 0) {
1930          // padding
1931          var padlen = 3 - _length % 3;
1932          for (var i = 0; i < padlen; i += 1) {
1933            _base64 += '=';
1934          }
1935        }
1936      };
1937  
1938      _this.toString = function() {
1939        return _base64;
1940      };
1941  
1942      return _this;
1943    };
1944  
1945    //---------------------------------------------------------------------
1946    // base64DecodeInputStream
1947    //---------------------------------------------------------------------
1948  
1949    var base64DecodeInputStream = function(str) {
1950  
1951      var _str = str;
1952      var _pos = 0;
1953      var _buffer = 0;
1954      var _buflen = 0;
1955  
1956      var _this = {};
1957  
1958      _this.read = function() {
1959  
1960        while (_buflen < 8) {
1961  
1962          if (_pos >= _str.length) {
1963            if (_buflen == 0) {
1964              return -1;
1965            }
1966            throw 'unexpected end of file./' + _buflen;
1967          }
1968  
1969          var c = _str.charAt(_pos);
1970          _pos += 1;
1971  
1972          if (c == '=') {
1973            _buflen = 0;
1974            return -1;
1975          } else if (c.match(/^\s$/) ) {
1976            // ignore if whitespace.
1977            continue;
1978          }
1979  
1980          _buffer = (_buffer << 6) | decode(c.charCodeAt(0) );
1981          _buflen += 6;
1982        }
1983  
1984        var n = (_buffer >>> (_buflen - 8) ) & 0xff;
1985        _buflen -= 8;
1986        return n;
1987      };
1988  
1989      var decode = function(c) {
1990        if (0x41 <= c && c <= 0x5a) {
1991          return c - 0x41;
1992        } else if (0x61 <= c && c <= 0x7a) {
1993          return c - 0x61 + 26;
1994        } else if (0x30 <= c && c <= 0x39) {
1995          return c - 0x30 + 52;
1996        } else if (c == 0x2b) {
1997          return 62;
1998        } else if (c == 0x2f) {
1999          return 63;
2000        } else {
2001          throw 'c:' + c;
2002        }
2003      };
2004  
2005      return _this;
2006    };
2007  
2008    //---------------------------------------------------------------------
2009    // gifImage (B/W)
2010    //---------------------------------------------------------------------
2011  
2012    var gifImage = function(width, height) {
2013  
2014      var _width = width;
2015      var _height = height;
2016      var _data = new Array(width * height);
2017  
2018      var _this = {};
2019  
2020      _this.setPixel = function(x, y, pixel) {
2021        _data[y * _width + x] = pixel;
2022      };
2023  
2024      _this.write = function(out) {
2025  
2026        //---------------------------------
2027        // GIF Signature
2028  
2029        out.writeString('GIF87a');
2030  
2031        //---------------------------------
2032        // Screen Descriptor
2033  
2034        out.writeShort(_width);
2035        out.writeShort(_height);
2036  
2037        out.writeByte(0x80); // 2bit
2038        out.writeByte(0);
2039        out.writeByte(0);
2040  
2041        //---------------------------------
2042        // Global Color Map
2043  
2044        // black
2045        out.writeByte(0x00);
2046        out.writeByte(0x00);
2047        out.writeByte(0x00);
2048  
2049        // white
2050        out.writeByte(0xff);
2051        out.writeByte(0xff);
2052        out.writeByte(0xff);
2053  
2054        //---------------------------------
2055        // Image Descriptor
2056  
2057        out.writeString(',');
2058        out.writeShort(0);
2059        out.writeShort(0);
2060        out.writeShort(_width);
2061        out.writeShort(_height);
2062        out.writeByte(0);
2063  
2064        //---------------------------------
2065        // Local Color Map
2066  
2067        //---------------------------------
2068        // Raster Data
2069  
2070        var lzwMinCodeSize = 2;
2071        var raster = getLZWRaster(lzwMinCodeSize);
2072  
2073        out.writeByte(lzwMinCodeSize);
2074  
2075        var offset = 0;
2076  
2077        while (raster.length - offset > 255) {
2078          out.writeByte(255);
2079          out.writeBytes(raster, offset, 255);
2080          offset += 255;
2081        }
2082  
2083        out.writeByte(raster.length - offset);
2084        out.writeBytes(raster, offset, raster.length - offset);
2085        out.writeByte(0x00);
2086  
2087        //---------------------------------
2088        // GIF Terminator
2089        out.writeString(';');
2090      };
2091  
2092      var bitOutputStream = function(out) {
2093  
2094        var _out = out;
2095        var _bitLength = 0;
2096        var _bitBuffer = 0;
2097  
2098        var _this = {};
2099  
2100        _this.write = function(data, length) {
2101  
2102          if ( (data >>> length) != 0) {
2103            throw 'length over';
2104          }
2105  
2106          while (_bitLength + length >= 8) {
2107            _out.writeByte(0xff & ( (data << _bitLength) | _bitBuffer) );
2108            length -= (8 - _bitLength);
2109            data >>>= (8 - _bitLength);
2110            _bitBuffer = 0;
2111            _bitLength = 0;
2112          }
2113  
2114          _bitBuffer = (data << _bitLength) | _bitBuffer;
2115          _bitLength = _bitLength + length;
2116        };
2117  
2118        _this.flush = function() {
2119          if (_bitLength > 0) {
2120            _out.writeByte(_bitBuffer);
2121          }
2122        };
2123  
2124        return _this;
2125      };
2126  
2127      var getLZWRaster = function(lzwMinCodeSize) {
2128  
2129        var clearCode = 1 << lzwMinCodeSize;
2130        var endCode = (1 << lzwMinCodeSize) + 1;
2131        var bitLength = lzwMinCodeSize + 1;
2132  
2133        // Setup LZWTable
2134        var table = lzwTable();
2135  
2136        for (var i = 0; i < clearCode; i += 1) {
2137          table.add(String.fromCharCode(i) );
2138        }
2139        table.add(String.fromCharCode(clearCode) );
2140        table.add(String.fromCharCode(endCode) );
2141  
2142        var byteOut = byteArrayOutputStream();
2143        var bitOut = bitOutputStream(byteOut);
2144  
2145        // clear code
2146        bitOut.write(clearCode, bitLength);
2147  
2148        var dataIndex = 0;
2149  
2150        var s = String.fromCharCode(_data[dataIndex]);
2151        dataIndex += 1;
2152  
2153        while (dataIndex < _data.length) {
2154  
2155          var c = String.fromCharCode(_data[dataIndex]);
2156          dataIndex += 1;
2157  
2158          if (table.contains(s + c) ) {
2159  
2160            s = s + c;
2161  
2162          } else {
2163  
2164            bitOut.write(table.indexOf(s), bitLength);
2165  
2166            if (table.size() < 0xfff) {
2167  
2168              if (table.size() == (1 << bitLength) ) {
2169                bitLength += 1;
2170              }
2171  
2172              table.add(s + c);
2173            }
2174  
2175            s = c;
2176          }
2177        }
2178  
2179        bitOut.write(table.indexOf(s), bitLength);
2180  
2181        // end code
2182        bitOut.write(endCode, bitLength);
2183  
2184        bitOut.flush();
2185  
2186        return byteOut.toByteArray();
2187      };
2188  
2189      var lzwTable = function() {
2190  
2191        var _map = {};
2192        var _size = 0;
2193  
2194        var _this = {};
2195  
2196        _this.add = function(key) {
2197          if (_this.contains(key) ) {
2198            throw 'dup key:' + key;
2199          }
2200          _map[key] = _size;
2201          _size += 1;
2202        };
2203  
2204        _this.size = function() {
2205          return _size;
2206        };
2207  
2208        _this.indexOf = function(key) {
2209          return _map[key];
2210        };
2211  
2212        _this.contains = function(key) {
2213          return typeof _map[key] != 'undefined';
2214        };
2215  
2216        return _this;
2217      };
2218  
2219      return _this;
2220    };
2221  
2222    var createDataURL = function(width, height, getPixel) {
2223      var gif = gifImage(width, height);
2224      for (var y = 0; y < height; y += 1) {
2225        for (var x = 0; x < width; x += 1) {
2226          gif.setPixel(x, y, getPixel(x, y) );
2227        }
2228      }
2229  
2230      var b = byteArrayOutputStream();
2231      gif.write(b);
2232  
2233      var base64 = base64EncodeOutputStream();
2234      var bytes = b.toByteArray();
2235      for (var i = 0; i < bytes.length; i += 1) {
2236        base64.writeByte(bytes[i]);
2237      }
2238      base64.flush();
2239  
2240      return 'data:image/gif;base64,' + base64;
2241    };
2242  
2243    //---------------------------------------------------------------------
2244    // returns qrcode function.
2245  
2246    return qrcode;
2247  }();
2248  
2249  // multibyte support
2250  !function() {
2251  
2252    qrcode.stringToBytesFuncs['UTF-8'] = function(s) {
2253      // http://stackoverflow.com/questions/18729405/how-to-convert-utf8-string-to-byte-array
2254      function toUTF8Array(str) {
2255        var utf8 = [];
2256        for (var i=0; i < str.length; i++) {
2257          var charcode = str.charCodeAt(i);
2258          if (charcode < 0x80) utf8.push(charcode);
2259          else if (charcode < 0x800) {
2260            utf8.push(0xc0 | (charcode >> 6),
2261                0x80 | (charcode & 0x3f));
2262          }
2263          else if (charcode < 0xd800 || charcode >= 0xe000) {
2264            utf8.push(0xe0 | (charcode >> 12),
2265                0x80 | ((charcode>>6) & 0x3f),
2266                0x80 | (charcode & 0x3f));
2267          }
2268          // surrogate pair
2269          else {
2270            i++;
2271            // UTF-16 encodes 0x10000-0x10FFFF by
2272            // subtracting 0x10000 and splitting the
2273            // 20 bits of 0x0-0xFFFFF into two halves
2274            charcode = 0x10000 + (((charcode & 0x3ff)<<10)
2275              | (str.charCodeAt(i) & 0x3ff));
2276            utf8.push(0xf0 | (charcode >>18),
2277                0x80 | ((charcode>>12) & 0x3f),
2278                0x80 | ((charcode>>6) & 0x3f),
2279                0x80 | (charcode & 0x3f));
2280          }
2281        }
2282        return utf8;
2283      }
2284      return toUTF8Array(s);
2285    };
2286  
2287  }();
2288  
2289  (function (factory) {
2290    if (typeof define === 'function' && define.amd) {
2291        define([], factory);
2292    } else if (typeof exports === 'object') {
2293        module.exports = factory();
2294    }
2295  }(function () {
2296      return qrcode;
2297  }));


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer