Created
April 28, 2022 21:09
-
-
Save krunkster/81402ce230990eeee9f342f4b194a4a1 to your computer and use it in GitHub Desktop.
GDevelop Extension for creating QR Codes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"author": "", | |
"category": "Advanced", | |
"description": "Adapted from https://github.com/Canees/qrcode-base64 and \"Import Image Using URL\" example.", | |
"extensionNamespace": "", | |
"fullName": "QR Code Utils", | |
"helpPath": "", | |
"iconUrl": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0ibWRpLWRhdGEtbWF0cml4LXNjYW4iIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMiAySDZWMEgyQy45IDAgMCAuOSAwIDJWNkgyVjJNMjIgMEgxOFYySDIyVjZIMjRWMkMyNCAuOSAyMy4xIDAgMjIgME0yIDE4SDBWMjJDMCAyMy4xIC45IDI0IDIgMjRINlYyMkgyVjE4TTIyIDIySDE4VjI0SDIyQzIzLjEgMjQgMjQgMjMuMSAyNCAyMlYxOEgyMlYyMk04IDZWNEgxMFY2SDhNMTAgMTRWMTJIMTJWMTRIMTBNMTYgNEgxOFY2SDE2VjRNMTggNkgyMFY4SDE4VjZNMTggMTRIMjBWMTZIMThWMTRNMjAgMTJIMTZWMThIMjBWMjBINFY0SDZWNkg4VjEwSDZWMTJIOFYxNEgxMFYxNkgxMlYxOEgxNFYxNkgxMlYxNEgxNFYxMEgxMFY2SDEyVjRIMTRWOEgxNlYxMEgyMFYxMk04IDE4VjE2SDZWMThIOFoiIC8+PC9zdmc+", | |
"name": "QRCode", | |
"previewIconUrl": "https://resources.gdevelop-app.com/assets/Icons/data-matrix-scan.svg", | |
"shortDescription": "Adds a function to generate a QR Code from a string of data and replace a sprite in the scene with the new QR code texture.", | |
"version": "1.0", | |
"tags": [ | |
"qr", | |
"qrcode", | |
"stenography" | |
], | |
"authorIds": [ | |
"Khhq7a4Lu8bt91GLLhG0QiGLpfx2" | |
], | |
"dependencies": [], | |
"eventsFunctions": [ | |
{ | |
"description": "", | |
"fullName": "Generate QR Code", | |
"functionType": "Action", | |
"group": "", | |
"name": "GenerateQRCode", | |
"private": false, | |
"sentence": "Creates a QR Code from input string _PARAM1_ and replaces sprite _PARAM2_ image", | |
"events": [ | |
{ | |
"disabled": false, | |
"folded": false, | |
"type": "BuiltinCommonInstructions::Standard", | |
"conditions": [], | |
"actions": [], | |
"events": [] | |
}, | |
{ | |
"disabled": false, | |
"folded": false, | |
"type": "BuiltinCommonInstructions::JsCode", | |
"inlineCode": "/*\n * Code below used under MIT license\n * https://github.com/Canees/qrcode-base64\n*/\n\nvar globalConfig = {\n colors: [],\n backgrounds: []\n }\n /**\n * qrcode\n * @param typeNumber 1 to 40\n * @param errorCorrectLevel 'L','M','Q','H'\n */\n var qrcode = function (typeNumber, errorCorrectLevel) {\n \n var PAD0 = 0xEC;\n var PAD1 = 0x11;\n \n var _typeNumber = typeNumber;\n var _errorCorrectLevel = QRErrorCorrectLevel[errorCorrectLevel];\n var _modules = null;\n var _moduleCount = 0;\n var _dataCache = null;\n var _dataList = new Array();\n \n var _this = {};\n \n var makeImpl = function (test, maskPattern) {\n \n _moduleCount = _typeNumber * 4 + 17;\n _modules = function (moduleCount) {\n var modules = new Array(moduleCount);\n for (var row = 0; row < moduleCount; row += 1) {\n modules[row] = new Array(moduleCount);\n for (var col = 0; col < moduleCount; col += 1) {\n modules[row][col] = null;\n }\n }\n return modules;\n }(_moduleCount);\n \n setupPositionProbePattern(0, 0);\n setupPositionProbePattern(_moduleCount - 7, 0);\n setupPositionProbePattern(0, _moduleCount - 7);\n setupPositionAdjustPattern();\n setupTimingPattern();\n setupTypeInfo(test, maskPattern);\n \n if (_typeNumber >= 7) {\n setupTypeNumber(test);\n }\n \n if (_dataCache == null) {\n _dataCache = createData(_typeNumber, _errorCorrectLevel, _dataList);\n }\n \n mapData(_dataCache, maskPattern);\n };\n \n var setupPositionProbePattern = function (row, col) {\n \n for (var r = -1; r <= 7; r += 1) {\n \n if (row + r <= -1 || _moduleCount <= row + r) continue;\n \n for (var c = -1; c <= 7; c += 1) {\n \n if (col + c <= -1 || _moduleCount <= col + c) continue;\n \n if ((0 <= r && r <= 6 && (c == 0 || c == 6))\n || (0 <= c && c <= 6 && (r == 0 || r == 6))\n || (2 <= r && r <= 4 && 2 <= c && c <= 4)) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n };\n \n var getBestMaskPattern = function () {\n \n var minLostPoint = 0;\n var pattern = 0;\n \n for (var i = 0; i < 8; i += 1) {\n \n makeImpl(true, i);\n \n var lostPoint = QRUtil.getLostPoint(_this);\n \n if (i == 0 || minLostPoint > lostPoint) {\n minLostPoint = lostPoint;\n pattern = i;\n }\n }\n \n return pattern;\n };\n \n var setupTimingPattern = function () {\n \n for (var r = 8; r < _moduleCount - 8; r += 1) {\n if (_modules[r][6] != null) {\n continue;\n }\n _modules[r][6] = (r % 2 == 0);\n }\n \n for (var c = 8; c < _moduleCount - 8; c += 1) {\n if (_modules[6][c] != null) {\n continue;\n }\n _modules[6][c] = (c % 2 == 0);\n }\n };\n \n var setupPositionAdjustPattern = function () {\n \n var pos = QRUtil.getPatternPosition(_typeNumber);\n \n for (var i = 0; i < pos.length; i += 1) {\n \n for (var j = 0; j < pos.length; j += 1) {\n \n var row = pos[i];\n var col = pos[j];\n \n if (_modules[row][col] != null) {\n continue;\n }\n \n for (var r = -2; r <= 2; r += 1) {\n \n for (var c = -2; c <= 2; c += 1) {\n \n if (r == -2 || r == 2 || c == -2 || c == 2\n || (r == 0 && c == 0)) {\n _modules[row + r][col + c] = true;\n } else {\n _modules[row + r][col + c] = false;\n }\n }\n }\n }\n }\n };\n \n var setupTypeNumber = function (test) {\n \n var bits = QRUtil.getBCHTypeNumber(_typeNumber);\n \n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ((bits >> i) & 1) == 1);\n _modules[Math.floor(i / 3)][i % 3 + _moduleCount - 8 - 3] = mod;\n }\n \n for (var i = 0; i < 18; i += 1) {\n var mod = (!test && ((bits >> i) & 1) == 1);\n _modules[i % 3 + _moduleCount - 8 - 3][Math.floor(i / 3)] = mod;\n }\n };\n \n var setupTypeInfo = function (test, maskPattern) {\n \n var data = (_errorCorrectLevel << 3) | maskPattern;\n var bits = QRUtil.getBCHTypeInfo(data);\n \n // vertical\n for (var i = 0; i < 15; i += 1) {\n \n var mod = (!test && ((bits >> i) & 1) == 1);\n \n if (i < 6) {\n _modules[i][8] = mod;\n } else if (i < 8) {\n _modules[i + 1][8] = mod;\n } else {\n _modules[_moduleCount - 15 + i][8] = mod;\n }\n }\n \n // horizontal\n for (var i = 0; i < 15; i += 1) {\n \n var mod = (!test && ((bits >> i) & 1) == 1);\n \n if (i < 8) {\n _modules[8][_moduleCount - i - 1] = mod;\n } else if (i < 9) {\n _modules[8][15 - i - 1 + 1] = mod;\n } else {\n _modules[8][15 - i - 1] = mod;\n }\n }\n \n // fixed module\n _modules[_moduleCount - 8][8] = (!test);\n };\n \n var mapData = function (data, maskPattern) {\n \n var inc = -1;\n var row = _moduleCount - 1;\n var bitIndex = 7;\n var byteIndex = 0;\n var maskFunc = QRUtil.getMaskFunction(maskPattern);\n \n for (var col = _moduleCount - 1; col > 0; col -= 2) {\n \n if (col == 6) col -= 1;\n \n while (true) {\n \n for (var c = 0; c < 2; c += 1) {\n \n if (_modules[row][col - c] == null) {\n \n var dark = false;\n \n if (byteIndex < data.length) {\n dark = (((data[byteIndex] >>> bitIndex) & 1) == 1);\n }\n \n var mask = maskFunc(row, col - c);\n \n if (mask) {\n dark = !dark;\n }\n \n _modules[row][col - c] = dark;\n bitIndex -= 1;\n \n if (bitIndex == -1) {\n byteIndex += 1;\n bitIndex = 7;\n }\n }\n }\n \n row += inc;\n \n if (row < 0 || _moduleCount <= row) {\n row -= inc;\n inc = -inc;\n break;\n }\n }\n }\n };\n \n var createBytes = function (buffer, rsBlocks) {\n \n var offset = 0;\n \n var maxDcCount = 0;\n var maxEcCount = 0;\n \n var dcdata = new Array(rsBlocks.length);\n var ecdata = new Array(rsBlocks.length);\n \n for (var r = 0; r < rsBlocks.length; r += 1) {\n \n var dcCount = rsBlocks[r].dataCount;\n var ecCount = rsBlocks[r].totalCount - dcCount;\n \n maxDcCount = Math.max(maxDcCount, dcCount);\n maxEcCount = Math.max(maxEcCount, ecCount);\n \n dcdata[r] = new Array(dcCount);\n \n for (var i = 0; i < dcdata[r].length; i += 1) {\n dcdata[r][i] = 0xff & buffer.getBuffer()[i + offset];\n }\n offset += dcCount;\n \n var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);\n var rawPoly = qrPolynomial(dcdata[r], rsPoly.getLength() - 1);\n \n var modPoly = rawPoly.mod(rsPoly);\n ecdata[r] = new Array(rsPoly.getLength() - 1);\n for (var i = 0; i < ecdata[r].length; i += 1) {\n var modIndex = i + modPoly.getLength() - ecdata[r].length;\n ecdata[r][i] = (modIndex >= 0) ? modPoly.getAt(modIndex) : 0;\n }\n }\n \n var totalCodeCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalCodeCount += rsBlocks[i].totalCount;\n }\n \n var data = new Array(totalCodeCount);\n var index = 0;\n \n for (var i = 0; i < maxDcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < dcdata[r].length) {\n data[index] = dcdata[r][i];\n index += 1;\n }\n }\n }\n \n for (var i = 0; i < maxEcCount; i += 1) {\n for (var r = 0; r < rsBlocks.length; r += 1) {\n if (i < ecdata[r].length) {\n data[index] = ecdata[r][i];\n index += 1;\n }\n }\n }\n \n return data;\n };\n \n var createData = function (typeNumber, errorCorrectLevel, dataList) {\n \n var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);\n \n var buffer = qrBitBuffer();\n \n for (var i = 0; i < dataList.length; i += 1) {\n var data = dataList[i];\n buffer.put(data.getMode(), 4);\n buffer.put(data.getLength(), QRUtil.getLengthInBits(data.getMode(), typeNumber));\n data.write(buffer);\n }\n \n // calc num max data.\n var totalDataCount = 0;\n for (var i = 0; i < rsBlocks.length; i += 1) {\n totalDataCount += rsBlocks[i].dataCount;\n }\n \n if (buffer.getLengthInBits() > totalDataCount * 8) {\n throw new Error('code length overflow. ('\n + buffer.getLengthInBits()\n + '>'\n + totalDataCount * 8\n + ')');\n }\n \n // end code\n if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {\n buffer.put(0, 4);\n }\n \n // padding\n while (buffer.getLengthInBits() % 8 != 0) {\n buffer.putBit(false);\n }\n \n // padding\n while (true) {\n \n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD0, 8);\n \n if (buffer.getLengthInBits() >= totalDataCount * 8) {\n break;\n }\n buffer.put(PAD1, 8);\n }\n \n return createBytes(buffer, rsBlocks);\n };\n \n _this.addData = function (data) {\n var newData = qr8BitByte(data);\n _dataList.push(newData);\n _dataCache = null;\n };\n \n _this.isDark = function (row, col) {\n if (row < 0 || _moduleCount <= row || col < 0 || _moduleCount <= col) {\n throw new Error(row + ',' + col);\n }\n return _modules[row][col];\n };\n \n _this.getModuleCount = function () {\n return _moduleCount;\n };\n \n _this.make = function () {\n makeImpl(false, getBestMaskPattern());\n };\n \n _this.createTableTag = function (cellSize, margin) {\n \n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined') ? cellSize * 4 : margin;\n \n var qrHtml = '';\n \n qrHtml += '<table style=\"';\n qrHtml += ' border-width: 0px; border-style: none;';\n qrHtml += ' border-collapse: collapse;';\n qrHtml += ' padding: 0px; margin: ' + margin + 'px;';\n qrHtml += '\">';\n qrHtml += '<tbody>';\n \n for (var r = 0; r < _this.getModuleCount(); r += 1) {\n \n qrHtml += '<tr>';\n \n for (var c = 0; c < _this.getModuleCount(); c += 1) {\n qrHtml += '<td style=\"';\n qrHtml += ' border-width: 0px; border-style: none;';\n qrHtml += ' border-collapse: collapse;';\n qrHtml += ' padding: 0px; margin: 0px;';\n qrHtml += ' width: ' + cellSize + 'px;';\n qrHtml += ' height: ' + cellSize + 'px;';\n qrHtml += ' background-color: ';\n qrHtml += _this.isDark(r, c) ? '#000000' : '#ffffff';\n qrHtml += ';';\n qrHtml += '\"/>';\n }\n \n qrHtml += '</tr>';\n }\n \n qrHtml += '</tbody>';\n qrHtml += '</table>';\n \n return qrHtml;\n };\n \n _this.createImgTag = function (cellSize, margin, size) {\n \n cellSize = cellSize || 2;\n margin = (typeof margin == 'undefined') ? cellSize * 4 : margin;\n \n var min = margin;\n var max = _this.getModuleCount() * cellSize + margin;\n \n return createImgTag(size, size, function (x, y) {\n if (min <= x && x < max && min <= y && y < max) {\n var c = Math.floor((x - min) / cellSize);\n var r = Math.floor((y - min) / cellSize);\n return _this.isDark(r, c) ? 0 : 1;\n } else {\n return 1;\n }\n });\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // qrcode.stringToBytes\n //---------------------------------------------------------------------\n \n qrcode.stringToBytes = function (s) {\n var bytes = new Array();\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n bytes.push(c & 0xff);\n }\n return bytes;\n };\n \n //---------------------------------------------------------------------\n // qrcode.createStringToBytes\n //---------------------------------------------------------------------\n \n /**\n * @param unicodeData base64 string of byte array.\n * [16bit Unicode],[16bit Bytes], ...\n * @param numChars\n */\n qrcode.createStringToBytes = function (unicodeData, numChars) {\n \n // create conversion map.\n \n var unicodeMap = function () {\n \n var bin = base64DecodeInputStream(unicodeData);\n var read = function () {\n var b = bin.read();\n if (b == -1) throw new Error();\n return b;\n };\n \n var count = 0;\n var unicodeMap = {};\n while (true) {\n var b0 = bin.read();\n if (b0 == -1) break;\n var b1 = read();\n var b2 = read();\n var b3 = read();\n var k = String.fromCharCode((b0 << 8) | b1);\n var v = (b2 << 8) | b3;\n unicodeMap[k] = v;\n count += 1;\n }\n if (count != numChars) {\n throw new Error(count + ' != ' + numChars);\n }\n \n return unicodeMap;\n }();\n \n var unknownChar = '?'.charCodeAt(0);\n \n return function (s) {\n var bytes = new Array();\n for (var i = 0; i < s.length; i += 1) {\n var c = s.charCodeAt(i);\n if (c < 128) {\n bytes.push(c);\n } else {\n var b = unicodeMap[s.charAt(i)];\n if (typeof b == 'number') {\n if ((b & 0xff) == b) {\n // 1byte\n bytes.push(b);\n } else {\n // 2bytes\n bytes.push(b >>> 8);\n bytes.push(b & 0xff);\n }\n } else {\n bytes.push(unknownChar);\n }\n }\n }\n return bytes;\n };\n };\n \n //---------------------------------------------------------------------\n // QRMode\n //---------------------------------------------------------------------\n \n var QRMode = {\n MODE_NUMBER: 1 << 0,\n MODE_ALPHA_NUM: 1 << 1,\n MODE_8BIT_BYTE: 1 << 2,\n MODE_KANJI: 1 << 3\n };\n \n //---------------------------------------------------------------------\n // QRErrorCorrectLevel\n //---------------------------------------------------------------------\n \n var QRErrorCorrectLevel = {\n L: 1,\n M: 0,\n Q: 3,\n H: 2\n };\n \n //---------------------------------------------------------------------\n // QRMaskPattern\n //---------------------------------------------------------------------\n \n var QRMaskPattern = {\n PATTERN000: 0,\n PATTERN001: 1,\n PATTERN010: 2,\n PATTERN011: 3,\n PATTERN100: 4,\n PATTERN101: 5,\n PATTERN110: 6,\n PATTERN111: 7\n };\n \n //---------------------------------------------------------------------\n // QRUtil\n //---------------------------------------------------------------------\n \n var QRUtil = function () {\n \n var PATTERN_POSITION_TABLE = [\n [],\n [6, 18],\n [6, 22],\n [6, 26],\n [6, 30],\n [6, 34],\n [6, 22, 38],\n [6, 24, 42],\n [6, 26, 46],\n [6, 28, 50],\n [6, 30, 54],\n [6, 32, 58],\n [6, 34, 62],\n [6, 26, 46, 66],\n [6, 26, 48, 70],\n [6, 26, 50, 74],\n [6, 30, 54, 78],\n [6, 30, 56, 82],\n [6, 30, 58, 86],\n [6, 34, 62, 90],\n [6, 28, 50, 72, 94],\n [6, 26, 50, 74, 98],\n [6, 30, 54, 78, 102],\n [6, 28, 54, 80, 106],\n [6, 32, 58, 84, 110],\n [6, 30, 58, 86, 114],\n [6, 34, 62, 90, 118],\n [6, 26, 50, 74, 98, 122],\n [6, 30, 54, 78, 102, 126],\n [6, 26, 52, 78, 104, 130],\n [6, 30, 56, 82, 108, 134],\n [6, 34, 60, 86, 112, 138],\n [6, 30, 58, 86, 114, 142],\n [6, 34, 62, 90, 118, 146],\n [6, 30, 54, 78, 102, 126, 150],\n [6, 24, 50, 76, 102, 128, 154],\n [6, 28, 54, 80, 106, 132, 158],\n [6, 32, 58, 84, 110, 136, 162],\n [6, 26, 54, 82, 110, 138, 166],\n [6, 30, 58, 86, 114, 142, 170]\n ];\n var G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0);\n var G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0);\n var G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1);\n \n var _this = {};\n \n var getBCHDigit = function (data) {\n var digit = 0;\n while (data != 0) {\n digit += 1;\n data >>>= 1;\n }\n return digit;\n };\n \n _this.getBCHTypeInfo = function (data) {\n var d = data << 10;\n while (getBCHDigit(d) - getBCHDigit(G15) >= 0) {\n d ^= (G15 << (getBCHDigit(d) - getBCHDigit(G15)));\n }\n return ((data << 10) | d) ^ G15_MASK;\n };\n \n _this.getBCHTypeNumber = function (data) {\n var d = data << 12;\n while (getBCHDigit(d) - getBCHDigit(G18) >= 0) {\n d ^= (G18 << (getBCHDigit(d) - getBCHDigit(G18)));\n }\n return (data << 12) | d;\n };\n \n _this.getPatternPosition = function (typeNumber) {\n return PATTERN_POSITION_TABLE[typeNumber - 1];\n };\n \n _this.getMaskFunction = function (maskPattern) {\n \n switch (maskPattern) {\n \n case QRMaskPattern.PATTERN000:\n return function (i, j) { return (i + j) % 2 == 0; };\n case QRMaskPattern.PATTERN001:\n return function (i, j) { return i % 2 == 0; };\n case QRMaskPattern.PATTERN010:\n return function (i, j) { return j % 3 == 0; };\n case QRMaskPattern.PATTERN011:\n return function (i, j) { return (i + j) % 3 == 0; };\n case QRMaskPattern.PATTERN100:\n return function (i, j) { return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 == 0; };\n case QRMaskPattern.PATTERN101:\n return function (i, j) { return (i * j) % 2 + (i * j) % 3 == 0; };\n case QRMaskPattern.PATTERN110:\n return function (i, j) { return ((i * j) % 2 + (i * j) % 3) % 2 == 0; };\n case QRMaskPattern.PATTERN111:\n return function (i, j) { return ((i * j) % 3 + (i + j) % 2) % 2 == 0; };\n \n default:\n throw new Error('bad maskPattern:' + maskPattern);\n }\n };\n \n _this.getErrorCorrectPolynomial = function (errorCorrectLength) {\n var a = qrPolynomial([1], 0);\n for (var i = 0; i < errorCorrectLength; i += 1) {\n a = a.multiply(qrPolynomial([1, QRMath.gexp(i)], 0));\n }\n return a;\n };\n \n _this.getLengthInBits = function (mode, type) {\n \n if (1 <= type && type < 10) {\n \n // 1 - 9\n \n switch (mode) {\n case QRMode.MODE_NUMBER: return 10;\n case QRMode.MODE_ALPHA_NUM: return 9;\n case QRMode.MODE_8BIT_BYTE: return 8;\n case QRMode.MODE_KANJI: return 8;\n default:\n throw new Error('mode:' + mode);\n }\n \n } else if (type < 27) {\n \n // 10 - 26\n \n switch (mode) {\n case QRMode.MODE_NUMBER: return 12;\n case QRMode.MODE_ALPHA_NUM: return 11;\n case QRMode.MODE_8BIT_BYTE: return 16;\n case QRMode.MODE_KANJI: return 10;\n default:\n throw new Error('mode:' + mode);\n }\n \n } else if (type < 41) {\n \n // 27 - 40\n \n switch (mode) {\n case QRMode.MODE_NUMBER: return 14;\n case QRMode.MODE_ALPHA_NUM: return 13;\n case QRMode.MODE_8BIT_BYTE: return 16;\n case QRMode.MODE_KANJI: return 12;\n default:\n throw new Error('mode:' + mode);\n }\n \n } else {\n throw new Error('type:' + type);\n }\n };\n \n _this.getLostPoint = function (qrcode) {\n \n var moduleCount = qrcode.getModuleCount();\n \n var lostPoint = 0;\n \n // LEVEL1\n \n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount; col += 1) {\n \n var sameCount = 0;\n var dark = qrcode.isDark(row, col);\n \n for (var r = -1; r <= 1; r += 1) {\n \n if (row + r < 0 || moduleCount <= row + r) {\n continue;\n }\n \n for (var c = -1; c <= 1; c += 1) {\n \n if (col + c < 0 || moduleCount <= col + c) {\n continue;\n }\n \n if (r == 0 && c == 0) {\n continue;\n }\n \n if (dark == qrcode.isDark(row + r, col + c)) {\n sameCount += 1;\n }\n }\n }\n \n if (sameCount > 5) {\n lostPoint += (3 + sameCount - 5);\n }\n }\n };\n \n // LEVEL2\n \n for (var row = 0; row < moduleCount - 1; row += 1) {\n for (var col = 0; col < moduleCount - 1; col += 1) {\n var count = 0;\n if (qrcode.isDark(row, col)) count += 1;\n if (qrcode.isDark(row + 1, col)) count += 1;\n if (qrcode.isDark(row, col + 1)) count += 1;\n if (qrcode.isDark(row + 1, col + 1)) count += 1;\n if (count == 0 || count == 4) {\n lostPoint += 3;\n }\n }\n }\n \n // LEVEL3\n \n for (var row = 0; row < moduleCount; row += 1) {\n for (var col = 0; col < moduleCount - 6; col += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row, col + 1)\n && qrcode.isDark(row, col + 2)\n && qrcode.isDark(row, col + 3)\n && qrcode.isDark(row, col + 4)\n && !qrcode.isDark(row, col + 5)\n && qrcode.isDark(row, col + 6)) {\n lostPoint += 40;\n }\n }\n }\n \n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount - 6; row += 1) {\n if (qrcode.isDark(row, col)\n && !qrcode.isDark(row + 1, col)\n && qrcode.isDark(row + 2, col)\n && qrcode.isDark(row + 3, col)\n && qrcode.isDark(row + 4, col)\n && !qrcode.isDark(row + 5, col)\n && qrcode.isDark(row + 6, col)) {\n lostPoint += 40;\n }\n }\n }\n \n // LEVEL4\n \n var darkCount = 0;\n \n for (var col = 0; col < moduleCount; col += 1) {\n for (var row = 0; row < moduleCount; row += 1) {\n if (qrcode.isDark(row, col)) {\n darkCount += 1;\n }\n }\n }\n \n var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;\n lostPoint += ratio * 10;\n \n return lostPoint;\n };\n \n return _this;\n }();\n \n //---------------------------------------------------------------------\n // QRMath\n //---------------------------------------------------------------------\n \n var QRMath = function () {\n \n var EXP_TABLE = new Array(256);\n var LOG_TABLE = new Array(256);\n \n // initialize tables\n for (var i = 0; i < 8; i += 1) {\n EXP_TABLE[i] = 1 << i;\n }\n for (var i = 8; i < 256; i += 1) {\n EXP_TABLE[i] = EXP_TABLE[i - 4]\n ^ EXP_TABLE[i - 5]\n ^ EXP_TABLE[i - 6]\n ^ EXP_TABLE[i - 8];\n }\n for (var i = 0; i < 255; i += 1) {\n LOG_TABLE[EXP_TABLE[i]] = i;\n }\n \n var _this = {};\n \n _this.glog = function (n) {\n \n if (n < 1) {\n throw new Error('glog(' + n + ')');\n }\n \n return LOG_TABLE[n];\n };\n \n _this.gexp = function (n) {\n \n while (n < 0) {\n n += 255;\n }\n \n while (n >= 256) {\n n -= 255;\n }\n \n return EXP_TABLE[n];\n };\n \n return _this;\n }();\n \n //---------------------------------------------------------------------\n // qrPolynomial\n //---------------------------------------------------------------------\n \n function qrPolynomial(num, shift) {\n \n if (typeof num.length == 'undefined') {\n throw new Error(num.length + '/' + shift);\n }\n \n var _num = function () {\n var offset = 0;\n while (offset < num.length && num[offset] == 0) {\n offset += 1;\n }\n var _num = new Array(num.length - offset + shift);\n for (var i = 0; i < num.length - offset; i += 1) {\n _num[i] = num[i + offset];\n }\n return _num;\n }();\n \n var _this = {};\n \n _this.getAt = function (index) {\n return _num[index];\n };\n \n _this.getLength = function () {\n return _num.length;\n };\n \n _this.multiply = function (e) {\n \n var num = new Array(_this.getLength() + e.getLength() - 1);\n \n for (var i = 0; i < _this.getLength(); i += 1) {\n for (var j = 0; j < e.getLength(); j += 1) {\n num[i + j] ^= QRMath.gexp(QRMath.glog(_this.getAt(i)) + QRMath.glog(e.getAt(j)));\n }\n }\n \n return qrPolynomial(num, 0);\n };\n \n _this.mod = function (e) {\n \n if (_this.getLength() - e.getLength() < 0) {\n return _this;\n }\n \n var ratio = QRMath.glog(_this.getAt(0)) - QRMath.glog(e.getAt(0));\n \n var num = new Array(_this.getLength());\n for (var i = 0; i < _this.getLength(); i += 1) {\n num[i] = _this.getAt(i);\n }\n \n for (var i = 0; i < e.getLength(); i += 1) {\n num[i] ^= QRMath.gexp(QRMath.glog(e.getAt(i)) + ratio);\n }\n \n // recursive call\n return qrPolynomial(num, 0).mod(e);\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // QRRSBlock\n //---------------------------------------------------------------------\n \n var QRRSBlock = function () {\n \n \n // [1: [L, M, Q, H], ..]\n 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]];\n \n var qrRSBlock = function (totalCount, dataCount) {\n var _this = {};\n _this.totalCount = totalCount;\n _this.dataCount = dataCount;\n return _this;\n };\n \n var _this = {};\n \n var getRsBlockTable = function (typeNumber, errorCorrectLevel) {\n \n switch (errorCorrectLevel) {\n case QRErrorCorrectLevel.L:\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];\n case QRErrorCorrectLevel.M:\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];\n case QRErrorCorrectLevel.Q:\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];\n case QRErrorCorrectLevel.H:\n return RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];\n default:\n return undefined;\n }\n };\n \n _this.getRSBlocks = function (typeNumber, errorCorrectLevel) {\n \n var rsBlock = getRsBlockTable(typeNumber, errorCorrectLevel);\n \n if (typeof rsBlock == 'undefined') {\n throw new Error('bad rs block @ typeNumber:' + typeNumber +\n '/errorCorrectLevel:' + errorCorrectLevel);\n }\n \n var length = rsBlock.length / 3;\n \n var list = new Array();\n \n for (var i = 0; i < length; i += 1) {\n \n var count = rsBlock[i * 3 + 0];\n var totalCount = rsBlock[i * 3 + 1];\n var dataCount = rsBlock[i * 3 + 2];\n \n for (var j = 0; j < count; j += 1) {\n list.push(qrRSBlock(totalCount, dataCount));\n }\n }\n \n return list;\n };\n \n return _this;\n }();\n \n //---------------------------------------------------------------------\n // qrBitBuffer\n //---------------------------------------------------------------------\n \n var qrBitBuffer = function () {\n \n var _buffer = new Array();\n var _length = 0;\n \n var _this = {};\n \n _this.getBuffer = function () {\n return _buffer;\n };\n \n _this.getAt = function (index) {\n var bufIndex = Math.floor(index / 8);\n return ((_buffer[bufIndex] >>> (7 - index % 8)) & 1) == 1;\n };\n \n _this.put = function (num, length) {\n for (var i = 0; i < length; i += 1) {\n _this.putBit(((num >>> (length - i - 1)) & 1) == 1);\n }\n };\n \n _this.getLengthInBits = function () {\n return _length;\n };\n \n _this.putBit = function (bit) {\n \n var bufIndex = Math.floor(_length / 8);\n if (_buffer.length <= bufIndex) {\n _buffer.push(0);\n }\n \n if (bit) {\n _buffer[bufIndex] |= (0x80 >>> (_length % 8));\n }\n \n _length += 1;\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // qr8BitByte\n //---------------------------------------------------------------------\n \n var qr8BitByte = function (data) {\n \n var _mode = QRMode.MODE_8BIT_BYTE;\n var _data = data;\n var _parsedData = [];\n \n var _this = {};\n \n \n // Added to support UTF-8 Characters\n for (var i = 0, l = _data.length; i < l; i++) {\n var byteArray = [];\n var code = _data.charCodeAt(i);\n \n if (code > 0x10000) {\n byteArray[0] = 0xF0 | ((code & 0x1C0000) >>> 18);\n byteArray[1] = 0x80 | ((code & 0x3F000) >>> 12);\n byteArray[2] = 0x80 | ((code & 0xFC0) >>> 6);\n byteArray[3] = 0x80 | (code & 0x3F);\n } else if (code > 0x800) {\n byteArray[0] = 0xE0 | ((code & 0xF000) >>> 12);\n byteArray[1] = 0x80 | ((code & 0xFC0) >>> 6);\n byteArray[2] = 0x80 | (code & 0x3F);\n } else if (code > 0x80) {\n byteArray[0] = 0xC0 | ((code & 0x7C0) >>> 6);\n byteArray[1] = 0x80 | (code & 0x3F);\n } else {\n byteArray[0] = code;\n }\n \n // Fix Unicode corruption bug\n _parsedData.push(byteArray);\n }\n \n _parsedData = Array.prototype.concat.apply([], _parsedData);\n \n if (_parsedData.length != _data.length) {\n _parsedData.unshift(191);\n _parsedData.unshift(187);\n _parsedData.unshift(239);\n }\n \n var _bytes = _parsedData;\n \n _this.getMode = function () {\n return _mode;\n };\n \n _this.getLength = function (buffer) {\n return _bytes.length;\n };\n \n _this.write = function (buffer) {\n for (var i = 0; i < _bytes.length; i += 1) {\n buffer.put(_bytes[i], 8);\n }\n };\n \n return _this;\n };\n \n //=====================================================================\n // GIF Support etc.\n //\n \n //---------------------------------------------------------------------\n // byteArrayOutputStream\n //---------------------------------------------------------------------\n \n var byteArrayOutputStream = function () {\n \n var _bytes = new Array();\n \n var _this = {};\n \n _this.writeByte = function (b) {\n _bytes.push(b & 0xff);\n };\n \n _this.writeShort = function (i) {\n _this.writeByte(i);\n _this.writeByte(i >>> 8);\n };\n \n _this.writeBytes = function (b, off, len) {\n off = off || 0;\n len = len || b.length;\n for (var i = 0; i < len; i += 1) {\n _this.writeByte(b[i + off]);\n }\n };\n \n _this.writeString = function (s) {\n for (var i = 0; i < s.length; i += 1) {\n _this.writeByte(s.charCodeAt(i));\n }\n };\n \n _this.toByteArray = function () {\n return _bytes;\n };\n \n _this.toString = function () {\n var s = '';\n s += '[';\n for (var i = 0; i < _bytes.length; i += 1) {\n if (i > 0) {\n s += ',';\n }\n s += _bytes[i];\n }\n s += ']';\n return s;\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // base64EncodeOutputStream\n //---------------------------------------------------------------------\n \n var base64EncodeOutputStream = function () {\n \n var _buffer = 0;\n var _buflen = 0;\n var _length = 0;\n var _base64 = '';\n \n var _this = {};\n \n var writeEncoded = function (b) {\n _base64 += String.fromCharCode(encode(b & 0x3f));\n };\n \n var encode = function (n) {\n if (n < 0) {\n // error.\n } else if (n < 26) {\n return 0x41 + n;\n } else if (n < 52) {\n return 0x61 + (n - 26);\n } else if (n < 62) {\n return 0x30 + (n - 52);\n } else if (n == 62) {\n return 0x2b;\n } else if (n == 63) {\n return 0x2f;\n }\n throw new Error('n:' + n);\n };\n \n _this.writeByte = function (n) {\n \n _buffer = (_buffer << 8) | (n & 0xff);\n _buflen += 8;\n _length += 1;\n \n while (_buflen >= 6) {\n writeEncoded(_buffer >>> (_buflen - 6));\n _buflen -= 6;\n }\n };\n \n _this.flush = function () {\n \n if (_buflen > 0) {\n writeEncoded(_buffer << (6 - _buflen));\n _buffer = 0;\n _buflen = 0;\n }\n \n if (_length % 3 != 0) {\n // padding\n var padlen = 3 - _length % 3;\n for (var i = 0; i < padlen; i += 1) {\n _base64 += '=';\n }\n }\n };\n \n _this.toString = function () {\n return _base64;\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // base64DecodeInputStream\n //---------------------------------------------------------------------\n \n var base64DecodeInputStream = function (str) {\n \n var _str = str;\n var _pos = 0;\n var _buffer = 0;\n var _buflen = 0;\n \n var _this = {};\n \n _this.read = function () {\n \n while (_buflen < 8) {\n \n if (_pos >= _str.length) {\n if (_buflen == 0) {\n return -1;\n }\n throw new Error('unexpected end of file./' + _buflen);\n }\n \n var c = _str.charAt(_pos);\n _pos += 1;\n \n if (c == '=') {\n _buflen = 0;\n return -1;\n } else if (c.match(/^\\s$/)) {\n // ignore if whitespace.\n continue;\n }\n \n _buffer = (_buffer << 6) | decode(c.charCodeAt(0));\n _buflen += 6;\n }\n \n var n = (_buffer >>> (_buflen - 8)) & 0xff;\n _buflen -= 8;\n return n;\n };\n \n var decode = function (c) {\n if (0x41 <= c && c <= 0x5a) {\n return c - 0x41;\n } else if (0x61 <= c && c <= 0x7a) {\n return c - 0x61 + 26;\n } else if (0x30 <= c && c <= 0x39) {\n return c - 0x30 + 52;\n } else if (c == 0x2b) {\n return 62;\n } else if (c == 0x2f) {\n return 63;\n } else {\n throw new Error('c:' + c);\n }\n };\n \n return _this;\n };\n \n //---------------------------------------------------------------------\n // gifImage (B/W)\n //---------------------------------------------------------------------\n \n var gifImage = function (width, height) {\n \n var _width = width;\n var _height = height;\n var _data = new Array(width * height);\n \n var _this = {};\n \n _this.setPixel = function (x, y, pixel) {\n _data[y * _width + x] = pixel;\n };\n \n _this.write = function (out) {\n \n //---------------------------------\n // GIF Signature\n \n out.writeString('GIF87a');\n \n //---------------------------------\n // Screen Descriptor\n \n out.writeShort(_width);\n out.writeShort(_height);\n \n out.writeByte(0x80); // 2bit\n out.writeByte(0);\n out.writeByte(0);\n \n //---------------------------------\n // Global Color Map\n \n // black\n for (var i = 0; i < 3; i++) {\n out.writeByte(globalConfig.colors[i] || 0x00);\n }\n \n // white\n for (var i = 0; i < 3; i++) {\n var color = globalConfig.backgrounds[i] === 0 ? 0 : (globalConfig.backgrounds[i] || 0xff)\n out.writeByte(color);\n }\n // out.writeByte(0xff);\n // out.writeByte(0xff);\n // out.writeByte(0xff);\n \n //---------------------------------\n // Image Descriptor\n \n out.writeString(',');\n out.writeShort(0);\n out.writeShort(0);\n out.writeShort(_width);\n out.writeShort(_height);\n out.writeByte(0);\n \n //---------------------------------\n // Local Color Map\n \n //---------------------------------\n // Raster Data\n \n var lzwMinCodeSize = 2;\n var raster = getLZWRaster(lzwMinCodeSize);\n \n out.writeByte(lzwMinCodeSize);\n \n var offset = 0;\n \n while (raster.length - offset > 255) {\n out.writeByte(255);\n out.writeBytes(raster, offset, 255);\n offset += 255;\n }\n \n out.writeByte(raster.length - offset);\n out.writeBytes(raster, offset, raster.length - offset);\n out.writeByte(0x00);\n \n //---------------------------------\n // GIF Terminator\n out.writeString(';');\n };\n \n var bitOutputStream = function (out) {\n \n var _out = out;\n var _bitLength = 0;\n var _bitBuffer = 0;\n \n var _this = {};\n \n _this.write = function (data, length) {\n \n if ((data >>> length) != 0) {\n throw new Error('length over');\n }\n \n while (_bitLength + length >= 8) {\n _out.writeByte(0xff & ((data << _bitLength) | _bitBuffer));\n length -= (8 - _bitLength);\n data >>>= (8 - _bitLength);\n _bitBuffer = 0;\n _bitLength = 0;\n }\n \n _bitBuffer = (data << _bitLength) | _bitBuffer;\n _bitLength = _bitLength + length;\n };\n \n _this.flush = function () {\n if (_bitLength > 0) {\n _out.writeByte(_bitBuffer);\n }\n };\n \n return _this;\n };\n \n var getLZWRaster = function (lzwMinCodeSize) {\n \n var clearCode = 1 << lzwMinCodeSize;\n var endCode = (1 << lzwMinCodeSize) + 1;\n var bitLength = lzwMinCodeSize + 1;\n \n // Setup LZWTable\n var table = lzwTable();\n \n for (var i = 0; i < clearCode; i += 1) {\n table.add(String.fromCharCode(i));\n }\n table.add(String.fromCharCode(clearCode));\n table.add(String.fromCharCode(endCode));\n \n var byteOut = byteArrayOutputStream();\n var bitOut = bitOutputStream(byteOut);\n \n // clear code\n bitOut.write(clearCode, bitLength);\n \n var dataIndex = 0;\n \n var s = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n \n while (dataIndex < _data.length) {\n \n var c = String.fromCharCode(_data[dataIndex]);\n dataIndex += 1;\n \n if (table.contains(s + c)) {\n \n s = s + c;\n \n } else {\n \n bitOut.write(table.indexOf(s), bitLength);\n \n if (table.size() < 0xfff) {\n \n if (table.size() == (1 << bitLength)) {\n bitLength += 1;\n }\n \n table.add(s + c);\n }\n \n s = c;\n }\n }\n \n bitOut.write(table.indexOf(s), bitLength);\n \n // end code\n bitOut.write(endCode, bitLength);\n \n bitOut.flush();\n \n return byteOut.toByteArray();\n };\n \n var lzwTable = function () {\n \n var _map = {};\n var _size = 0;\n \n var _this = {};\n \n _this.add = function (key) {\n if (_this.contains(key)) {\n throw new Error('dup key:' + key);\n }\n _map[key] = _size;\n _size += 1;\n };\n \n _this.size = function () {\n return _size;\n };\n \n _this.indexOf = function (key) {\n return _map[key];\n };\n \n _this.contains = function (key) {\n return typeof _map[key] != 'undefined';\n };\n \n return _this;\n };\n \n return _this;\n };\n \n var createImgTag = function (width, height, getPixel, alt) {\n \n var gif = gifImage(width, height);\n for (var y = 0; y < height; y += 1) {\n for (var x = 0; x < width; x += 1) {\n gif.setPixel(x, y, getPixel(x, y));\n }\n }\n \n var b = byteArrayOutputStream();\n gif.write(b);\n \n var base64 = base64EncodeOutputStream();\n var bytes = b.toByteArray();\n for (var i = 0; i < bytes.length; i += 1) {\n base64.writeByte(bytes[i]);\n }\n base64.flush();\n \n var img = '';\n img += 'data:image/png;base64,';\n img += base64;\n \n return img;\n };\n \n var color2hexs = function (colorString) {\n var color = [], rgb = [], hex;\n if (colorString.startsWith('#')) {\n hex = colorString.replace(/#/, \"\");\n if (hex.length == 3) { // 处理 \"#abc\" 成 \"#aabbcc\"\n var tmp = [];\n for (var i = 0; i < 3; i++) {\n tmp.push(hex.charAt(i) + hex.charAt(i));\n }\n hex = tmp.join(\"\");\n }\n \n for (var i = 0; i < 3; i++) {\n color[i] = \"0x\" + hex.substr(i * 2, 2);\n rgb.push(parseInt(Number(color[i])));\n }\n } else if (colorString.startsWith('rgb')) {\n rgb = colorString.toString().match(/\\d+/g);\n }\n return rgb;\n }\n //---------------------------------------------------------------------\n // returns qrcode function.\n \n var drawImg = function (text, options) {\n options = options || {};\n var typeNumber = options.version || 4;\n var errorCorrectLevel = options.errorCorrectLevel || 'M';\n var size = options.size || 500;\n globalConfig.colors = color2hexs(options.color || '#000')\n globalConfig.backgrounds = color2hexs(options.background || '#fff')\n var padding = options.padding || 0\n var qr;\n \n try {\n qr = qrcode(typeNumber, errorCorrectLevel || 'M');\n qr.addData(text);\n qr.make();\n } catch (e) {\n if (typeNumber > 40) {\n throw new Error('Text too long to encode. Necessary type required: ' + typeNumber);\n } else {\n return drawImg(text, {\n size: size,\n errorCorrectLevel: errorCorrectLevel,\n version: typeNumber + 1,\n color: options.color,\n background: options.background,\n padding: options.padding\n });\n }\n }\n \n // calc cellsize and margin\n var cellsize = ((size) / (qr.getModuleCount() + 2 * padding));\n return qr.createImgTag(cellsize, padding * cellsize, size);\n };\n module.exports = {\n drawImg: drawImg\n };\n\n\n/*\n *\n * Code below adapted from \"Load Image from URL\" Example\n * \n*/\n\nconst object = eventsFunctionContext.getArgument(\"SpriteName\");\nconst resourceName = \"GENERATED_QR_CODE_FOR_\" + object;\nconst anim = 0;\n\n// Generate QR Code\nconst base64URI = drawImg(eventsFunctionContext.getArgument(\"InputString\"), {\n version: eventsFunctionContext.getArgument(\"version\"),\n errorCorrectLevel: eventsFunctionContext.getArgument(\"errorCorrectLevel\"),\n color: '#3d0d83',\n background: '#fff',\n padding: 1,\n size: eventsFunctionContext.getArgument(\"size\")\n})\n\nruntimeScene.myCallback = function(loader, resources){ // loader and ressources come from PIXI.Loader.shared\n var mySprite= resources[resourceName]; //get the image from PIXI ressources\n var game = runtimeScene.getGame(); //get the game currently running\n var object_texture_image = runtimeScene.getObjects(object);\n var object_texture_image_renderer = object_texture_image[anim].getRendererObject(); // get the renderer (PIXI sprite)\n object_texture_image_renderer.texture = mySprite.texture; // change the texture in renderer (PIXI sprite)\n};\n\nPIXI.Loader.shared.reset(); // Vestigal?\nPIXI.Loader.shared.add(resourceName, base64URI); // Load data from base64 data URL\nPIXI.Loader.shared.load(runtimeScene.myCallback); // Use callback for load the new image\n\n", | |
"parameterObjects": "", | |
"useStrict": true, | |
"eventsSheetExpanded": false | |
} | |
], | |
"parameters": [ | |
{ | |
"codeOnly": false, | |
"defaultValue": "", | |
"description": "The string of data to generate QR Code from", | |
"longDescription": "", | |
"name": "InputString", | |
"optional": false, | |
"supplementaryInformation": "", | |
"type": "string" | |
}, | |
{ | |
"codeOnly": false, | |
"defaultValue": "", | |
"description": "The name of the Sprite object to replace with QR Code image", | |
"longDescription": "", | |
"name": "SpriteName", | |
"optional": false, | |
"supplementaryInformation": "", | |
"type": "string" | |
}, | |
{ | |
"codeOnly": false, | |
"defaultValue": "", | |
"description": "QR Code Version (1-40) [higher for the more data]", | |
"longDescription": "", | |
"name": "version", | |
"optional": false, | |
"supplementaryInformation": "", | |
"type": "expression" | |
}, | |
{ | |
"codeOnly": false, | |
"defaultValue": "", | |
"description": "QR Code Error Correction Level (L < M < Q < H)", | |
"longDescription": "", | |
"name": "errorCorrectLevel", | |
"optional": false, | |
"supplementaryInformation": "[\"L\",\"M\",\"Q\",\"H\"]", | |
"type": "stringWithSelector" | |
}, | |
{ | |
"codeOnly": false, | |
"defaultValue": "", | |
"description": "The length and width of the square image generated for this QR code", | |
"longDescription": "", | |
"name": "size", | |
"optional": false, | |
"supplementaryInformation": "", | |
"type": "expression" | |
} | |
], | |
"objectGroups": [] | |
} | |
], | |
"eventsBasedBehaviors": [] | |
} |
I would wager a guess it's due to CORs or XSS or whatever web security browsers use these days to prevent fetching and executing code from other sites.On Jan 6, 2023, at 10:27 PM, scooter42 ***@***.***> wrote:Re: ***@***.*** commented on this gist.any reason why the QR code extension works on the local test but not the HTML export?—Reply to this email directly, view it on GitHub or unsubscribe.You are receiving this email because you authored the thread.Triage notifications on the go with GitHub Mobile for iOS or Android.
I didn't see in your script where it was fetching from another site though.
Just passed it a string to convert to QR was all.
…On Fri, Jan 6, 2023 at 11:21 PM krunkster ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
I would wager a guess it's due to CORs or XSS or whatever web security
browsers use these days to prevent fetching and executing code from other
sites.On Jan 6, 2023, at 10:27 PM, scooter42 ***@***.***> wrote:Re:
***@***.*** commented on this gist.any reason why the QR code extension
works on the local test but not the HTML export?—Reply to this email
directly, view it on GitHub or unsubscribe.You are receiving this email
because you authored the thread.Triage notifications on the go with GitHub
Mobile for iOS or Android.
—
Reply to this email directly, view it on GitHub
<https://gist.github.com/81402ce230990eeee9f342f4b194a4a1#gistcomment-4427767>
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AC6NI6YWJARFDZCZXB4PXGTWREKQHBFKMF2HI4TJMJ2XIZLTSKBKK5TBNR2WLJDHNFZXJJDOMFWWLK3UNBZGKYLEL52HS4DFQKSXMYLMOVS2I5DSOVS2I3TBNVS3W5DIOJSWCZC7OBQXE5DJMNUXAYLOORPWCY3UNF3GS5DZVRZXKYTKMVRXIX3UPFYGLK2HNFZXIQ3PNVWWK3TUUZ2G64DJMNZZDAVEOR4XAZNEM5UXG5FFOZQWY5LFVEYTCNRQGA4DEOBSU52HE2LHM5SXFJTDOJSWC5DF>
.
You are receiving this email because you commented on the thread.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
--
Scott Jacobson
https://jnoodle.com/games
https://twitter.com/jacobson42
*the most natural thing would be for nothing to exist at all*
The issue is because you copy pasted the library verbatim, without looking at the code. At the end, there is a node-style export (module.export = {}
), which works on a node/electron environment like GDevelop, but will crash in JS strict mode (which events are in by default) as module
is undeclared. I quickly reworked the extension to
- Add color options
- Fix it on exports outside of previews
- Replace your hack with
PIXI.Loader
by just loading the texture directly instead
Thanks once again!
You are 4 for 4!
Genius!
On Sat, Jan 7, 2023 at 9:00 AM Arthur Pacaud ***@***.***> wrote:
***@***.**** commented on this gist.
------------------------------
The issue is because you copy pasted the library verbatim, without looking
at the code. At the end, there is a node-style export (module.export = {}),
which works on a node/electron environment like GDevelop, but will crash in
JS strict mode (which events are in by default) as module is undeclared.
I quickly reworked the extension to
- Add color options
- Fix it on exports outside of previews
- Replace your hack with PIXI.Loader by just loading the texture
directly instead
QRtest.zip
<https://github.com/GDevelopApp/GDevelop-extensions/files/10366776/QRtest.zip>
—
Reply to this email directly, view it on GitHub
<https://gist.github.com/81402ce230990eeee9f342f4b194a4a1#gistcomment-4428492>
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AC6NI67YI6554ST6N5REMKLWRGOK7BFKMF2HI4TJMJ2XIZLTSKBKK5TBNR2WLJDHNFZXJJDOMFWWLK3UNBZGKYLEL52HS4DFQKSXMYLMOVS2I5DSOVS2I3TBNVS3W5DIOJSWCZC7OBQXE5DJMNUXAYLOORPWCY3UNF3GS5DZVRZXKYTKMVRXIX3UPFYGLK2HNFZXIQ3PNVWWK3TUUZ2G64DJMNZZDAVEOR4XAZNEM5UXG5FFOZQWY5LFVEYTCNRQGA4DEOBSU52HE2LHM5SXFJTDOJSWC5DF>
.
You are receiving this email because you commented on the thread.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>
.
--
Scott Jacobson
https://jnoodle.com/games
https://twitter.com/jacobson42
*the most natural thing would be for nothing to exist at all*
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
any reason why the QR code extension works on the local test but not the HTML export?