diff options
| author | Adam Soltys <[email protected]> | 2023-09-21 11:59:12 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2023-09-21 11:59:12 -0700 |
| commit | 0fc21acf8ba14a3f5e306c9829573f3ac7d0e05f (patch) | |
| tree | 59e749043ecdc3730d97e23ebfe56a2258361631 /static | |
| parent | 92ff34396242e2a22d0c3f8248dc08451afc7cab (diff) | |
| parent | 3d8943e5bc1fbe7904d04531521f5496962e6efc (diff) | |
| download | coinos-ui-0fc21acf8ba14a3f5e306c9829573f3ac7d0e05f.tar.gz coinos-ui-0fc21acf8ba14a3f5e306c9829573f3ac7d0e05f.zip | |
Merge branch 'master' into swapee
Diffstat (limited to 'static')
| -rw-r--r-- | static/icons/link.svg | 1 | ||||
| -rw-r--r-- | static/icons/shopify.svg | 2 | ||||
| -rw-r--r-- | static/qr.js | 1626 | ||||
| -rw-r--r-- | static/shopify.html | 167 |
4 files changed, 1796 insertions, 0 deletions
diff --git a/static/icons/link.svg b/static/icons/link.svg new file mode 100644 index 00000000..7b3654be --- /dev/null +++ b/static/icons/link.svg @@ -0,0 +1 @@ +<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd"><path d="M14.851 11.923c-.179-.641-.521-1.246-1.025-1.749-1.562-1.562-4.095-1.563-5.657 0l-4.998 4.998c-1.562 1.563-1.563 4.095 0 5.657 1.562 1.563 4.096 1.561 5.656 0l3.842-3.841.333.009c.404 0 .802-.04 1.189-.117l-4.657 4.656c-.975.976-2.255 1.464-3.535 1.464-1.28 0-2.56-.488-3.535-1.464-1.952-1.951-1.952-5.12 0-7.071l4.998-4.998c.975-.976 2.256-1.464 3.536-1.464 1.279 0 2.56.488 3.535 1.464.493.493.861 1.063 1.105 1.672l-.787.784zm-5.703.147c.178.643.521 1.25 1.026 1.756 1.562 1.563 4.096 1.561 5.656 0l4.999-4.998c1.563-1.562 1.563-4.095 0-5.657-1.562-1.562-4.095-1.563-5.657 0l-3.841 3.841-.333-.009c-.404 0-.802.04-1.189.117l4.656-4.656c.975-.976 2.256-1.464 3.536-1.464 1.279 0 2.56.488 3.535 1.464 1.951 1.951 1.951 5.119 0 7.071l-4.999 4.998c-.975.976-2.255 1.464-3.535 1.464-1.28 0-2.56-.488-3.535-1.464-.494-.495-.863-1.067-1.107-1.678l.788-.785z"/></svg>
\ No newline at end of file diff --git a/static/icons/shopify.svg b/static/icons/shopify.svg new file mode 100644 index 00000000..426386ea --- /dev/null +++ b/static/icons/shopify.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="800px" height="800px" viewBox="-18 0 292 292" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M223.774 57.34c-.201-1.46-1.48-2.268-2.537-2.357-1.055-.088-23.383-1.743-23.383-1.743s-15.507-15.395-17.209-17.099c-1.703-1.703-5.029-1.185-6.32-.805-.19.056-3.388 1.043-8.678 2.68-5.18-14.906-14.322-28.604-30.405-28.604-.444 0-.901.018-1.358.044C129.31 3.407 123.644.779 118.75.779c-37.465 0-55.364 46.835-60.976 70.635-14.558 4.511-24.9 7.718-26.221 8.133-8.126 2.549-8.383 2.805-9.45 10.462C21.3 95.806.038 260.235.038 260.235l165.678 31.042 89.77-19.42S223.973 58.8 223.775 57.34zM156.49 40.848l-14.019 4.339c.005-.988.01-1.96.01-3.023 0-9.264-1.286-16.723-3.349-22.636 8.287 1.04 13.806 10.469 17.358 21.32zm-27.638-19.483c2.304 5.773 3.802 14.058 3.802 25.238 0 .572-.005 1.095-.01 1.624-9.117 2.824-19.024 5.89-28.953 8.966 5.575-21.516 16.025-31.908 25.161-35.828zm-11.131-10.537c1.617 0 3.246.549 4.805 1.622-12.007 5.65-24.877 19.88-30.312 48.297l-22.886 7.088C75.694 46.16 90.81 10.828 117.72 10.828z" fill="#95BF46"/><path d="M221.237 54.983c-1.055-.088-23.383-1.743-23.383-1.743s-15.507-15.395-17.209-17.099c-.637-.634-1.496-.959-2.394-1.099l-12.527 256.233 89.762-19.418S223.972 58.8 223.774 57.34c-.201-1.46-1.48-2.268-2.537-2.357" fill="#5E8E3E"/><path d="M135.242 104.585l-11.069 32.926s-9.698-5.176-21.586-5.176c-17.428 0-18.305 10.937-18.305 13.693 0 15.038 39.2 20.8 39.2 56.024 0 27.713-17.577 45.558-41.277 45.558-28.44 0-42.984-17.7-42.984-17.7l7.615-25.16s14.95 12.835 27.565 12.835c8.243 0 11.596-6.49 11.596-11.232 0-19.616-32.16-20.491-32.16-52.724 0-27.129 19.472-53.382 58.778-53.382 15.145 0 22.627 4.338 22.627 4.338" fill="#FFF"/></svg>
\ No newline at end of file diff --git a/static/qr.js b/static/qr.js new file mode 100644 index 00000000..92aa4ec1 --- /dev/null +++ b/static/qr.js @@ -0,0 +1,1626 @@ +//--------------------------------------------------------------------- +// +// 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 +// +//--------------------------------------------------------------------- + +//---------------微信小程序基于base64生成二维码插件修改------------------- +/* + * @Modified: Pudon + * @demoURL: https://github.com/Pudon/weapp-qrcode + * @Date: 2018-09-11 14:00:05 + * @Last Modified by: Pudon + * @Last Modified time: 2018-09-12 16:33:19 + */ +//--------------------------------------------------------------------- + +/** + * 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, size) { + + cellSize = cellSize || 2; + margin = (typeof margin == 'undefined')? cellSize * 4 : margin; + + var min = margin; + var max = _this.getModuleCount() * cellSize + 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() { + + + // [1: [L, M, Q, H], ..] + var RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,45,15,67,46,16],[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 _parsedData = []; + + var _this = {}; + + + // Added to support UTF-8 Characters + for (var i = 0, l = _data.length; i < l; i++) { + var byteArray = []; + var code = _data.charCodeAt(i); + + if (code > 0x10000) { + byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18); + byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12); + byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6); + byteArray[3] = 0x80 | (code & 0x3F); + } else if (code > 0x800) { + byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12); + byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6); + byteArray[2] = 0x80 | (code & 0x3F); + } else if (code > 0x80) { + byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6); + byteArray[1] = 0x80 | (code & 0x3F); + } else { + byteArray[0] = code; + } + + // Fix Unicode corruption bug + _parsedData.push(byteArray); + } + + _parsedData = Array.prototype.concat.apply([], _parsedData); + + if (_parsedData.length != _data.length) { + _parsedData.unshift(191); + _parsedData.unshift(187); + _parsedData.unshift(239); + } + + var _bytes = _parsedData; + + _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 += 'data:image/gif;base64,'; + img += base64; + + return img; +}; + +//--------------------------------------------------------------------- +// returns qrcode function. + +var drawImg = function(text, options) { + options = options || {}; + var typeNumber = options.typeNumber || 4; + var errorCorrectLevel = options.errorCorrectLevel || 'M'; + var size = options.size || 500; + + var qr; + + try { + qr = qrcode(typeNumber, errorCorrectLevel || 'M'); + qr.addData(text); + qr.make(); + } catch (e) { + if(typeNumber >= 40) { + throw new Error('Text too long to encode'); + } else { + return drawImg(text, { + size: size, + errorCorrectLevel: errorCorrectLevel, + typeNumber: typeNumber + 1 + }); + } + } + + // calc cellsize and margin + var cellsize = parseInt(size / qr.getModuleCount()); + var margin = parseInt((size - qr.getModuleCount() * cellsize) / 2); + + return qr.createImgTag(cellsize, margin, size); +}; + +export default { + drawImg: drawImg +};
\ No newline at end of file diff --git a/static/shopify.html b/static/shopify.html new file mode 100644 index 00000000..886c3d34 --- /dev/null +++ b/static/shopify.html @@ -0,0 +1,167 @@ +<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script> +<script> + window.addEventListener('load', async () => { + let sat = (s) => { + s = Math.abs(s); + let p = Math.floor(Math.log(s) / Math.LN10 + 0.000000001); + let d = Math.floor((p + 1) / 3); + + return ( + '⚡️' + + (parseInt(s) > 0 + ? new Intl.NumberFormat('en-US', { maximumFractionDigits: 2 }).format( + s / Math.pow(1000, d) + ) + ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'][d] + : 0 + ).toString() + ); + }; + + let copy = (text) => { + navigator.clipboard.writeText(text); + }; + + let f = (s, currency) => + new Intl.NumberFormat('en-US', { + style: 'currency', + currency + }) + .format(s) + .replace('CA', ''); + + let s = (s) => new Intl.NumberFormat('en-US', { maximumFractionDigits: 0 }).format(s); + + let { + default: { drawImg } + } = await import('https://coinos.io/qr.js'); + let base64 = drawImg('test', { size: 300 }); + + let link = document.createElement('link'); + link.setAttribute('rel', 'stylesheet'); + link.setAttribute('type', 'text/css'); + link.setAttribute( + 'href', + 'https://fonts.googleapis.com/css?family=Public+Sans:400italic,400,300,700' + ); + + var style = document.createElement('style'); + style.innerHTML = `#check { + transform: scale(0.5); + transition: transform 1s; + } + `; + document.head.appendChild(style); + + document.head.appendChild(link); + document.title = 'Pay With Bitcoin'; + + let fiat = Shopify.checkout.payment_due; + let main = document.querySelector('main'); + main.style.fontFamily = 'Public Sans, sans-serif'; + main.innerHTML = 'Please Pay'; + + let data = await fetch('https://dev.coinos.io/api/invoice', { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + accept: 'application/json' + }, + body: JSON.stringify({ + invoice: { + fiat, + type: 'lightning', + webhook: `https://dev.coinos.io/api/shopify/${Shopify.checkout.order_id}` + }, + user: { username: 'horseradish' } + }) + }) + .then(function (response) { + return response.json(); + }) + .catch(console.log); + + main.innerHTML = `<a href="lightning:${data.hash}"> + <div style="display: flex; margin-top: 50px; margin-bottom: 80px; position: relative;"> + <img id="qrcode" src="${base64}" /> + <div id="bg"></div> + </div> + </a> + <div style="width: 100%; text-align: center; "> + <div style="font-size: 24px; font-weight: bold; margin-bottom: 12px;">${f( + (data.amount * data.rate) / 100000000, + data.currency + )}</div> + <div style="color: #666; font-size: 18px;">${sat(data.amount)}</div> + </div> + <div style="text-align: center; margin: 40px auto; max-width: 460px; word-break: break-all; line-height: 1.5rem">${ + data.hash + }</div> + <div style="margin: 20px 0; display: flex; gap: 1rem; justify-content: center; align-items: center;"> + <a href="lightning:${data.hash}" style="text-decoration: none"> + <div style="color: #999; font-size: 18px; border-radius: 9999px; padding: 0.5rem 1rem; border: 1px solid #ccc; background: white;">Open</div> + </a> + + <a id="copy" href="#" style="text-decoration: none"> + <div style="color: #999; font-size: 18px; border-radius: 9999px; padding: 0.5rem 1rem; border: 1px solid #ccc; background: white;">Copy</div></a> + </div> + `; + + let copyButton = document.getElementById('copy'); + copyButton.addEventListener('click', (e) => { + e.preventDefault(); + copy(data.hash); + let copied = document.createElement('div'); + copied.textContent = 'Copied!'; + main.appendChild(copied); + setTimeout(() => copied.remove(), 3000); + }); + + let qr = document.getElementById('qrcode'); + qr.style.margin = 'auto'; + qr.style.marginTop = '40px'; + qr.style.border = '12px white solid'; + qr.style.zIndex = 10; + + new QRCode(qr, data.hash); + + let bg = document.getElementById('bg'); + bg.style.position = 'absolute'; + bg.style.margin = 'auto'; + bg.style.left = '0'; + bg.style.right = '0'; + bg.style.width = '400px'; + bg.style.height = '400px'; + bg.style.borderRadius = '50%'; + bg.style.background = 'linear-gradient(to right, #F2F6FC, #E1E3FF)'; + bg.style.zIndex = '0'; + + let ws = new WebSocket('wss://dev.coinos.io/ws'); + ws.onmessage = ({ data }) => { + try { + let { type, data: d } = JSON.parse(data); + if (type === 'payment') { + main.innerHTML = + '<img id="check" src="https://dev.coinos.io/icons/check.svg" alt="Check" />' + + `<h1>Payment received!</h1> + <h2> + ${((d.amount * d.rate) / 100000000).toFixed(2)} CAD + </h2> + <h3> + ⚡️${d.amount} + </h3>`; + + var image = document.getElementById('check'); + image.addEventListener('load', function () { + image.style.transform = 'scale(1)'; + }); + } + } catch (e) { + console.log(e); + } + }; + ws.onopen = () => { + ws.send(JSON.stringify({ type: 'subscribe', data })); + }; + }); +</script> |
